No.002 進捗状況10[オブジェクトプーリング][ビルボード]
みなさんこんにちは🌚
ステファノス・チチパスってなんか口に出したくなっちゃうよね。ブルーノです。
では今回もオブジェクトを製作していきます。
今回作ろうと考えたのはズバリ「雷」。雷を避けるなんてかっこいいですよね。というわけでこれを作成していこうと思います。
雷ってぐにゃぐにゃしてるから3Dモデルを用意したらその表現がとても難しいしめんどくさそうですよね。というわけで今回はまずこの雷の表現に「ビルボード」という技法を使いたいと思います。
ビルボード
ちょっと昔のゲームをやっていると時々かなりグラフィックが写実的なのにどこからみてもその面しか見えないオブジェクトとかありますよね?これはビルボードという技術で2Dの見た目のものを常にカメラの方を向かせることで立体感を出す技法で、3Dモデルの節約ができます。
nn-hokuson.hatenablog.com
こちらの方がとても詳しく解説しています。というかこれ見て作りました🌝
まずは背景を透過させた雷の画像をインポート
背景の透過仕方は
mtimsno.hatenablog.jp
こちらに詳しく載っています。
そして新しく作ったQuadオブジェクトに適用。名前はLightningにしときました。見た目はペラペラですがコライダーは普通にCapsule Colliderを使っているので当たり判定はあります。
そしてビルボードのスクリプトを作り、Lightningにアタッチ。
常にカメラの方を向くようになりました。良かった良かった。
しかしこの雷、実際に光を発しているわけではないので日陰だととても暗くなってしまうんですよね。
オブジェクトへの光の当たり具合や見た目の影響を管理するのはマテリアルのエミッション(Emission)が関係しているようなのですがこちらのサイトを参考にしてみたもののUnityのバージョンが違うためかメニューが変わっていて記事通りにいかなかったです。
[Unity]色を失わないオブジェクト | KENスクールブログ
しかたないのでオブジェクトの目に前に光源を置くという強硬手段に。そして下に降る動きと地面の下に入ったら消えるようスクリプトで制御します。ちゃんとタイマーで遅くできるようpublicなスピードの値も導入。ただ落ちるだけだと物足りない気もしたので34行目で地面に落ちた時に光っぽいパーティクルも発生させました。
しかし、これが後述するオブジェクトプーリングというあらたな壁に大きく関わってくることになるのです。
オブジェクトプーリング
さあさっき作ったLightningを生成するスクリプトを作ってたくさん雷を降らせるぞーと思い、こちらのジェネレータースクリプトを作ったところ....
お、重い。。。。
全くゲームプレイができないわけではないですが結構な頻度で画面が角つきました。パソコンでこれならスマホはどうなってしまうんだ....
どうやら先ほどスクリプト内で頻出していたInstantiate()メソッドが原因で、新たにオブジェクトを生成する作業は負荷が大きいそうです。でもこの量でもこれだけカクつくのにシューティングゲームとかはどうやってあれだけの弾を動かしているのでしょうか。
そこでオブジェクトプーリングという技法の出番というわけです。
【Unity】オブジェクトプーリングでオブジェクト節約術 | Unity | DoRuby
こちらのサイトを参考にしました。どうやらオブジェクトをゲーム開始時にたくさん作っておき、そのアクティブ/非アクティブを切り替え使い回す方法のようです。なるほど。
では実際にスクリプトを書いていきます。var型とかforeachとか自分では全然使わないから理解が大変だ😵😵😵
オブジェクトプールのスクリプトはリストの生成と取り出し周りだけなので全く同じ記述で良いですね。
こちらの雷生成スクリプトは大幅な変更が余儀なくされましたが、おかげでオブジェクトプールの仕組みと使い方がよくわかりました。使用する際はGetObject()メソッドのみなので楽ですね!
一応雷のスクリプトもオブジェクトプールの仕様により用済みになったら非アクティブにするように変更。このスクリプトの22行目で世界時間をかけているので加速に伴って雷のスピードが1/10になるのは当然なのですが雷の生成も遅くなるように前の雷生成スクリプトの51行目でも工夫してあります。
結果は....
成功!!
雷の中を加速して避けるのはなかなか面白いですよ。さあゲーム内容が面白くなってきた!!今回はここまでにしておきます。
No.002 進捗状況09[ワープするチェックポイント]
ペルー/クスコ -レインボーマウンテン-
みなさんこんにちは🌚
隻狼というゲームが気になっているもののゲームしている暇もお金もなくて動画をみてしまいたい欲と葛藤するブルーノです。ゲーム動画って100%ネタバレだから見るかどうかすごく悩みます。
では前回に続き今回は通過したら次の地点まで移動して現れるタイプのチェックポイントの作成に移りたいと思います。
前回のものとの違いは
- 触れてもオブジェクトは消えない
- 出現するための座標・角度を複数格納できる
- 触れると次の指定された座標に再び現れる(最終地点の場合は消える)
といったところでしょうか
このチェックポイントは前回のCheckPoint02の中身を改良してその結果を分岐させようと思います。
長くなってしまいましたがようやくできた...!!
本当に時間がかかってしまいました。この記事の投稿が遅れた原因の8割はこのスクリプトで詰まっていたからといっても過言ではないです。気分転換すると突然解決策が浮かぶことってありますよね。
当初の予定通り、次に現れる位置と向きを格納する配列を2つ作り、コライダーがプレイヤーに触れると次の予定された座標に移動、回転し、もし次の座標がなければクリアフラグを立てる。といった風になりました。
52行目のMoveCheckPoint()関数はアニメーションから呼び出しています。今回はこのアニメーションの途中で関数を呼び出せることを学ぶことができました。結果は。。回転もうまく反映させてることがわかるようにイーサンに対して違う向きを向いている写真を撮ってみました。イーサンも感動のあまり立ち尽くしてますね。
試行錯誤の途中はアニメーションが変なことになったりスクリプトが無駄に3枚に増えたり大変でした。こうして一つのスクリプトに収められたのはとても良かったです。
オブジェクト一つ作るのにこれだけ時間がかかってしまうのはとてもまずいですね。もっと簡単な形にしてペースを上げていこうと思います。
No.002 進捗状況08
みなさんこんにちは🌚
キングダムハーツ3やApex Legendsに最近はまっていてPS4の家庭内勢力がSwitchを上回ってきているブルーノです。PSの圧倒的なグラフィックは定期的にみたくなりますね。
では今回もオブジェクトを制作していきます。
移動するチェックポイント
今回はキャラが触れた時に消えるようないわゆるチェックポイントを作りたいと思います。イメージとしてはゼルダの伝説ブレスオブザワイルドの光の輪くぐりの感じですまず簡単に見た目だけ作ります。この中をくぐることにします。
そして今置いたオブジェクトたちにはデフォルトでコライダーがついていますが彼らにぶつかる必要はあまりないので取り除き、逆に空のオブジェクトに適当なコライダーを通過した判定のため追加しておきます。
大きさを変更し、Is Triggerにチェックをつけます。これで物理的な干渉をせずに当たり判定を行うことができます。
今回実装する感じとしては
- ただ触れた瞬間に消える。
- 座標を格納する変数を任意の数指定し、触れたら次の座標に現れる
という二つの方法を考えつきました。
後者はまんまゼルダのイメージですね。実装が簡単なのは間違いなく前者ですが、今回は両方作りたいと思います。
触れた瞬間に消える
これは簡単ですね。コライダーが当たりを感知したらDestroyするようにすればOKです。が、いきなりパッと消えると変なのでアニメーションでとても小さくしてから消します。
dreameaters5239.hatenablog.com
アニメーションの参考過去記事わかりにくいですが、0.3秒でちょっと大きくなり、0.5秒までで小さくなって消えるアニメーションです。こんな風にスクリプトを書いてみました。ついているAnimatorの取得とコライダー反応時にアニメーションを再生する動きのみとりあえず記述です。再生してみると
一応できたのですが、アニメーションがループ再生してしまいました。これでアニメーションの方はOKですが、まだオブジェクトを消す事と触れたことを知らせるフラグを実装することが残っています。というわけでスクリプトを改良します。
アニメーション後にオブジェクトを消す
簡単そうに思えましたが意外にネットに方法がなかったので、アニメーションウィンドウにあったこれを利用してみました。
アニメーション内でスクリプトのアクティブ化・非アクティブ化を操作できるみたいです。これでオブジェクトを消す下のスクリプトを有効化します。フラグについて
ゲームにおいてフラグというのは欠かせない存在ですよね。しかしこのフラグ、どういう風に実装するのがゲーム作りにおいて主流なのでしょうかね。独学なのでいまだによくわかりません。今回はこのCheckPointScriptの中でbool値を操作し、ゲームシステムのスクリプトでそれを検出するという風にしようと思います。これで検出できるはずです。記事が長くなるので今回はここまでにして次回移動する機能の実装を作りたいと思います。
キングダムハーツ3のシークレットムービー、気になる内容ばかりでしたねえ〜〜😄結局黒い箱とマスターオブマスターは出てきませんでしたが、次回で深く関わってきそうですよね。Verum Rexの存在も新しく今後に関わってくるような描写もあってせっかくゼアノートを倒したのにもう世界観が広がりまくりでソラたちの冒険は終わらなそうです。まだまだキンハーは楽しめるコンテンツとして続きそうで楽しみです😍
No.002 進捗状況07
フィリピン -ビガン-
明けましておめでとうございます🌚
といってももう2月ですね。新元号は一体何になるのでしょうか。この年末年始は卒論に追われてゲーム制作どころじゃありませんでしたが😭また再開していこうと思います。というわけで今回の進行具合のレポートを残します。
床の整備
いきなり地味な内容なんですがプレイヤーキャラの挙動を実装した時に街中を走って試運転しているとよく何もないところで飛び跳ねたりするのが気になって原因を調べてみました。どうやら原因は街作りのために敷き詰めた道路の継ぎ目らしく、同じ高さで座標をぴったり隣に合わせたとしても隙間が判定されてしまいAirboneのアニメーションに移ってしまっていたようです。そこで道路関係のオブジェクトのコライダーを全て無くして見かけだけにし、かわりに透明の大きなPlaneを街の床に配置しました。縁石などの地味な高低は無視されますが、いちいちここにつまづいても面白くなさそうなのでちょうど良かったです。なにより各道路のオブジェクトに適用していたMesh ColliderやBox Colliderを消したことで動作が軽くなったことが個人的にとても嬉しいです。
ステージギミックの制作
プレイヤーだけでは面白くないので他ステージギミックを作りたいと思います!どんどん足していきましょう。
ジャンプ台
やっぱり3Dアクションならジャンプできるギミックがないと!ジャンプボタンでの能動的なアクションの実装も考えたのですがGUIがごちゃごちゃするのがいやなのでステージギミックという形で実装します。
クリアシンボル
ゲームをクリアする条件として特定のオブジェクトを全てもしくは一定以上集めるという形式をとりたいのですが以前作ったコイン以外にもそういったオブジェクトを設けたいのでまた別に作成したいと思います。また、応用が利くように2D画像をそのオブジェクトのレンダラーにしてレパートリーを増やします。
この時sizeがquadに合わせて薄っぺらくなっているので全ての値を1にしてとりあえず直方体にしておく
nn-hokuson.hatenablog.com
そしてこちらのサイトを参考に常に画像がカメラを向くビルボードを実装する元サイト様のposition.yの行を入れてしまうと上下のはんてんができなくなってしまうので今回は不適切です。元サイト様のように木などの上下には動いて欲しくないオブジェクトの場合は使えます。
最後に画像を拾ってマテリアルをQuadに適用すればゲームオブジェクトっぽいものができました。lookatメソッドだけで良かったんですね。あとはこの中身の画像を入れ替えれば様々な用途で使用できそうです。以前のコインもこれで良かったんじゃん。。。まあ勉強ですね!今回はここまでです
この記事を書いている間に年が明けてしまい投稿までに1ヶ月もかかってしまいました。この内容に関わることで時間がかかっていたわけではないのでプロジェクトは進んでいませんがペースが明らかに落ちていますね。頑張っていきたいと思います。
No.002 進捗状況06
コムローイ祭り -タイ-
みなさんこんにちは🌚
いまさらアサシンクリードシンジケートにはまっているブルーノです。洋ゲーは写実的というのかとてもリアルに近い美麗なグラフィックがプレステにマッチしていますね。もちろんXboxやPCという手もあるのですがクオリティに対しての値段や日本人にとっての販売タイトルの身近さが良いですよね。
さて今回は前回のプレイヤー周りに取り組むのですが、実は以前友人に制作途中のこのプロジェクトを見てもらったところそんなところはあとでいいからゲームとしての核を先に作れと言われてしまいました笑 というわけで現在改善途中のプレイヤーの挙動をひとまず直したらもうインゲームに取り組んで行こうと思います。というわけで今回は「プレイヤーの動き方」+「インゲーム少し」という内容の投稿になると思います。
プレイヤーの挙動
実は作っている間ずっと気になっていたことがあって、Unity標準搭載のEthanくんのアニメーションでは走行時の方向転換の際に後ろ向きに急な角度だといちいちたちどまってから振り向く動作を行うためテンポが悪いなーと思っていました。なのでブレンドツリーをいじってEthanくんからこの振り向く動作を取り除きたいと思います。
EthanのAnimatorにあてられているThirdPersonAnimatorコントローラーを確認します。
AnimatorのGroundedからBlend TreeがあてられているMotionタブからブレンドツリーを確認します。
このブレンドツリーについては実は昔の記事で使い方をざっとやったことがあります。
dreameaters5239.hatenablog.com
この時のいじり方を参考にたちどまったままの方向転換のモーションを消してみます
おさらいとして、すでにあるモーションを削除するにはそのモーションを該当するひし形かリストから選択し、-ボタンで削除します。だいぶスッキリしましたね。走りながらの急な方向転換もいらないかなと思ったので外側のモーションを全て削除してしまいました。また、まっすぐ走ることが難しかったのでモーション間の間隔を広げることでパッド操作時の敏感な方向転換を鈍くしてみました。
いい感じになりました!成功です!
では本格的にインゲーム作成をしていきたいと思います。
今回は加速装置的な内容をやっていきたいと思います。
加速装置の演出的な部分以外を大別すると
・他の動くものの動きを遅くする
・自分の動きを速くする
ことでそれっぽくしようかなと思います。
一つ目の物体を遅くすることについてはイーサンにPlayerController的なスクリプトをつけ、その中のstaticなbool値とfloat値を設けようと思います。ほかのオブジェクトはそれを参照することでモーションのスピードと加速しているかどうかの2点を変更できます。float値だけで最初はいいんじゃないかとも思いましたが自身は動かないで動作するオブジェクトなどのためにbool値もつけておきました(使うかはわかりませんが)。
それに伴い、以前作ったAudienceControllerも変更しました。
dreameaters5239.hatenablog.com
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AudienceController : MonoBehaviour { private Animation anim; private bool quicker; private int motionTimer; //モーションの時間のタイマーと同時に何のモーションをするかを決める。 private float motionTime; //モーションまでの時間。マックスになったらモーションをし、リセットされる。 private bool motionBool; //モーションタイマーを進めるかどうか // Use this for initialization void Start () { quicker = false; anim = GetComponent<Animation> (); motionTimer = Random.Range(5, 10); motionTime = 0f; motionBool = true; } // Update is called once per frame void Update() { if(motionBool) motionTime += Time.deltaTime; //motionBoolがtrueの時だけタイマーが進む。 if(motionTime > motionTimer) { motionBool = false; StartCoroutine(AudienceAnim(motionTimer)); motionTime = 0f; motionTimer = Random.Range(5, 10); } if (!anim.isPlaying) anim.Play(); //anim[anim.clip.name].speed = PlayerController.WorldTime; //これじゃダメらしい if (PlayerController.QuickTimeSwitch == true && quicker == false) { foreach (AnimationState a in anim) { a.speed = PlayerController.WorldTime; } quicker = true; } if (PlayerController.QuickTimeSwitch == false) { foreach (AnimationState a in anim) { a.speed = PlayerController.WorldTime; } quicker = false; } } IEnumerator AudienceAnim(int i) { switch(i) { case 5: anim.CrossFade("applause"); anim.CrossFadeQueued("idle"); yield return new WaitForSeconds(2.07f); break; case 6: anim.CrossFade("applause2"); anim.CrossFadeQueued("idle"); yield return new WaitForSeconds(2.07f); break; case 7: anim.CrossFade("celebration"); anim.CrossFadeQueued("idle"); yield return new WaitForSeconds(2.07f); break; case 8: anim.CrossFade("celebration2"); anim.CrossFadeQueued("idle"); yield return new WaitForSeconds(2.07f); break; case 9: anim.CrossFade("celebration3"); anim.CrossFadeQueued("idle"); yield return new WaitForSeconds(2.07f); break; } motionBool = true; yield return null; } }
なんかソースコード貼り付けられるってことを聞いたんで試してみましたが行番号わからなくて微妙ですね。javaScriptをつかって行数を表示させる方法もあるらしいですがいくらやってもできませんでした。。。また今度😓
Update真ん中のコメントアウトした行(//anim[anim...)のように記述してもうまく機能しなかったので下のように長く書くしかありませんでした。foreach文を毎フレームやるのは負荷が大きいという情報を聞いたのでちょっと長いですが下にその対策をした文を作りました。
では次にプレイヤーの速度をあげようと思います。
ThirdPersonControllerはThirdPersonCharacterというスクリプトコンポーネントがついており、このMoveSpeedMultiplierとAnimSpeedMultiplierがそれぞれモーションと移動速度を変更できるようですね。しかしこのコンポーネント、スクリプトの場所が名前空間から違い、参照する場合は少々長くなります。そしてスクリプトをみてみると先ほどの関数たちはSerializeFieldで可視化されたprivate値のようで、外部から変更できないようになっているのでpublicに書き換えます。
そしてこれを操作する記述をPlayerControllerに追加しました。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityStandardAssets.CrossPlatformInput; public class PlayerController : MonoBehaviour { public static bool QuickTimeSwitch; //現在加速しているかどうか public static float WorldTime; //主人公以外の時間。各アニメーションにはこの変数をかけておくことで加速時にスローにする float QuickTimeCount; //現在の加速時間 public int QuickTimeLimit; //何秒間加速するか設定する public UnityStandardAssets.Characters.ThirdPerson.ThirdPersonCharacter TPC; // Use this for initialization void awake () { QuickTimeSwitch = false; } // Update is called once per frame void Update() { //QuickTimeSwitch = CrossPlatformInputManager.GetButtonUp("Button"); //「Button」に設定しているボタンを使う if (Input.GetKeyDown(KeyCode.T) && QuickTimeSwitch == false) TimeQuicker(); if (QuickTimeSwitch == true) { QuickTimeCount += Time.deltaTime; if (QuickTimeCount > QuickTimeLimit) { QuickTimeSwitch = false; TPC.m_AnimSpeedMultiplier /= 2; TPC.m_GravityMultiplier /= 2; TPC.m_MoveSpeedMultiplier /= 2; WorldTime = 1f; QuickTimeCount = 0; } } } void TimeQuicker() { QuickTimeSwitch = true; TPC.m_AnimSpeedMultiplier *= 2f; TPC.m_GravityMultiplier *= 2f; TPC.m_MoveSpeedMultiplier *= 2f; WorldTime = 0.1f; } }
重力のGravity Multiplierもついでに操作しておきました。
再生してみると。。。
画像ではわかりにくいですがプレイヤーとオーディエンスの速度変更に成功しました!!今回はここまでにしておきます。
Unityでの開発もまだまだままならないですがコンシューマーゲームを作る場合はCやC++が主流と聞きました。そちらの勉強もこれからしていきたいです。
No.002 進捗状況05
ヒリアー湖 - オーストラリア -
みなさんこんにちは🌚
マリオパーティ8に毎回全力で挑むも最後のスターボーナスがでかすぎて辛いブルーノです。こんなん運ゲーやんと思いつつもついやってしまうんですよねー。
さて今回は、プレイヤー制御をしていきます。大きく考えてプレイヤー制御は
・UIの配置
・機能実装
の二つと考えています。UIの配置はまず基本の移動を実装することから始め、うまくいったら別の要素も実装していこうと思っています。スマホゲーはコンシューマーやアーケードと異なりボタンが著しく少ないのでどうしても画面に対応させる機能を追加しなければならないです。このワンクッションだけでも僕には大仕事なので今回分けることにしました😰
しかし調べてみるとスタンダードアセットにどうやら便利なものがあるようです。
[Assets]→[Import Package]→[CrossPlatformImput]を選択
Standard Assetsの中に新たにCrossPlatformImputというフォルダが追加されています。
中のPrefabにあるMoblieSingleStickControlをシーンにおき、Canvasを追加すると
画面に十字キーとジャンプボタンのUIが設置されました!
こんな簡単な手順でモバイル向けのコントローラが配置できるなんていい時代ですね。。。。。。。。。。
あれ?
一向に動かない。。。。インポートしたばかりのスクリプトの中身弄ってない状態でも、あらゆるサイトに載っているスクリプトをひとつずつ試してはReimportしても直らない。。。。
探ること1週間。。。。
わかりました。これが原因でした
いつか何かの拍子に入れていたCanvasが入力を遮ってしまっていたようです。こんな簡単なことだったのか。。。じゃあGUIとこのコントローラを共存させるにはどうすれば良いんだ.....?とりあえず今は実装できたのでよしとします
そしてUIにいろいろ手を加えて...
こんな感じにしてみました。十字キーの方は画像を差し替えただけで機能はあまり弄っていません。インスペクターから可動範囲を後ろの白いシルエット画像あたりまで変えた程度でしょうか。ただこの時に画像をただトランスフォームで移動させるだけではタッチ範囲を変えたことにはならないことに注意しましょう。CrossPlatformのバーチャルパッドはアンカーの座標を中心としているようなのでこちらも座標を変えてあげる必要がありました。
真ん中のリボンがアンカー
そしてもう一方の時計のマークは最初のジャンプボタンなのですが、仕様を大きく変更しようと思いこのアイコンにしました。ここまで作りながら考えていたのですが、今回のゲームは時間を操るアクションにしようと思いました。というわけでこのボタンは高速化のボタンにしようと思います。専用の機能をこれからどんどん足していくひつようがありそうです。
ずいぶん久しぶりの更新ですね。いろいろやらなければいけないことが多くて忙しいですがもっとペースをあげていかないと....
No.002 進捗状況04
アンスース・ダルジャン セーシェル共和国
みなさんこんにちは🌚
バイオハザード7を繰り返しやるうちに怖さに隠れていた製作陣の仕掛けの誘導のうまさに驚嘆したブルーノです。特にビデオテープ「ミア」の部分はとても自然と誘導されていると思いました。モールデッドの配置と出現のタイミングはめっちゃビビるんじゃ😡😡😡
さて今回は目に見えるオブジェクトや展開について作っていこうと思います。
まずゲームに活気を出すため、モブとなるアセットを配置したいと思います。
前回にもちょっとだけ出てきましたが、すごい適材がいました。これを今回は使います。
いろんなタイプの色があるようですね。全部使って出してみましょう
イーサンくんを取り囲む6人の男たちです。
アニメーションも6つほど入っていました。これをスクリプトから取得して制御したいと思います。
AudienceControllerというスクリプトを作成。
シーン上のすべてのAudienceたちにアタッチ。なぜか親に変更を反映させるapplyタブがopenになっているので仕方なく全部を選択してアタッチしました。
ではスクリプトを編集していきましょう。
ここを見ながら作ります
animationをStartメソッドで取得し、とりあえずZボタンを押したら拍手するようにしてみました。再生が終わればidleに戻します。
実験してみると...
全員が祝ってくれました。成功です😀
では街の人っぽい動きに変えていきます。
ランダムで生成したint値によっていろんなモーションをするようにしました。せっかくintを取得したのにanimationコンポーネント内のanimation clipの取得の仕方がわからないせいでコルーチンの中身が無駄に長くなってしまっています。どこに載ってるんだろう🤔
みんな別々の動きでモブっぽいです笑
では今回はもう一つだけオブジェクトを作ります。
3Dアクションといえばやっぱコインですよね!というわけで、コインのオブジェクトを実装していきます。
何気にこれBlenderで自作しました。友人に質問しまくって簡単なものですがつくれました。時計をモチーフにしています。ではシーン上にこれを配置しますが、、、
プレビューだと金ピカなのにシーンだとなんか土みたいだなあ...
ここで友人に教えてもらった魔法を使います。
[GameObject]→[Light]→[Refrection Probe]を選択
なんかごちゃごちゃした画像を用意(なんでも良い)
TextureTypeをDefaultに、TextureShapeをcubeにします
これをReflectionProbeのCubemapに指定すると
いい感じに金ピカ!Reflection Probeの画像を反射させることができるんですね。
サンキュー友人😆
インスペクターのBoxSizeをいじると反射の有効範囲を変えられます。
また、反射させたくないオブジェクトはそれぞれのメッシュレンダラーのReflection ProbesをOffにしておくと無効にできます。すべてに反射させると重くなりそうなのでコイン以外は今回切っておきます
そしてイーサンがコインに触れたことを取得するためにコライダーをコインにつけます
Box Colliderじゃ判定ガバガバですがまあ気にしないでおきましょう。
では今度はコインの動きを制御していきましょう。とくあるゲームの中のコインは浮いていて、くるくる回ってたりして、取得すると上にピコーンって動くようなイメージですよね。これを実装したいと思います。そこで、Animatorコンポーネントを使っていきたいと思います。
Add Componentの欄からAnimatorを選択
Animatorコンポーネントがアタッチされましたが、これだけでは動きません。アニメーションを制御するのは青字でもありますがControllerというもので、これはそれをオブジェクトに再生させる再生装置のようなものらしいです。ではこのコントローラを作っていくのですが、実はコントローラもアニメーションの動きの中身ではなく、文字通りアニメーション同士の相関性を管理するコントローラでしかないのです。各々の動き自体はアニメーションクリップというものによって管理されます。というわけでこのアニメーションクリップを作っていきましょう。
Window→Animation→Animationを選択します
これがアニメーションの動きを編集できるウィンドウです。
こんなウィンドウが出て来ました。今この画面ではAudienceのアニメーションを作り出そうとしていますが、これはヒエラルキービューでAudienceを現在選択しているためです。今回はコインのアニメーションを作成するのでコインを選択してから[Create]をクリックします。
新しく作るアニメーションクリップの名前を選択。
Coin Idleという名前のアニメーションクリップを作成しました。左上で名前が確認できます。ちなみに、この名前が表示されているタブをクリックするとそのオブジェクトの他のクリップに移動したり、また新たにアニメーションクリップを作成することができます。まずは待機状態のくるくる回っているアニメーションを作成します。
Add PropertyからTransform→Rotationを選択
Rotationのクリップができました。右の時間らしき目盛たちがタイムラインで、現在見えている中では1秒間でのアニメーションを編集できるようになっています。右にスライドすれば当然もっと長い時間までのアニメーションを組むことができますが今回はとりあえずこの1秒の中で何回か回転するようにしてそれをループ再生することでコインがくるくる回っているアイドル状態を表現したいと思います。
さて、タイムライン上にはそろばんのように現在ひし形の玉が一つ表示されていますね。CoinNew : Rotationという行の玉にはrotation情報が入っており、タイムライン上でさまざまなrotation情報をいろんな時間に置くことで再生した時にそれらを滑らかに補間してくれます。
玉の作り方はいたって単純です。左上の赤丸をクリックし、レコードモードにします。
するとタイムラインとrotationに対応するオブジェクトのインスペクター欄が赤くなりましたね。タイムラインにかかっている白の縦線は時間の目盛を押すことで移動でき、インスペクター上の数値を変更するとこの縦線の時間にその数値の情報が玉として記録されるということです。ではいろいろ数値を記録してみます
1/4秒ごとにコインが1回転するように組んでみました。レコードボタン横の再生ボタンで再生すると...
画像なので分かりにくいですがくるくる回転しています。
タブの下側の[Curves]という欄をクリックするともっと視覚的に数値の変動加減を編集できます。待機状態のアニメーションがこれで完成したのでこんな感じでコインゲット時のアニメーションも作ります。
名前の欄をクリックして、クリップを変更したり追加したりできます
アニメーションが完成したら次はそれを制御するコントローラを作ります。それをAnimatorコンポーネントに適応したら完成です!もう少しですね
実はアニメーションをCreateした時に同時に空のコントローラも生成されています。
コントローラの中身はこんな感じになってます。中にある四角ひとつひとつのことをステートと呼び、必ずEntryステートからアニメーションは始まり、矢印に沿って進みます。最初はidleに伸びているはずですが、もし最初のアニメーションが思惑と違っていたら目的のステートで右クリックし、Set as Layer Default Stateを選択しましょう
今、二つのクリップは独立していて切り替わることは絶対にありません。そこで、Entryステートが行なっているようにidleステートで右クリックし、Make Transitionで目的のステートまでトランジション(矢印)を伸ばします。
ただこれだけではアニメーションが遷移する条件がないので遷移されません。トランジションをクリックして情報を見ると
遷移する具合や条件(Condition)を指定できます。このConditionも自分で決めなければならず、先ほどのコントローラのビューの右上のParametersから追加します。
条件の値も様々な型の変数が用意できますが、今回はTriggerにします。
これで作った条件を改めてインスペクター上のConditionに入力します。これで準備は完了です。あとはスクリプトでAnimatorを取得し、このTriggerを起こせばアニメーションが遷移します。
とても単純ですが、12行目でAnimatorを取得し、31行目でTriggerを引き起こしています。再生してみると
触れると上にくるくるしました!!大成功です😸こんな調子でオブジェクトを今後追加した際はこうやって動かしてにぎやかにしたいと思います。今回はここまでにしておきます。
一つ一つの過程をメモしていたらすごい量になってしまいました。でもほとんど画像なんですよね。。。いろいろあってかれこれ1ヶ月もこれの土台作成で止まっていました。おもしろいの作るぞー