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