テラシュールブログスマートフォン用の表示で見るテラシュールブログ旧テラシュールウェアブログUnity記事。UnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。Birdライクなゲームを作成したときの手順を紹介します。tsubakit1.hateblo.jp分からない事があれば、このブログか@tsubaki_t1に連絡くれると超喜びます(フィードバックほすぃ)。このプロジェクトのソースコードはここで公開してます。板を無限に出現させるスコアの追加スコアの表示ゲームオーバーを作る地面を用意してスクロールする背景を多重スクロールさせるゲームオーバーからのリトライ関連イメージをまとめるまず自分が作るものをイメージする。Birdイメージしたら要素を分解して羅列してみる。完璧な模倣であればもう少し項目が増えるが、面倒なので無視。面白さを確認するだけならこの程度で十分なので、この要素をさらに分解してみる。土管との魚は接触する土管の間を通過する判定スコアの加算制御スコアの表示ゲームオーバー時操作が効かなくなる絵作りまずは自分のイメージしている絵を作ってみる。絵を作り動かしてみるのがこの手の簡単なゲームを作る場合は一番わかりやすい。Learnより素材を拝借した。魚でないのが残念だが、魚の画像がないので仕方がない。パブリックドメインなので、使用も問題ないし。投入した画像がSpriteになっていなかったのでTextureTypeからSpriteに変更。2Dモードで実行しておけば自動でなるのだが、何故か3Dモードでプロジェクトを作ってたらしい。確認するとCameraのProjectionもPerspective(3Dモード)だったのでOrthographic(2Dモード)に変更しておく。この辺りはプロジェクト作る時に2Dモード設定してれば治るハズなのだが。後はPlayer_Fly0(鳥の画像)とboad(板の画像)をシーンに適当に配置して絵作り。適当に並べて大体イメージ通りの画像が出来た。作ったら実際に(手動やAnimation)で動かしてみて調整する。動かすことで実際の動作イメージを掴んだり、新しいアイディアを見つけたり、問題点を発見出来る。今回の場合は板の隙間が上下しても他の場所に隙間が発生しないことが条件になっているので、そのあたりも確認。動かしているうちに両方選択するのが面倒になってきたので、板オブジェクトの中に板画像を配置する事にした。これで板オブジェクトを動かせば板画像2枚とも動かせる。鳥をジャンプさせるとりあえず配置したので鳥をジャンプさせる事にする。記憶では割と機敏に上下していた気がするので、大きさをかなり小さくして調整(ボックス=1m。小さい方が機敏に動き、大きいと遅い)。いくらなんでも鳥が1mなのはおかしいので20cmくらいを目指す、面倒くさいので適当なGameObject(命名root)に入れてをrootのscale一気に0.2にした。これで板の画像も一緒に小さく出来る。後はジャンプ処理の実装。入力を受け付けるジャンプの3つに分けられる。落下については面倒なのでrigidbody2dを使う事にする。すればジャンプ処理はrigidbody2d.velocityを弄るだけで済む。最終的にrigidbody2dを使うにせよ使わないにせよ、とりあえず形になるのでこれは割と好き。Componentボタンの検索ボタンにrigidbodyと打ってrigidbody2dを選択。最近コンポーネントをD&Dしたりメニューから選択するよりもコッチのほうが楽な事に気づいた。追加したら落下するか確認してみる、うんOK。入力を受けたらジャンプする機能を追加する。PlayerController.csとか適当なC#スクリプトを作って適当な場所に配置。タッチされたらフラグを立てる処理を追加する。これでボタンが押されているタイミングのみisJumpRequestがtrueになる。true;}}Updateの下の方に以下の処理を追加しておく。これでisJumpRequestがtrueなら(ボタンが押された瞬間なら)ジャンプするようになる。power;}}今作ったスクリプトを鳥に作成したスクリプト(PlayerController.cs)をアタッチして、動作を確認。上手い感じに飛んでくれる。(※1)rigidbodyはUpdateと異なるタイミングで動作しているため、Updateにrigidbody2dの処理を記述すると稀に失敗する。そのため、Updateではフラグ立てのみを行う。右に移動する処理だが、板自体を左に動かすことにした。逆に鳥を動かしても良かったのだが、無限に移動するのも気持ち悪い話なので(※2)。背景の多重スクロールもコッチのほうがやりやすいって話もある。collider2dを追加して当たり判定を追加し、鳥との判定を確保。動かすために板オブジェクトにrigidbody2dを追加する(※3)。これで上下のコライダーが板オブジェクト一つとして計算される。「板」オブジェクトに左に移動する処理を記述する。MoveBoad.csを用意して、中に記述を追加。}ただココで一つ問題が発生する。rigidbody2dはFixedUpdateのタイミングでvelocityを上書きすれば挙動をハック出来るといった訳では無いらしく、鳥と衝突した場合板が転がってしまう。scaleを0」「Massを1000くらい(とにかく大きい数)」「FixedAngleにチェック」を設定した。(※2)実際はrigidbodyの数的に地面より背景動かした方が効率的だが、一定距離でプレイヤーの位置を初期化するのが面倒だったので背景を移動する方を選択。(※3)別に要らないように思うかもしれないが、rigidbodyがない場合にコライダーを動かすと毎回計算が走るらしく、場合によっては致命的なスパイクを呼ぶ。板を無限に出現させる板を定期的に配置する処理を追加する。方法は単純に一定時間ごとにInstantate(生成)し範囲外に移動したら削除する。一定時間ごとにオブジェクトを配置する処理を記述する。BoadManager.csを用意し、処理を記述。単純にInstantateを書かないのは、この処理が拡張される事が多いため(※4)。ここで指定するboadObjectにはプレハブ化した板オブジェクトを配置する。}この際ミスで親オブジェクトがscaleを変更していた事を忘れてそのままプレハブ化してしまったため、生成時にものすごい大きな板オブジェクトを出現させてしまった(※5)。これはプレハブ化するオブジェクトを一旦root直下に移動させてからApplyすることで問題を回避した。このコードで板オブジェクトを生成する場所は、BoadManagerをアタッチしたオブジェクトの上3~10くらいの位置。この3〜10の値は絵作り中に板オブジェクトを上下に動かして画面内に収まる位置で決めた。それとオブジェクトが一定時間ごとに出現する処理も追加する。一定時間ごとに出現させる処理はInvokeRepeatingやコルーチン等々色々とあるが、今回はUpdateとTime.timeSinceLevelLoadを利用して実装する。作業が完了したら適当なゲームオブジェクト(命名:板マネージャー)を作ってBoadManagerを登録し、板プレハブをboadObjectに登録。再生すればゲーム板オブジェクトが定期的に流れるようになる。}画面外に出たら削除する処理も作成する。画面外判定もOnBecameInvisibleや位置判定等々色々とあるが、今回は移動する物にRendererが無いのでOnTriggerExit2Dを使用して判定する。先ほど作成した板の管理オブジェクトにboxcollider2dを追加し「isTrigger」にチェック。boxcollider2dのcenterやsizeを使い画面外となる位置に判定を配置。後は下の処理をBoadManagerに追加する。OnTriggerEnter2DではなくOnTriggerExit2Dなのは動いていないオブジェクトに反応させないため。}(※4)大抵の場合、この後パラメータ追加やオブジェクトの参照関連の処理が入るため、別メソッドにしたほうが良い(※5)GameObject.Instantiateは一旦オブジェクトをグローバルスケールに配置するため、親オブジェクトがscaleを変更していた場合、オブジェクトの大きさが変化してしまう。板の隙間を抜けるとスコアが加算する仕組みを追加する。Triggerにチェックを入れる。このオブジェクトは板オブジェクトと同じようにうごくように、板オブジェクト下に配置しておく。スコアの保存場所だが、色々考えた末にGameController(※6)を作り保存する事にする。今回はコンパクトなゲームなのでGameController.csを作成。SingletonMonoBehaviourを継承して何処からでもアクセスできるようにしておく。スコアはせっかく作ったのでNotificationObjectに登録しておく。スコアやゲームステート、プレイヤー等の情報はNotificationObjectで制御しておくと連携が楽だ。}}プレイヤーが通過した際にスコアが発生する仕組みも作成する。AddScore.csを追加して接触時にスコア追加。これを先ほどつくった棒と棒の間の当たり判定に追加しておけば、通過時自動でスコアが加算される。}一つ注意なのが、単純に判定だけを取るとプレイヤー以外が通過した場合もカウントされてしまう点だ。対策に通過したものがPlayerタグの場合のみスコアを加算するように記述しておけば間違いは無い。この処理を追加したらプレイヤーはPlayerタグに設定しておく必要がある。上のコードを下のように変更する。}(※6)GameControllerはUnityにビルトインされているタグの一つ。多くの場合、ゲームの制御を行う中枢オブジェクトはこのタグを持ち、この名称に近い名称を持つスクリプトを持つ。現状ではスコアが見れないのでスコアを表示する。3DTextで画面の真ん中に数字を配置。ScoreLabel.csを作成し作成した3DTextにアタッチ。GameController.Instance.scoreと接続し変更通知を受け取る処理を記述する。これで数値が変更した場合のみ数値を変更する処理が走る。NotificationObjectの特性で、Destroyする際は(例えばシーン切り替えでGameControllerが先に破棄されている可能性も考え)GameController.Instanceを事前にチェック。破棄されていた場合はイベントもついでに全て破棄されているので気にせず破棄。score){}ChangeScoreにラベルを更新する処理を更新する。NotificationObjectに登録するイベントは"Change変数名"みたいに名前を統一しておくと良いかも。}ゲームオーバーを作るプレイとゲームオーバーのステートを作る。enumでステートを定義しておいて、その定義をシングルトンのGameControllerに持たせ、変更通知を受けられるようにNotificationObjectで登録する。gameStateを追加する。);忘れずにOnDestroyで削除する対象に追加しておく。}PlayerController.csに壁と接触した時にステートをGameOverにする処理を追加。これでプレイヤーが壁と接触したらゲームステートがGameoverへ移行する。}ステートの状態で挙動の変わるオブジェクトにステート変更通知を受ける処理を追加し、各々必要な処理を記述しておく。プレイヤーの場合はゲームオーバー時に入力を効かなくする。}地面を用意してスクロールするせっかくなので地面も用意する。スクロールする背景を作るには「スプライトを並べて総移動」と「テクスチャのUVをスクロール」が思いつくが、今回はテクスチャのUV移動を選択。多重スクロールがやりたい。スプライトのUV移動は現状出来ないので(※7)、QUADを使用して実現する。Other>QUADでQuadを用意して、スクロールさせる画像をD&Dで登録する。今回の場合はImages>Stageの中にあるboxを使用。名前は地面とでもしておく。地面オブジェクトのスケールのxを3にして横に3倍に引き伸ばし、shaderのtilingを3にする。1個しか表示されない場合は、テクスチャのwrapModeがRepeatになっていない。shaderはunlit>Textureを使用。透明を使いたいならばunlit>Transparentを使う(※9)スクロール処理を追加する。これは単純にUVを時間毎に変更を加えたもの。多重スクロールしたい場合は、速度を落とした画像を複数配置すればOK。collider2dを付与する。このままでは流れてくる板オブジェクトに干渉するので、対策に地面と流れてくる板オブジェクトはレイヤーを分けお互い接触しないようにする。ニュー>Edit>PorjectSettings>Physics2dよりLayerCollisionMatrixを調整。groundとboadの列からチェックを外す。板の奥に地面が表示される場合、座標のz値をマイナス方向に弄る。(※8)やろうと思えばスプライトでもスクロール出来るには出来る。可能な限りTextureを使うと良い。背景を多重スクロールさせる画面の奥行きを作るため多重スクロールさせる。奥のものは遅く、手前の物は高速で動作するので、画面奥にスクロールする板を配置し、スピードを低速に設定する。背景の場合は当たり判定が不要なのでコライダーは外しておく。スクロール処理にはspeedを設定していたので、それを変更すればOK。その際、当たり判定は不要なので外しておく。ゲームオーバーからのリトライゲームオーバー後にゲームをリトライする処理を追加する。これはStateがGameOverの時何らかのアクションで現在のシーンを読み直せば良い。適当なスクリプト(GUIController.cs)を作成し、下のコードを記述。マトモなGUIを組みたい場合、変更通知でリザルト画面をLoadLevelAditiveにしたり、そのタイミングで下から飛び出すアニメーションさせたりする。面倒になったので一気に公開。BirdのUnity3d再現チュートリアルは既に色々とある模様。それぞれやり方が少しずつ異なるので、実装を見比べるのも面白いかもしれません。Debugg...物理演算を使用している際に、現在Rigidbodyがスリープしている...2014-07-13Unityで接触したブロック達を吹っ飛ばす物理演算的には正しくなくとも、表現的に物体がぶつかった時に...2014-03-08値の変更を通知するクラスUnityのゲーム開発で大抵頭を悩ませるのがメッセージングだ。メ...2014-01-19物理演算のスリープについて今回は物理演算のスリープについてです。所謂「拡張メソッド」というものをUnityも使うことが出来る。(1)月別アーカイブはてなブログをはじめよう!tsubaki_t1さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。