tanaka's Programming Memo

プログラミングについてのメモ。

GAMEJAMで作ったイノシシのギミックの作り方

この記事は Cluster Creator #1 Advent Calendar 2022 の6日目の記事です。

adventar.org

◆前の日は Sha-la /歌詠しゃら🧸Vシンガー🌷本垢凍結で一時避難中。 さんの clusterで音楽イベントを開いてみたいアーティストの方へ。

◆次の日は さな さんの 会話ロボ in cluster です。


先日開催されたCluster GAMEJAM 2022 in AUTUMNに参加しました。三回目にして初空振りだったと思ってたのですが(毎回自主トレやにぎやかし目的で参加してるので空振りでいいんですけど)、奨励賞をいただけてました!!手広く色々な賞を用意してくださっていて参加して楽しいゲームジャムです。

奨励賞!!

GAMEJAMでは前回の春の時は「天翔ける腕輪」で空飛ぶ腕輪とクマ。

cluster.mu

今回は「イノシシ★ダッシュ!!」で直進しかできないイノシシを作りました。

cluster.mu

Cluster Creator Kitを使えば様々な仕掛けが作れます。公式のテンプレートワールドはどのようなことができるのかや実装テクニックを知ることができる宝の山です。 上記の乗り物もテンプレートワールドのHorseをもとに作りました。この記事ではHorseを観察しながら機能を理解して、イノシシに改造するまでをご紹介します。 Cluster Creator Kit(以降、CCK)を使えるようにするための一助になれば幸いです。

目次

動作環境

  • Unity2021.3.4f1
  • 2022/12/1現在のCCKとCluster

乗り物作りの環境構築

自由にいじりまわせるUnityプロジェクトを作成して、そこに公式のテンプレートワールドを読み込みます(サンプルプロジェクトではありません)。以下の公式サイトの「すぐにワールド制作したい──テンプレートワールドを導入する」を参考にテンプレートワールドをUnityで開いてください。

creator.cluster.mu

テンプレートワールドは、「プロジェクトに含まれるアセットは cluster にアップロードする場合には、すべてクレジット表示不要で自由に使う」ことができるとても有難いものです。活用しない手はありません。

ダウンロードしたClusterCreatorKitTemplate-master.zipを展開して、フォルダーの名前を変更すれば(例えばNorimonoRensyuなど)複数のテンプレートワールドのプロジェクトを扱えるので便利です。

テンプレートワールドをUnityで開いたら以下のガイドに進みます。

creator.cluster.mu

「テンプレートワールド『乗り物』について」を参考にVehicleシーンを開きます。Playして用意されている乗り物を乗り回してみてください。ぱっと思い浮かぶ乗り物は一通り揃っていると思います。使えるようならそのまま利用してもいいですし、仕組みを観察すればCCKの活用方法を学ぶことができます。

イノシシの能力

イノシシは以下のようにします。

  • スペースキーで一定速度まで加速
  • スペースキーを離すと急停止
  • 加減速は着地時のみ
  • 左右旋回はできない

秋のゲームジャムでは上キーで等速で前進させていましたが、せっかくなのでイノシシらしく(?)加速させたいと思います。

既存の乗り物を観察する

一通り乗り物に乗ってみてイノシシに近いのはHorseなのでこれをベースにします。

Horseの階層

階層はこんな感じです。

Horseの階層

  • Horse...Character Controllerやトリガーなどの制御系のコンポーネントで構成
    • Horse...ウマのモデルオブジェクト。アニメもここ。grip_Lとgrip_Rが手の位置
    • Seat...腰掛ける位置を表すオブジェクト
    • Exit...降りた時の位置を表すオブジェクト
    • Sounds...乗り(GetOnSound)降り(GetOffSound)、着地(LandSound)を鳴らすためのオブジェクト

動きに関するコンポーネントを親オブジェクトにまとめて、モデルデータが子になっています。モデルの差し替えがしやすいUnityのオススメ構造になっていて助かります。

Horseのコンポーネント

ご覧の通りなかなかの量ですが頑張って確認していきます。

Horseのコンポーネント

Character Controllerで動くキャラクタの設定

Character Controllerで動くキャラクタの設定

Character Controllerで制御するキャラクターにするためのコンポーネントです。 パラメータは殆どなく、着地位置や当たる範囲を調整したい時にCharacter Controllerをいじるぐらいです。

乗り物の設定と旋回、移動

乗り物の設定と旋回、移動

Ridable Itemで乗り降りや腰掛ける位置、手の位置、下りる位置、乗った時のアニメを設定できます。

Steer Item Triggerは乗り物の操作入力のためのトリガーで、前後左右操作に加えて、スペースキーなどのAdditionalキーに変化があった時のシグナルと、入力値をトリガーとして送信することができます。

Set Angular Velocity Character ItemGimmickは操作入力で旋回させるギミック、Set Velocity Character Item Gimmickは同様に移動させるギミックです。

間に挟まってるItem Logicは移動を前後に制限するためのものです。入力したmoveInputをそのまま速度に設定すると左右キーでHorseが横移動してしまいます。Item Logicで上下入力だけmove.yに設定することで左右キーの影響を除外しています。

着地とジャンプ

着地とジャンプ

Horseで一番参考になったのがこの辺りでした。着地を確認するIs Grounded Character Item Triggerですが、地面のわずかなデコボコの影響で一瞬だけ空中にいると判定されることがしばしば発生します。そのまま使うとジャンプボタンを押してもジャンプしないことが頻発して操作性が落ちてしまいます。

そこで下から3番目の位置にあるItem Timerを使って、空中にいるかを表すisInAirへの着地状態の反映を0.15秒遅らせる仕組みになっています。ジャンプできるかどうかはisInAirがfalseかどうかで判定しているので、空中に浮いても0.15秒間はジャンプ可能で、その間に着地すれば空中に浮いていたことはチャラになります。ジャンプ開始時にisInAirをtrueにしているのでこの処理によって連続ジャンプすることもありません。

0.15秒後のチェック時に運悪く空中にいる可能性もありますが、ジャンプができなかったと感じることはないので対策として十分だと思います。

イノシシでも加速は着地時にしたいのでこの処理は活用します。

その他

残りは以下のような処理です。

  • 乗った時の演出のためのシグナル送信
  • 降りた時の演出と操作をリセットするためのシグナル送信
  • オーナーが変わった時に操作をリセットするためのシグナル送信
  • 操作のリセット処理

操作や状態を一括してリセットするItem Logicは便利で、作り方の参考になりました。

イノシシへの改造

Horseの機能は一通り把握できました。改造の方針は以下の通りです。

  • モデルをイノシシに差し替え
  • 前後左右操作、ジャンプは不要なので削除
  • Additionalキー(スペースキー)による加減速
  • 加速は着地時のみ

一つずつ手順をまとめます。

モデルをイノシシに差し替え

イノシシは3月のウクライナアセットバンドルで入手したLowPoly Wild Animalsのものを利用しました。前回のシロクマもこれだったと思います。

assetstore.unity.com

Horseのプレハブを複製してBoarに名前を変更します。SeatとExitの位置をモデルに併せて調整して、左右の手の置き場を表すLeftHandRightHandをモデルに追加しました。

イノシシモデルを設定

アニメーション関連は、HorseのモデルからAnimatorやギミックを手作業で移植しました。Animator Controllerは Animator Override Controller を作成してHorseのAnimatorを参照して、イノシシの該当するAnimationを設定しました。Set Animator Value Gimmickは、InspectorウィンドウからHorseのコンポーネントをドラッグしてHierarchyウィンドウのBoarモデルにドロップするのを片っ端からやりました。

おおよそ以上でモデルの対応完了です。Horseを非表示にするなどして動作確認をします。

イノシシに差し替え完了

前後左右操作、ジャンプの削除

Horseの構造から不要なものを削除していきます。ここに書いてないものは後で利用予定なので手を加えないようにします。

  • 上下左右キーでの操作はいらないのでSteer Item TriggerMove Input Triggersを消します。

移動に関する設定を-を押して削除

  • 旋回動作はないのでSet Angular Velocity Character Item GimmickコンポーネントをRemoveします
  • ジャンプは不要なので、Jump Character Item GimmickコンポーネントをRemoveします

以上で、乗っても移動やジャンプができなくなりました。

Additionalキー(スペースキー)での加減速

このブログの本丸である加減速を実装します。RigidbodyならAdd Force系のギミックで加速できるのですが、HorseはCharactor Controllerなので自前で実装する必要があります。

移動速度はSet Velocity Character Item Gimmickにおいてmoveキーで設定しています。Additionalキーが押されていたらmove.yに加速値を足し、離されていたら減速させれば加減速ができます。またmove.yに空気抵抗に見立てた値を掛ければ最高速度の制限ができます。

この処理は物理更新と似たような頻度で実行したいので、やや無理やりですがItem Timerを0.02秒ごとに呼び出し続けて処理することにします。

関連変数の初期化

  • KeyがResetInputItem Logicを探して開きます
  • moveInputは不要になったので削除します
  • ロジックを追加して、VelocityTimerという名前で型はSignalにして、式は=Constant, Boolを選んでチェックします
  • もう一つロジックを追加して、accelという名前で型はFloatにして、式は=Constant, Floatを選んで値を0にします

パラメータの初期化

速度を更新するためのタイマーを設定

  • 新規にItem Timerを追加します
  • TargetはThis, KeyはVelocityTimer, Delay Time Secondsは0.02にします
  • ロジックを追加して、TargetをCheckVelocityValueSignalにします

ItemTimerの始動

Additionalキーの変更時にaccelの値を設定

  • 新規にItem Logicを追加します
  • TargetをThis, KeyをOnAdditionalInputChangedにします
  • ロジックを追加して、Additionalキーの入力が0より大きかったらisAccelがtrueになるように設定します
    • 最初の行はThis, isAccel, Boolを設定します
    • 式は=GreaterThanにします
    • 1つ目をRoomState, Float, This, additionalInputにします
    • 2つ目をConstant, Float, 0にします
  • さらにロジックを追加して、先に設定したisAccelがtrueならaccelに加速値、falseなら減速値を設定します
    • 最初の行はThis, accel, Floatを設定します
    • 式は=Conditionにします
    • 1つ目をRoomState, Bool, This, isAccelにします
    • 2つ目をConstant, Float, 0.13にします
    • 3つ目をConstant, Float, -0.5にします

加減速をaccelに設定

タイマーで0.02秒ごとに呼び出される速度管理の処理

  • 新規にItem Logicを追加します
  • TargetをThis, KeyをCheckVelocityにします
  • ロジックを追加して、速度管理を持続させるためにタイマーを開始するVelocityTimerシグナルを送信します
    • ThisでKeyはVelocityTimerにして型はSignal
    • 式は=ConstantBoolでチェックします
  • ロジックを追加して、着地時のみに加減速するための設定をします
    • ThisでKeyはcurrentAccel、型はFloatにします
    • 式は=Conditionにします
    • 1つ目の設定の条件式はRoomState, Bool, This, isInAirとして、空中かどうかで判定します
    • 2つ目の設定はConstant, Float, 0を設定して、isInAirがtrueの時は空中なので加速しないようにします
    • 3つ目の設定はRoomState, Float, This, accelにします。これでisInAirがfalseで着地時にはcurrentAccelaccelが代入されるので加速か減速をします
  • ロジックを追加して、currentAccelをmove.yに加算します
    • ThisでKeyはmove.y, 型はFloatにします
    • 式は=Addにします
    • 1つ目の設定はRoomState, Float, This, move.yにします
    • 2つ目の設定はRoomState, Float, This, currentAccelにします
  • ロジックを追加して、減速しすぎてバックしないようにします
    • ThisでKeyはmove.y、型はFloatにします
    • 式は=Maxにして、move.yと0のうちの大きい方をmove.yの値にすることで、値が0より小さくなることを防ぎます
    • 1つ目の設定はRoomState, Float, This, move.yにします
    • 2つ目の設定はConstant, Float, 0にします
  • ロジックを追加して、move.yに空気抵抗がわりの定数をかけます
    • ThisでKeyはmove.y, 型はFloatにします
    • 式は=Multiplyにして掛け算をします
    • 1つ目の設定はRoomState, Float, This, move.yにします
    • 2つ目の設定はConstant, Float, 0.95にします

速度管理のItem Logic

以上で完了です。スペースキーなどのAdditionalキーに該当する操作でイノシシが加速するようになりました。

成果物は以下でご確認いただけます。こちらはもう少し改造して、上キーでも加速するようにしています。

cluster.mu

まとめ

公式テンプレートから実装したいものに近いものを探して観察し、改造することで独自の乗り物や仕掛けを作る手順をご紹介しました。Character Controllerはそのまま使うと等速移動になりますが、自前で速度計算をして加減速に対応させました。またサンプルテンプレートの着地判定を利用することで、苦労せずに着地時のみに加減速する動きが実装できました。

実装している中で機能として欲しいと思ったのは以下の2つでした。

  • Set Animator Value Gimmickに別のゲームオブジェクトのアニメーターを設定したい - これによりアニメギミックを親オブジェクトなどのモデル以外のオブジェクトに構築することで、モデルの差し替えがより簡単にできるようになるのではと思います
  • Is Grounded Character Item Triggerの不安定さをトリガーコンポーネント自体で吸収して欲しい

以上、Cluster Creator #1 Advent Calendar 2022 の6日目の記事でした。創作の一助になれば幸いです。

adventar.org

◆前の日は Sha-la /歌詠しゃら🧸Vシンガー🌷本垢凍結で一時避難中。 さんの clusterで音楽イベントを開いてみたいアーティストの方へ。

◆次の日は さな さんの 会話ロボ in cluster です。

関連・参考URL