Mokosoft開発者ブログ

こんなブログ読んでも時間の無駄ですよ

【第2回目】Unity3Dで2D物理シミュレーションゲームを作る:プログラム編

f:id:mad_ochi:20140329095842p:plain

前回

Unity3Dで2D物理シミュレーションゲームを作ってみよう - Mokosoft開発者ブログ

 

に続き、プログラムを書いてキャラクタが動くようにしてみましょう。

前回説明したように、UnityではSceneに配置したオブジェクトに対してプログラムを割り当てるという仕組みになっています。

また、デフォルトで用意されているアセットにも、キャラクタのコントロールに関するアセットが存在するので、決められた入力方法であればアセットを組み込むだけで、キャラクタを動かすことが可能です。

 

ただ、キーボードでコントロールするものが主であるので、今回は自作でプログラムを書いてみたいと思います。

 

1からゲームプログラミングを書いたことある人ならば、このUnityのようなプログラムの持ち方に若干違和感を覚えるでしょう。

通常のゲームプログラミングであれば、メインループがあって、フラグ毎に描画を切り替えて、なんて感じですべてを一箇所で制御している感が強かったですが、Unityの場合はオブジェクト単位で個々に制御を行うという感じです。

それらすべてを管理するオブジェクトを作成して、画面上のオブジェクトと監視させることもできますが、基本的には各個別オブジェクト同士で完結してしまって良い場合が多いでしょう。

 

前書きが長いですが、とりあえずやってみましょう。

 

f:id:mad_ochi:20140331120942p:plain

「GameObject」→「Create Empty」として空のオブジェクトをシーン上に配置します。

 

f:id:mad_ochi:20140331121027p:plain

 

名前を「Controller」などに変えておきましょう。

 

キーウィの操作を行うので、キーウィのオブジェクトにプログラムを書いていっても良いのですが、ゲームの内容によってはキーウィが画面上から消滅してしまうかもしれませんし、不確定要素を考えていくと、コントロールを司る処理は、誰からも影響をうけないオブジェクトに持っておくのが良いのではないかと思います。

が、これは人それぞれなので、お好きなようにしてください。

 

f:id:mad_ochi:20140331121357p:plain

 

Controllerオブジェクトのインスペクタから「Add Component」とし、「New Script」を選択。

スクリプト名を指定して作成を行いましょう。

言語はC#、JavaScript、Booが選べます。

どれでもいいんだと思うんですが、アセットを利用する場合に、アセットで利用している言語と合わせておかないと、不具合が起こることがある【らしい】ので、アセットでよく利用されているC#を使うことにしています。

JavaScriptで書いてる人も多いので、問題はないと思うんですけども。

 

 

f:id:mad_ochi:20140331121938p:plain

 

作成したスクリプトファイルをダブルクリックすると、コードウィンドウが開きます。

ここで最初から Startメソッドと Updateメソッドが用意されています。

またいくつかの予約メソッドが用意されているので、それらを理解すれば、だいたいできることが見えてきます。

 

 

f:id:mad_ochi:20140331123441p:plain

初期化に関わるのメソッドが

Awake Start の2つになります。

Awakeはオブジェクトが生成された時に呼び出されるメソッドで、

Startは全てのオブジェクト準備が完了し、ゲームの処理が開始されるタイミング(Updateを呼び出す直前)に呼び出されるメソッドです。

それぞれ常にシーン毎に1回だけ呼び出されます。

 

2つ使える理由としては、初期化処理のタイミングを分けたい場合などで利用ができるように、とのことらしいです。

私は主にStartで初期化をすることが多いです。

Awakeの段階では、他のオブジェクトがまだシーン上に用意されていない可能性があるので、他のオブジェクトを参照する場合などは、Startでやるのが良いですね。

オブジェクト内で完結できる変数初期化などであれば、Awakeを使っても問題ないと思います。

 

次にUpdate LastUpdate FixedUpdate の3つが、いわゆるゲームループ処理になります。

 

Updateは一番基本的なゲームループです。

現在のフレームレートのフレーム毎に呼び出されるメソッドとなります。

ですので、60fpsであれば、1秒間に60回呼び出されるはずです。

ただあくまでもMaxフレームレートの場合なので、処理が混み合って処理落ちをして20fpsまで落ちれば、1秒間に20回呼び出される、はずです。

 

LastUpdateは毎フレームの最後に呼び出されるメソッドです。

必ずUpdateとセットになりますが、おそらくこれはUpdateが描画前、LastUpdateが描画後呼び出されるということなのでしょうか。(未調査)

公式にはカメラの追尾処理などはLastUpdateでやるのが好ましいとあります。フレーム内で新しい座標などが確定した後に、カメラの移動などを行いましょう、ということらしいです。

 

そして次にFixedUpdateです。

まず、Update、LastUpdateとFixedUpdateは違う処理体型であるということを理解しておいてください。

名前からも推測されますが、Updateが毎フレームレートの処理タイミングなのに対して、FixedUpdateは固定フレームレートでの処理タイミングとなっています。

このフレームレートはデフォルト値で50FPSとなっています。

f:id:mad_ochi:20140331125232p:plain

この値はプロジェクト設定から変更することが可能です。「Fixed Timestep」がそれに当たります。たぶん。

 

そして、FixedUpdateは物理シミュレーション演算の際に利用するというのが通説のようです。

 

ややこしいのですが、海外のフォーラムなんかを読んでいると、入力制御はUpdateでやったほうがよいというのが書いていたり、そんなことを気にせずFixedUpdateでやってる人がいたり、どれが正しいのかはわからないですが、

いろいろ試してみて、自分に合う処理を選べば良いんじゃないかと思います。

 

 

以上を踏まえて処理の流れは以下のとおりです

 

Startで初期化、キーウィのオブジェクトを用意しておく

Updateで入力の有無をチェックして、フラグを持たせておく。

FixedUpdateで物理演算処理を実行

 

となります。

今回は、画面をタッチしてる間、そのタッチしている所へキーウィが寄ってくる、という処理です。

 

まず、Controllerオブジェクトからキーウィを操作するので、キーウィオブジェクトを掴まないといけないのですが、手っ取り早い掴み方を紹介します。

f:id:mad_ochi:20140331130630p:plain

まず、プログラム内で、public型のGameObject変数を宣言して、保存します。

すると、

f:id:mad_ochi:20140331130658p:plain

Controllerオブジェクトのインスペクタ内に「kiwi」という宣言したGameObject欄が表示されるようになります。

現在はNoneとなっていますが、右のボタンを押すと、

f:id:mad_ochi:20140331130747p:plain

 

オブジェクト選択画面が出てくるので、シーン内に配置しているキーウィを選んでやります。

こうするだけで、スクリプトのkiwi変数の中に、画面内のこのオブジェクトが関連付けられます。

 

オブジェクトにタグを付けておいて

GameObject kiwi = GameObject.FindWithTag("nantoka");

として、呼び出すことも可能です。

 

 

f:id:mad_ochi:20140331133658p:plain

 

UpdateとFixedUpdate内の処理です。

 

本当はスマホのタッチに対応させるんですが、シミュレーション上はマウスじゃないと動かせないので、マウスで代用しています。

Input.GetMousButtonDown(0) というのは、0番目のマウスボタンを押しているかどうかの判断に使います。0番目のボタンは左クリックですね。

 

マウスが押されている間はboTouchのフラグをたて、マウスが離されたらフラグをオフにしています。

その時の座標を取得して保存するのですが、マウスの座標(Input.mousePosition)は画面上のどこをクリックされたか、という位置なので、ゲーム内で利用するワールド座標に変換します。

 

この状態で、FixedUpdate内では、フラグを見て、キーウィより右方向でタッチされたら、右方向へ力を加え、

左の場合は左方向へ力を加えるということをしています。

kiwi.rigidbody2D.AddForceがそれですね。

Vector2というのは呼んで字のごとく、x,y座標のみの2次元ベクター変数です。

Vector2.right は右向き矢印のようなものですから、これに力をかけて、処理してやると、キーウィはそちらの方向に押し出されます。

 

 

そして前回は記述してなかったのですが、Main Cameraのインスペクタで

f:id:mad_ochi:20140331133728p:plain

 

ProjectionをOrthographicに変更しておいてください。

 

さて、これで、実行を行ってみると

f:id:mad_ochi:20140331133831p:plain

 

マウスをクリックした箇所へキーウィがよってきます。

右側をクリックすれば右側へ行きます。

 

こんな感じで、プログラムが進んでいきます。

次回は、アニメーションやら細かい部分も説明していきたいと思います。