0:00:01.290,0:00:03.940 Unity 4.3 より新たな2D機能が追加されました。 0:00:03.940,0:00:05.939 我々の作成したデモを元に、 0:00:05.939,0:00:08.290 これらの機能を解説したいと思います。 0:00:08.290,0:00:11.520 この「Tower Bridge Defence」というゲームは 0:00:11.520,0:00:13.770 宇宙人の侵略に晒されている 0:00:13.770,0:00:15.550 ロンドンのタワーブリッジを描いたデモです。 0:00:15.550,0:00:18.950 これは、スプライトのみで構成された物理駆動のゲームで、 0:00:18.950,0:00:22.210 Unityにおける2Dゲーム制作の理解に役立つのではないかと思います。 0:00:23.470,0:00:25.470 この動画では 0:00:25.470,0:00:28.180 デモの背景と前景の作り方 0:00:28.180,0:00:30.180 キャラクター、エフェクト、カメラの追従 0:00:30.180,0:00:31.630 アニメーションとスクリプトについて解説します。 0:00:31.630,0:00:35.630 まずは、Unity 2Dの基本的な操作を説明しましょう。 0:00:36.860,0:00:40.290 まず、2D機能を使うにあたって 0:00:40.290,0:00:42.220 「Editor Behaviour Mode」を2Dにしてください。 0:00:43.040,0:00:45.040 新規プロジェクトウィザードのドロップダウン 0:00:45.040,0:00:48.040 またはメニューから[br]Edit > Project Settings > Editor 0:00:48.040,0:00:50.540 で設定出来ます。 0:00:53.170,0:00:55.170 この設定により 0:00:55.170,0:00:57.170 インポートされたテクスチャーはデフォルトでスプライトに設定され、 0:00:57.170,0:00:59.630 「Scene View」のデフォルトの表示は2Dになります。 0:00:59.630,0:01:01.630 このモードでは2Dゲーム制作を行いやすい様に 0:01:01.630,0:01:04.420 ビューは並行投影になります。 0:01:04.420,0:01:06.800 そして、ビューの右上に表示されている3D Gizmoが非表示になり、 0:01:06.800,0:01:09.190 より広いスペースを使えるようになります。 0:01:09.190,0:01:11.940 この設定以外の点では 0:01:11.940,0:01:16.240 2Dのワークフローは従来の3Dゲームを作るアプローチとよく似ています。 0:01:17.040,0:01:20.040 なので、既にUnityを使ったことがある方なら 0:01:20.040,0:01:22.040 すぐに2Dゲームを作ることができると言うことです。 0:01:22.920,0:01:24.920 また、2Dと3Dの要素は混在できるので 0:01:24.920,0:01:27.210 2Dゲームに3Dの要素を加える事も 0:01:27.210,0:01:31.720 またその逆に3Dのゲームに2Dの要素を加えることもできます。 0:01:33.360,0:01:35.490 ではデモプロジェクトを元に 0:01:35.490,0:01:39.310 我々がどのようにステージを作成したのかを見てみましょう。 0:01:40.810,0:01:42.810 まず、Photoshopでステージ構成の概要を作成し 0:01:42.810,0:01:44.810 そこからレイアウトを決めました。 0:01:45.310,0:01:47.310 レイヤー毎に書き出す事で、 0:01:47.310,0:01:50.310 Unityのスプライトタイプとしてインポートできます 0:01:58.370,0:02:01.300 背景を視点に応じて移動させるため 0:02:01.300,0:02:03.660 いくつかの背景要素は別にして 0:02:03.660,0:02:06.510 Background Sorting レイヤーに配置します。 0:02:06.510,0:02:09.650 これはUnityの新たなもう一つの2D開発機能です。 0:02:10.150,0:02:12.840 このレイヤーにすべての背景を追加する事で、 0:02:12.840,0:02:15.150 Order In LayerというSprite Rendererのプロパティで 0:02:15.150,0:02:17.370 一括して描画順番を変更する事ができます。 0:02:17.370,0:02:19.370 配置位置が決まったなら 0:02:19.370,0:02:21.370 Sorting Layerの”Background”をロックする事で 0:02:21.370,0:02:23.370 前景の要素を追加するときに 0:02:23.370,0:02:27.370 間違えて背景を動かせることを予防できます。 0:02:27.750,0:02:29.750 右上のLayersドロップダウンで 0:02:29.750,0:02:31.750 この設定を指定できます。 0:02:32.810,0:02:35.530 背景は飾りの要素だけですので、 0:02:35.530,0:02:37.530 スプライト以外のコンポーネントは必要ありません。 0:02:37.530,0:02:39.530 背景オブジェクトの親オブジェクトには 0:02:39.530,0:02:41.530 視点に応じて位置を操作する 0:02:41.530,0:02:46.200 BackgroundParallaxという単純なスクリプトが追加してあります。 0:02:46.200,0:02:48.640 このスクリプトに関しての詳しい説明は 0:02:48.640,0:02:50.640 Scriptsフォルダにあるスクリプトのコメントを参照して下さい。 0:02:54.910,0:02:58.910 次は、前景の要素、キャラクターの作成です。 0:02:59.790,0:03:02.280 デザインはロンドンのタワーブリッジの中に 0:03:02.280,0:03:03.460 UFOが着陸した状況です。 0:03:03.460,0:03:05.460 プレイヤーはフィールド内を動き回り、 0:03:05.460,0:03:07.460 敵は空から登場して 0:03:07.460,0:03:09.210 フィールドの中を移動します。 0:03:09.210,0:03:11.210 そういった、キャラクターの移動のために、 0:03:11.210,0:03:13.630 各前景の部分にはコライダーが必要です。 0:03:13.630,0:03:17.630 大体のフィールドには2DのBox Colliderで良いのですが、 0:03:17.630,0:03:20.630 UFOの形はかなり複雑です。 0:03:22.500,0:03:24.500 UnityのPolygon Colliderはスプライトの形に基づき 0:03:24.500,0:03:28.700 自動的にコライダーを作成してくれます。 0:03:28.720,0:03:32.050 また、生成されたコライダーの形を手動で調整する事も可能です。 0:03:32.050,0:03:34.160 ポイントの移動、追加、削除で 0:03:34.160,0:03:38.160 コライダーの形を歩かせるのに適切な形にします。 0:03:38.660,0:03:40.660 前景を背景より手前に表示するために 0:03:40.660,0:03:43.150 Tags and Layersマネジャーに 0:03:43.150,0:03:45.590 "Foregrounds"ソートレイヤーを作成してあります。 0:03:48.870,0:03:50.870 次は、プレイヤーキャラクターを見てみましょう。 0:03:53.700,0:03:55.590 プレイヤーキャラクターもPhotoshopでデザインしました。 0:03:55.590,0:03:58.590 2Dゲームに合うように 0:03:58.590,0:04:02.590 Raymanの様に手足が独立したデザインです。 0:04:03.590,0:04:07.590 もしくは、スプライトアニメを用いた[br]コマアニメーションで表現する事も可能です。 0:04:08.140,0:04:12.640 そのアプローチは後で背景の鳥に使用します。 0:04:15.070,0:04:17.070 キャラクターの手足を別々に動かしたいので 0:04:17.070,0:04:20.190 Unityが別のスプライトとしてインポートされる様に 0:04:20.190,0:04:26.190 それぞれ分割して配置します。 0:04:27.000,0:04:32.760 これにより、全てのスプライトを独立的に動く様に配置する事ができます。 0:04:33.090,0:04:35.490 新しい"Character"ソートレイヤーに配置して 0:04:35.490,0:04:40.160 PositionのZの値を入力して描画順を設定します。 0:04:48.810,0:04:50.810 プレイヤーキャラクターのスプライトは空のGameObjectの子供に設定し 0:04:50.810,0:04:52.810 親のオブジェクトにはコントロールスクリプト、コライダー、 0:04:52.810,0:04:56.590 フィジックス、その他を付加します。 0:04:56.590,0:04:58.590 その後、新しくなったAnimation Windowで 0:04:58.590,0:05:03.040 待機、移動、ジャンプ、攻撃、死亡の時の 0:05:03.040,0:05:06.900 各スプライトのパーツの動きを設定します。 0:05:07.090,0:05:09.790 Animation windowのDopesheetビューを使う事で 0:05:09.790,0:05:11.790 簡単に設定ができます。 0:05:13.410,0:05:16.000 親オブジェクトにアニメーションを追加して 0:05:16.000,0:05:19.400 子オブジェクトのKeyframeを作成します。 0:05:19.400,0:05:21.400 再生位置を動かし、キャラクターのパーツを動かして 0:05:21.400,0:05:25.400 自動的にKeyframeを作ってアニメーションを作る事ができます。 0:05:27.310,0:05:29.640 CurveとDopesheet、2つの表示を切り替える事で 0:05:29.640,0:05:36.730 タイミング及びデザインを調整も 0:05:36.730,0:05:38.730 完成したアニメーションを 0:05:38.730,0:05:43.370 ステートマシーンを使って切り替える事が出来ます。 0:05:45.270,0:05:47.270 キャラクターのAnimator Controllerは[br]bipedを使用していないので 0:05:47.270,0:05:50.570 Apply Root Motionのチェックを解除して 0:05:50.570,0:05:53.670 Animate Physicsを有効にします。 0:05:53.670,0:05:57.670 これで、物理エンジンで正しくアニメーションされる様になります。 0:05:57.760,0:05:59.850 フィールド上を移動する為に 0:05:59.850,0:06:02.230 プレイヤーの足元にはCircle Colliderがあります。 0:06:02.230,0:06:04.560 また、体を囲うBox Colliderもあります。 0:06:04.560,0:06:07.060 これにより、段差をスムーズに乗り越える事ができ 0:06:07.060,0:06:09.450 ジャンプの時は頭が天井にをぶつかるようになります。 0:06:09.800,0:06:12.530 キャラクターのアニメーションを制御するために、 0:06:12.530,0:06:16.030 2Dフィジックスで動かすスクリプトを作りました。 0:06:16.030,0:06:18.030 フィジクスを使ってキャラクターと 0:06:18.030,0:06:20.030 敵を動かしてもっとダイナミックな 0:06:20.030,0:06:21.420 ゲームプレーが可能になります。 0:06:21.420,0:06:23.810 キャラクターのPlayerControlスクリプトでは 0:06:23.810,0:06:25.810 プレイヤーの入力をチェックします。 0:06:25.810,0:06:27.810 入力は物理制御を通してキャラクターを移動させ、 0:06:27.810,0:06:30.760 また、この入力をAnimatorに渡し 0:06:30.760,0:06:33.480 ステートから正しいアニメーションを選択して 0:06:33.480,0:06:37.470 それぞれのアニメーション間をスムーズに遷移させます。 0:06:40.470,0:06:43.470 アニメーションからステートを作成すると便利な点は 0:06:43.470,0:06:47.470 物理の速度に応じてアニメーションの速度を変化させられる事です。 0:06:47.470,0:06:51.860 速度に応じてアニメーションを切り替える必要はありません。 0:07:23.120,0:07:25.120 FixedUpdateという関数は物理更新の毎に呼び出されます。 0:07:25.120,0:07:28.580 この関数で水平方向の入力を取得し、 0:07:28.580,0:07:32.580 AnimatorのSpeedパラメータに入れます。 0:07:35.950,0:07:37.950 ステートマシーンの待機と移動間の遷移条件は 0:07:37.950,0:07:41.710 Speedパラメータが0.1以上かどうか、になります。 0:07:41.710,0:07:44.020 その状況になると、アニメーターは待機のステートから 0:07:44.020,0:07:46.020 移動のステートにブレンドします。 0:07:51.850,0:07:54.850 次は、プレイヤーのRigidbody2Dという2D物理要素に 0:07:54.850,0:07:58.180 力を加えてプレイヤーを動かします。 0:07:59.620,0:08:02.520 キャラクターの向いている向きを制御するのにも 0:08:02.520,0:08:06.700 水平方向の入力を利用します。 0:08:07.710,0:08:10.550 Unityでは、左キーを押すと-1が返り 0:08:10.550,0:08:14.570 右キーを押すと+1が返ってきます。 0:08:15.070,0:08:18.700 入力された値に応じて、Flip()関数で 0:08:18.700,0:08:21.470 キャラクターのXスケールを反転させて 0:08:21.470,0:08:24.560 反対側を向いている状態を表現します。 0:08:26.840,0:08:28.840 地面を接地しているかどうかを決めるために、 0:08:28.840,0:08:31.600 Groundというレーヤーを追加して 0:08:31.600,0:08:34.980 すべての歩ける地面に適用します。 0:08:43.390,0:08:45.960 そして2DのLinecastという関数を使い 0:08:45.960,0:08:47.960 キャラクターの足元にGroundレイヤーがあるかどうかを 0:08:47.960,0:08:50.230 チェックできます。 0:08:50.230,0:08:52.770 より簡単に変更できるようにするため、 0:08:52.770,0:08:54.770 接地判定用の空のGameObjectを追加しました 0:08:56.770,0:08:59.080 この空GameObjectにGizmoを追加する事で 0:08:59.080,0:09:01.080 接地判定の距離を調整できます。 0:09:03.080,0:09:05.480 ゲーム中は 0:09:05.480,0:09:07.950 キャラクターは地面に設置している状況でのみでジャンプできます。 0:09:08.450,0:09:10.450 プレイヤーの制御の詳細は、 0:09:10.450,0:09:12.640 スクリプトのコメントを確認してみてください。 0:09:12.640,0:09:15.640 プレイヤーの攻撃に関しては後ほどお話したいと思います。 0:09:15.870,0:09:17.870 次は、このデモで 0:09:17.870,0:09:19.870 カメラがどのような動きをするか見てみましょう。 0:09:21.290,0:09:24.350 2Dゲームにおいても、3Dゲームと変わらず 0:09:24.350,0:09:27.350 カメラの動作はとても重要です。 0:09:27.820,0:09:30.580 古典的2Dアクションのカメラを学ぶために 0:09:30.580,0:09:35.620 スーパーファミコンのスーパーマリオワールドを見てみましょう。 0:09:36.650,0:09:38.650 スーパーマリオワールドでは 0:09:38.650,0:09:42.650 カメラは横方向に追従しますが 0:09:42.650,0:09:47.650 画面の中心にはキャラクターに追従しない遊び幅があります。 0:09:49.340,0:09:51.630 この遊び幅の外側に動こうとすると 0:09:51.630,0:09:54.040 カメラはプレイヤーの位置に追従します。 0:09:54.040,0:09:56.860 高さ方向に対しては一定段階の高さを保ちますが、 0:09:56.860,0:09:59.540 我々のゲームに関してはその必要はありません。 0:09:59.540,0:10:03.540 ステージの横幅はそれほど長くなく 0:10:03.540,0:10:05.870 殆どが画面に収まる広さのステージです。 0:10:07.210,0:10:11.210 ですので、カメラの水平の動きと垂直の動きは同じ動きにします。 0:10:18.770,0:10:20.770 mainCameraのGameObjectに付属している 0:10:20.770,0:10:23.130 CameraFollowというスクリプトを見てみましょう。 0:10:23.130,0:10:25.130 どのような働きをするのか、コメントを確認してください。 0:10:26.130,0:10:28.840 色々な機能の中で最も重要なことは 0:10:28.840,0:10:30.840 ヒーローの宇宙人を倒す能力です。 0:10:32.730,0:10:36.330 ヒーローのバズーカは発砲後の反動アニメーションがあります。 0:10:36.330,0:10:38.890 このアクションはいくつかの部分に分かれています。 0:10:38.890,0:10:41.640 Fireキーの入力があると 0:10:41.640,0:10:43.960 ロケットを発射して、オーディオを再生して 0:10:43.960,0:10:47.960 アニメーションステートを再生します。 0:10:47.960,0:10:49.960 もっと詳しく調べてみましょう。 0:10:49.960,0:10:52.410 Runや他のアニメーションの再生中に 0:10:52.410,0:10:54.410 Shootアニメーションを再生するのため、 0:10:54.410,0:10:57.410 Shootingという別のレイヤーを作成しました。 0:10:57.670,0:10:59.670 Weightプロパティを1にすると 0:10:59.670,0:11:02.530 Shootingレイヤーに含まれるパーツは 0:11:02.530,0:11:06.530 ベースレイヤーの動きを完全に上書きします。 0:11:20.490,0:11:22.490 このレイヤーは、プログラムからShootトリガーを呼び出されると 0:11:22.490,0:11:25.350 いつでもShootアニメーションに切り替わります。 0:11:27.350,0:11:30.540 Gunスクリプトのこの機能を調べてみましょう。 0:11:32.700,0:11:35.140 ここで、アニメーターを操作して 0:11:35.140,0:11:37.400 ShootトリガーをTrueにします。 0:11:37.400,0:11:40.510 トリガーはスイッチのように 0:11:40.510,0:11:43.240 次のフレームにFalseに戻り、再び使用できるようになります。 0:11:43.240,0:11:45.510 これは攻撃のようなアクションにぴったりです。 0:11:46.010,0:11:48.670 アニメーションをセットし、 0:11:48.670,0:11:50.670 ロケットもこのスクリプトで発射します。 0:11:50.670,0:11:52.670 オーディオを再生して 0:11:52.670,0:11:54.670 プレイヤーの向いている方向に対して 0:11:54.670,0:11:59.770 ロケットの速度を設定します。 0:12:01.270,0:12:03.930 このスクリプトはヒーローの 0:12:03.930,0:12:05.290 Gunという空のGameObjectに付属します。 0:12:05.290,0:12:08.070 空のGameObjectにスクリプトを追加するのは、 0:12:08.070,0:12:11.070 簡単にロケットの発射位置を設定できるようにするためです。 0:12:11.660,0:12:15.660 バズーカの先に空のGameObjectを配置して 0:12:15.660,0:12:21.010 オブジェクトの位置にロケットが生成されるようにします。 0:12:40.240,0:12:42.800 ロケットは2DRigidbodyを持って 0:12:42.800,0:12:46.800 それに速度を与えて動かします。 0:12:46.800,0:12:51.090 スプライトの排気炎を付け 0:12:51.090,0:12:53.090 パーティクルシステムの煙も足します。 0:12:54.880,0:12:58.480 パーティクルシステムも新たなスプライト版機能が追加されました。 0:12:58.480,0:13:02.480 煙のコマが描かれたスプライトをマテリアルに追加する事で 0:13:02.480,0:13:07.140 簡単にスプライトアニメーションのパーティクルを作成できます。 0:13:16.120,0:13:18.930 敵またはフィールドにロケットが当たると 0:13:18.930,0:13:20.930 ロケットは消え 0:13:20.930,0:13:22.930 爆発が生成されます。 0:13:22.930,0:13:25.930 爆発は単純なコマアニメーションを行うスプライトです。 0:13:27.730,0:13:32.310 Sorting Layerで前景の最後に描画されるようにします。 0:13:36.170,0:13:38.170 このようなスプライトに基づいたアニメーションの追加は、 0:13:38.170,0:13:40.170 Project Panelからファイルを選んで 0:13:40.170,0:13:43.170 Sprite Modeを"Multiple"にします。 0:13:44.570,0:13:46.570 これでスプライトエディタを使い 0:13:46.570,0:13:49.750 手動、もしくは自動的に分割する事ができます。 0:13:49.750,0:13:52.400 ファイルをスプライトに設定する利点は、 0:13:52.400,0:13:54.400 この様にApplyをクリックするだけで 0:13:54.400,0:13:56.760 Unityはファイルの子供としてそれぞれのスプライトを生成し 0:13:56.760,0:13:58.760 そのスプライトをそのまま使う事が出来ます。 0:13:59.700,0:14:01.690 これがロケットの構造です。 0:14:01.690,0:14:03.690 どのようにして敵を倒すのかは、 0:14:03.690,0:14:06.530 後ほど敵の項目でお話したいと思います。 0:14:07.100,0:14:09.440 話をプレイヤーキャラクターに戻して 0:14:09.440,0:14:12.190 HPとダメージのことを調べましょう。 0:14:12.190,0:14:14.190 HPはfloatとして保存されています。 0:14:14.190,0:14:18.190 敵からのダメージはTakeDamage関数を呼び出して与えます。 0:14:18.540,0:14:20.540 プレイヤーが簡単に倒されてしまうのを避けるため、 0:14:20.540,0:14:22.540 前回のダメージからrepeatDamagePeriodが経過した場合のみ 0:14:22.540,0:14:25.340 ダメージを受けます。 0:14:26.520,0:14:29.130 また、敵から逃げ易くするため、 0:14:29.130,0:14:31.130 そしてプレイヤーのダメージを表現するため、 0:14:31.130,0:14:34.130 ダメージを受けたキャラクターをヒットバックさせます。 0:14:34.840,0:14:40.540 TakeDamage関数で一時的にプレイヤーのジャンプを止め、 0:14:40.540,0:14:44.540 敵からキャラクターへの方向に物理的な力を与えて動かします。 0:14:46.120,0:14:50.680 hurtForceの変数はInspectorで表示しているので、 0:14:50.680,0:14:55.320 スクリプトを編集せずにゲーム要素の調整が出来ます。 0:14:55.320,0:14:57.320 ダメージ表現に加えて 0:14:57.320,0:14:59.810 もちろんプレイヤーのHPも減らした上で 0:14:59.810,0:15:02.200 HPバーを更新します。 0:15:02.200,0:15:06.620 HPの差を表示するのためにバーの長さを縮め 0:15:06.620,0:15:08.880 色を緑から赤に補間します。 0:15:09.820,0:15:14.640 最大HPに対する現在のHPの比率を計算すれば出来ますね。 0:15:14.640,0:15:17.870 HPバーはシンプルなスプライト2つで構成されています。 0:15:17.870,0:15:20.960 バーの外周部分とバーの部分です。 0:15:21.740,0:15:23.740 これらもPhotoshopでデザインして 0:15:23.740,0:15:25.950 2つのテクスチャを書き出しました。 0:15:25.950,0:15:27.950 このスプライトのImport Settingsで 0:15:27.950,0:15:30.470 Pivotを左の中央に設定して 0:15:30.470,0:15:34.050 スケールを小さくした時に左側に縮んでいく様にします。 0:15:48.570,0:15:50.570 この2つのスプライトは 0:15:50.570,0:15:52.570 プレイヤーに追従するスクリプトを追加した 0:15:52.570,0:15:54.570 空のGameObjectの子供として配置します。 0:15:54.570,0:15:58.620 プレイヤーのGameObjectの位置とオフセットを足すので 0:15:58.620,0:16:00.620 表示位置はInspectorで調整できます。 0:16:16.210,0:16:18.210 プレイヤーは残りHPが0になると 0:16:18.210,0:16:20.210 コライダーをトリガーモードに設定されるので 0:16:20.210,0:16:22.620 プレイヤーはステージを突き破って落ちます。 0:16:22.620,0:16:24.620 その時、最前面に描画される様に 0:16:24.620,0:16:30.190 SpriteRendererを”UI”ソートレイヤーに移動させます。 0:16:31.590,0:16:34.220 プレイヤーの死亡アニメーションは、2段階で構成されます。 0:16:34.220,0:16:37.250 最初の”Death”は、帽子と武器を落とします。 0:16:37.250,0:16:38.630 2番目は”Falling”という名前です。 0:16:38.630,0:16:40.630 アニメータにExit Timeのコンディションを使って 0:16:40.630,0:16:44.000 ”Death”アニメーションが終わると 0:16:44.000,0:16:47.230 自動的に”Falling”に遷移します。 0:16:50.770,0:16:52.770 最後に、プレイヤの動きと攻撃を停止させるために 0:16:52.770,0:16:57.270 PlayerControlとGunのスクリプトを無効にします。 0:16:58.340,0:17:00.730 Die関数はPublicなので 0:17:00.730,0:17:03.330 どこからでも呼び出せます。 0:17:03.330,0:17:05.040 例えば、水に落ちた時。 0:17:05.040,0:17:07.730 プレイヤーが水に落ちるとゲームをリセットするために、 0:17:07.730,0:17:09.730 トリガーコライダーとスクリプトだけがある 0:17:09.730,0:17:12.460 KillTriggerという名前のGameObjectがあります。 0:17:12.460,0:17:15.010 Removerスクリプトには 0:17:15.010,0:17:17.010 川にザブンと飛び込んだ敵を消して 0:17:17.010,0:17:20.780 飛沫のアニメーションとサウンドを再生する役割があります。 0:17:21.440,0:17:24.000 しかしこのコライダーにプレイヤーが衝突すると 0:17:24.000,0:17:27.089 PlayerHealthスクリプトの”Die”関数呼び出して 0:17:27.089,0:17:30.090 プレイヤーを画面外に動かしている間カメラの追従を無効にし、 0:17:30.090,0:17:35.090 2秒後にステージをリセットするコルーチンを実行します。 0:17:37.070,0:17:39.070 さて、プレイヤーキャラクターの死について考えるのではなく、 0:17:39.070,0:17:42.070 彼が生き残るために何をあげればいいかを考えましょう。 0:17:42.480,0:17:47.480 このゲームでは2種類のプレイヤーを助けるアイテムボックスが落下してきます。 0:17:47.480,0:17:49.910 一つは爆弾、もう一つは救急箱です。 0:17:50.410,0:17:52.960 このアイテムは2つの部分で構成されています。 0:17:52.960,0:17:55.690 箱本体と落下傘の部分です。 0:17:58.040,0:18:03.310 これらの要素は空のオブジェクトでグループにして動かす事ができます。 0:18:03.760,0:18:07.760 落下傘の中心を親オブジェクトの中心に位置します。 0:18:09.040,0:18:14.900 これで箱を、落下中左右に揺れるようにできます。 0:18:15.300,0:18:17.300 オブジェクトが落下させる為には 0:18:17.300,0:18:19.300 単にRigidbodyを追加するだけです。 0:18:19.300,0:18:22.300 そして、箱の着地やプレイヤーの取得を検出する為に 0:18:22.300,0:18:24.300 コライダーも追加します。 0:18:24.960,0:18:26.960 箱が着陸したら 0:18:26.960,0:18:30.510 落下傘をしぼませるステートに遷移します。 0:18:30.510,0:18:33.300 他のアニメータと同じ様に 0:18:33.300,0:18:34.910 アニメーターはオブジェクトのステートを管理しています。 0:18:34.910,0:18:36.910 デフォルトではfloatDownステートですが 0:18:36.910,0:18:42.910 LandトリガーがTrueになると着陸のステートに切り替わります。 0:18:43.970,0:18:47.380 この処理はスクリプトのonTriggerEnter関数で実行しています。 0:18:47.380,0:18:49.730 タグで地面を見て地面かどうかを判断しています。 0:18:49.730,0:18:53.820 箱を親オブジェクトからデタッチし、 0:18:53.820,0:18:55.090 Rigidbodyを追加します。 0:18:55.090,0:18:57.490 それにより、地形の影響を受け 0:18:57.490,0:19:00.620 斜面に着陸した場合でも正しい角度で停止します。 0:19:00.620,0:19:03.670 さて、爆弾を見てみましょう。 0:19:03.670,0:19:05.670 爆弾を取得する処理は 0:19:05.670,0:19:08.470 箱に付属したBombPickupスクリプトで行われます。 0:19:08.470,0:19:11.050 爆弾を拾うと、箱を消して 0:19:11.050,0:19:14.050 プレイヤーに付属したLayBombsスクリプト内の 0:19:14.050,0:19:17.050 爆弾を持つ数を加算します。 0:19:17.550,0:19:19.550 LayBombsのスクリプトは 0:19:19.550,0:19:22.550 プレイヤーが爆弾を持っているかどうかをチェックして 0:19:22.550,0:19:24.550 BombのPrefabを生成します。 0:19:27.420,0:19:32.950 BombのPrefabはBombDetonationというcoroutineで 0:19:32.950,0:19:36.000 待ってExplode関数を呼び出します。 0:19:36.790,0:19:39.540 Explode関数は様々な動作があります。 0:19:39.540,0:19:41.540 まず、他の爆弾が出現できる様にするため 0:19:41.540,0:19:43.790 変数bombLaidをリセットします。 0:19:43.790,0:19:46.790 そしてアイテム管理に新しい箱が追加可能な事を通知し 0:19:46.790,0:19:49.790 範囲内にいる全ての敵を倒します。 0:19:50.510,0:19:53.050 最後の部分がどのような働きをするのか注目して下さい。 0:19:53.050,0:19:55.050 残りHPに関係なく全ての敵を倒すために 0:19:55.050,0:19:57.180 Physics.OverlapCircleAllを使って 0:19:57.180,0:20:02.970 全てのEnemyタグが付けられたオブジェクトを取得します。 0:20:03.470,0:20:08.610 foreachループで見つかった全ての敵のHPを0にして 0:20:08.610,0:20:13.660 爆弾から敵の方向に吹き飛ばします。 0:20:16.300,0:20:18.530 ループが終わったら 0:20:18.530,0:20:21.380 エフェクトを再生し[br]爆発の効果音を再生して 0:20:21.380,0:20:24.380 爆弾を消去します。 0:20:26.870,0:20:29.250 爆発には2つの要素で構成されています。 0:20:29.250,0:20:32.250 主な部分は、一時的に登場して消える丸です。 0:20:33.580,0:20:35.580 2番目の部分はロケットの爆発のスプライトを再利用した 0:20:35.580,0:20:38.580 星のパーティクルです。 0:20:42.260,0:20:44.260 効率よくこのパーティクルを使用するために 0:20:44.260,0:20:46.260 常にシーンに配置しておき 0:20:46.260,0:20:51.260 表示させたいタイミングで表示位置に動かして再生します。 0:20:52.510,0:20:54.510 メモリにパーティクルを常駐させる事で効率が良くなります。 0:20:54.510,0:20:56.510 これは、プレイヤーは1つしか爆弾を持てない、 0:20:56.510,0:21:00.510 つまり爆発も1つしか表示されないので出来る事です。 0:21:01.010,0:21:04.660 パーティクルを常駐させておくことで 0:21:04.660,0:21:12.790 毎回パーティクルのインスタンスを生成して削除するよりも効率的です。 0:21:15.710,0:21:18.610 ですが、ロケットの爆発は一度にたくさん出る事があるので 0:21:18.610,0:21:21.610 毎回生成と削除する事が必要です。 0:21:22.110,0:21:26.110 プレイヤーが敵を倒してポイントを得る処理を見てみましょう。 0:21:26.610,0:21:28.430 これは2つのパーツでできています。 0:21:28.430,0:21:31.660 プレイヤーが100ポイントを獲得した表示と 0:21:31.660,0:21:34.660 画面の上に表示されているスコアーが加算されてゆくUIです。 0:21:35.520,0:21:39.300 得点のアニメーションは1と0のスプライトで構成されています。 0:21:40.190,0:21:42.870 空のオブジェクトの子として配置し 0:21:42.870,0:21:47.030 アニメーションが終わると簡単なスクリプトで 0:21:47.030,0:21:49.180 シーンから削除されます。 0:21:49.180,0:21:52.180 アニメーションの最後にイベントを追加し 0:21:52.180,0:21:55.180 スクリプトの削除関数を呼び出します。 0:22:06.140,0:22:09.700 ScoreUIは、カスタムフォントと 0:22:09.700,0:22:11.700 プレイヤーの得点を管理するスクリプト付属された 0:22:11.700,0:22:13.700 シンプルなGUIコンポーネントです。 0:22:13.700,0:22:16.750 Scoreはパブリック変数です。 0:22:16.750,0:22:18.980 なので敵が倒された時、 0:22:18.980,0:22:20.980 Enemyのスクリプトからポイントを追加する事ができます。 0:22:20.980,0:22:24.980 さて、今度は敵の話です。[br]詳細を見てみましょう。 0:22:25.480,0:22:28.260 このゲームには2種類の敵が登場します。 0:22:28.260,0:22:30.850 緑のナメクジモンスターと 0:22:30.850,0:22:33.850 宇宙船に乗った宇宙人です。 0:22:34.560,0:22:40.560 挙動はほぼ同じなので同じスクリプトを使い回し、 0:22:40.560,0:22:44.560 Inspectorから移動速度とHPを調整して差を付けています。 0:22:46.630,0:22:49.090 各敵はそれぞれのWalkアニメーションがあります。 0:22:49.090,0:22:51.090 ナメクジには動く尾があり 0:22:51.090,0:22:54.440 宇宙船の敵は行ったり来たりします。 0:22:55.990,0:22:57.990 ナメクジの尾の部分は 0:22:57.990,0:23:01.990 スプライトインポータで独立したパーツとしてインポートしました。 0:23:01.990,0:23:04.430 なので、尾の部分を独立して動かす事ができ、 0:23:04.430,0:23:07.470 スプライト全体が伸び縮みししないようになっています。 0:23:07.470,0:23:09.470 Pivotを右にする事で 0:23:09.470,0:23:14.120 そこから尾が伸び縮みするアニメーションをつけます。 0:23:16.470,0:23:19.910 まぶたを上下に動かして 0:23:19.910,0:23:21.910 Z値でスプライトがソートされるようにし 0:23:21.910,0:23:25.850 目がまぶたの下に表示されるようにします。 0:23:28.860,0:23:31.260 次の敵はかなりシンプルです。 0:23:31.260,0:23:34.040 行ったり来たりを繰り返すアニメーションにします。 0:23:35.790,0:23:39.790 敵の動きには、Rigidbodyの速度をセットします。 0:23:41.220,0:23:43.880 宇宙船が障害物、例えば壁等への衝突は 0:23:43.880,0:23:47.820 ある点がコライダーと重なっているかどうかを 0:23:47.820,0:23:51.310 Physics.OverlapPoint関数を用いて検知します。 0:23:51.310,0:23:53.850 障害物、このステージ両端のタワーは 0:23:53.850,0:23:55.850 障害物としてタグが設定されています。 0:23:55.850,0:23:59.160 衝突を検知するとFlip関数を呼び出して 0:23:59.160,0:24:03.760 敵のXスケールを反対にして反対方向に向かわせます。 0:24:04.070,0:24:06.070 敵を倒す判定のために、 0:24:06.070,0:24:11.030 ロケットが敵に当たる度にHurt関数を呼び出します。 0:24:14.960,0:24:18.960 この関数の内部では、敵のHPを1づつ下げています。 0:24:19.210,0:24:23.210 FixedUpdate関数の中で敵のHPを監視しており、 0:24:23.210,0:24:27.120 0になっている場合はDeath関数が呼び出されます。 0:24:31.220,0:24:33.910 敵が死亡する時には様々な処理が実行されます。 0:24:33.910,0:24:39.910 まず、2Dのキャラクターの全てのスプライトを非表示にします。 0:24:40.940,0:24:42.940 これは、アニメーションのためにある複数のスプライトを 0:24:42.940,0:24:46.940 1つの死亡したキャラクターのスプライトに差し替えたいからです。 0:24:47.740,0:24:51.740 メインのSprite RendererにdeadEnemyのスプライトを設定します。 0:24:54.160,0:24:58.160 Scoreスクリプトのパブリック変数に対し[br]スコアを加算します。 0:24:58.160,0:25:00.740 敵の死亡のビジュアルをわかりやすくするため 0:25:00.740,0:25:03.530 Rigidbodyにトルクを追加して回転させます。 0:25:04.440,0:25:08.440 背景を突き抜けて川に落下させたいので 0:25:08.880,0:25:10.880 すべてのコライダーを探して 0:25:10.880,0:25:13.580 IsTriggerパラメーターをTrueにします。 0:25:13.580,0:25:17.130 これで背景のコライダーを突き抜ける事になります。 0:25:17.410,0:25:21.050 死亡時に再生するオーディオクリップ中の1つを選び再生し 0:25:21.050,0:25:25.050 前述の得点表示アニメーションを再生します。 0:25:27.870,0:25:29.870 敵をシーンから削除するため、 0:25:29.870,0:25:31.870 KillTriggerオブジェクトを使います。 0:25:31.870,0:25:34.760 これは先ほど説明した通り、[br]水しぶきをあげオブジェクトを消去する機能を持ちます。 0:25:34.760,0:25:36.760 プレイヤー以外のオブジェクトが触ると 0:25:36.760,0:25:39.950 水しぶきのエフェクトを表示して[br]オブジェクトを削除します。 0:25:39.950,0:25:42.950 効果音は水しぶきエフェクトが表示される時に 0:25:42.950,0:25:45.950 付属しているAudio Clipが同時に再生されます。 0:25:45.950,0:25:47.950 なので、オブジェクトを生成するだけで 0:25:47.950,0:25:50.630 効果音も鳴るようになっています。 0:25:55.150,0:25:57.150 動的なオブジェクトを追加し 0:25:57.150,0:26:01.150 背景を飾ってステージを完成させましょう。 0:26:02.300,0:26:05.700 飛んでいる白鳥と 0:26:05.700,0:26:07.120 川岸を走るバスとタクシーを追加します。 0:26:07.120,0:26:12.630 まずは白鳥のスプライトシートをPhotoshopで描いて 0:26:12.630,0:26:14.630 InspectorのMultiple Sprite Modeを使ってインポートしました。 0:26:16.050,0:26:18.800 この方法では 0:26:18.800,0:26:21.800 Unityが全てのコマを選択し自動的にインポートして 0:26:21.800,0:26:24.800 アセットのヒエラルキーに追加してくれます。 0:26:24.570,0:26:27.270 このコマは連続したアニメーションのセットなので、 0:26:27.270,0:26:29.270 全てのコマをシーンにドラッグするだけで 0:26:29.270,0:26:32.340 Unityが自動的にアニメーションさせてくれます。 0:26:32.340,0:26:35.310 ね、簡単でしょ? 0:26:35.310,0:26:37.750 白鳥は背景に追加します。 0:26:37.750,0:26:40.160 速度を与えて画面中を動けるように 0:26:40.160,0:26:43.160 Rigidbody2Dを追加します。 0:26:43.360,0:26:47.330 バスとタクシーのように、白鳥もPrefabです。 0:26:49.250,0:26:51.250 バスとタクシーのPrefabには、 0:26:51.250,0:26:54.250 Sprite Importerで車体とタイヤを分割して 0:26:54.250,0:26:57.250 シンプルなアニメーションを生成します。 0:26:58.390,0:27:01.790 これらにもRigidbody2Dを追加して 0:27:01.790,0:27:03.790 速度の追加で画面内を動かす事ができます。 0:27:07.270,0:27:10.270 白鳥、バス、タクシー 0:27:10.270,0:27:12.270 この3種のオブジェクトの生成を 0:27:12.270,0:27:14.270 管理するスクリプトを作成してあります。 0:27:14.270,0:27:17.610 BackgroundPropsSpawnerスクリプトは 0:27:18.610,0:27:21.830 頻度、速度、そして最初の位置を管理しています。 0:27:21.830,0:27:26.520 3種のオブジェクトに同じスクリプトを使うことができます。 0:27:26.520,0:27:28.520 生成するPrefabとプロパティを変更します。 0:27:30.520,0:27:35.850 詳細は、スクリプトのコメントをご覧ください。 0:27:36.170,0:27:40.400 最後に、動いている雲、川の流れ、そして霧を追加しました。 0:27:41.320,0:27:44.520 親オブジェクトに2つのスプライトを持たせ、 0:27:44.520,0:27:48.000 ゆっくりと横に動かします。 0:27:50.000,0:27:54.650 アニメーションはループで動き続けます。 0:27:59.180,0:28:02.030 以上が、私たちがどのようにしてこのゲームを作ったか、の全てです。 0:28:02.030,0:28:05.030 このビデオが2Dゲームの作り方の参考になれば嬉しく思います。 0:28:05.510,0:28:07.510 将来的には、より基本的なプロジェクトと 0:28:07.510,0:28:08.970 チュートリアルをお届けしたいと考えています。 0:28:08.970,0:28:12.680 私達は、Unity4.3についての感想と 0:28:12.680,0:28:14.680 あなたの作る素晴らしい2Dゲームが本当に楽しみです。 0:28:14.950,0:28:16.480 それでは、ご清聴ありがとうございました!