【Unity 入門】2時間で作るユニティちゃんRunゲーム!
「Unityを始めたばかりで何から始めれば良いかわからない…」そんな方に向けて、Unityの使い方を楽しく学んでもらうために『ユニティちゃんRunゲーム』の作成方法をご紹介します!
初心者の方にもわかるように詳しく解説していきますが、基本的な部分に関しては2時間程度で終わるような内容ですのでぜひチャレンジしてみてください!
時間がない方は3部構成になっているので第1部のみを進めていただければ、Unityを簡易的に体験していただくことができますのでそちらにチャレンジしてみてください。
※Unityでの基本操作が全くわからないという方は以下記事をご参考ください。
参考記事① Unityの魅力
参考記事② Unity環境構築
この作品はユニティちゃんライセンス条項の元に提供されています
概要
今回は3部構成で作成していきます。
第1部〜第2部までを基本部分としてここまでを2時間でご理解いただく構成となっています。第3部はゲームのクオリティを上げるためのおまけ的な章です。
第1部では迷路ゲームの基礎部分を作成します。スタートからゴールまでの一連の流れをあらかじめ作成しておくことで、好きなようにアレンジできます。
第2部では障害物や追いかけてくる敵を作成します。障害物などの作り方を覚えてしまえば、あとは自分好みのキャラクターや障害物にすることでオリジナリティのあるゲームを作成することができます。よりクオリティの高いゲームを作成してみたいという方はぜひ第3部にもチャレンジしてみてください!
第3部ではゲームのクオリティを上げるための細かいUIの設定やゴールエフェクトや背景の変更を行います。細かい部分をこだわるだけで格段にゲームのクオリティが上がります。難しいプログラムなどはほとんど出てきませんのでぜひチャレンジしてみてください!
ユーザーの前提知識は
- Unityプロジェクトの作成方法がわかる
- Unityを使ってオブジェクトを作ってみたりしたことがある
以上を想定して話を進めていきます。
Unityのセットアップが完了していない方、Unityのことが全くわからない方はUnityセットアップ・プロジェクト作成方法を参考にしてください。
第1部:スタートからゴールまで
概要でもご説明したとおり、第1部はスタートからゴールまでを作成します。
第1部はスラスラと進めることができると思います。まずは基本を理解しましょう!
目次
- プロジェクトを作成する
- シーンを保存する
- フィールドを作成する
- ユニティちゃんを使用する
- カメラを追従させる
- ゴールオブジェクトを作成する
- ゴールしたことを表示するためのテキストを作成する
- ゴール判定を行うスクリプトを作成する
プロジェクトを作成する
ゲームを作成するためにまずはUnityのプロジェクトを作成します。
Unityを立ち上げたら以下の手順でプロジェクトを作成してください。
作成すると以下ウィンドウが表示されます。
これでプロジェクトの作成は完了です。
シーンを保存する
シーンを保存します。
Unityではプロジェクトのなかにシーンというものが存在し、プロジェクトを構成します。
シーンを遷移することで色々なことを実現することができますが、ここでは詳しい解説は省略します。
ヒエラルキーウィンドウのSampleSceneを右クリックしてSaveSceneAsを選択してください。次にSaveAs欄に「Game」と入力してSaveを選択します。これでシーンの保存が完了しました。
続いて作成したシーンをScenesフォルダに保存します。
シーンやこの後出てくるC#スクリプト、プレハブをできる限りフォルダごと管理するようにしてください。
プロジェクトウィンドウのGameをドラッグ&ドロップでScenesフォルダに移動してください。
移動先のScenesフォルダのSampleSceneを削除しておきましょう。
フィールド(地面)を作成する
まずはユニティちゃんを登場させるためのフィールドを作成します。
ヒエラルキーウィンドウのCreate→3D Object→Planeを選択してください。
一度だけオブジェクトの作成手順のGIFをご紹介しますが、これ以降は省略します。
これでフィールドは完成です。
ユニティちゃんを使用する
次にユニティちゃんを使用する準備をします。
ユニティちゃんをインポートする
まずはじめにユニティちゃんをインポートします。
アセットストアで「Unity Chan」と検索して「”Unity-Chan!”Model」を選択してください。
選択したらDownloadを選択してダウンロードしてください。ダウンロードが終わっている場合はImportを選択してインポートしてください。
インポートすると以下のウィンドウが表示されますのでデフォルトのままImportを選択してください。
インポート後のプロジェクトウィンドウが以下のようになっていれば問題ありません。
これでインポートは完了です。
以降アセットストアからインポートする場合、手順は省略します。
ユニティちゃんを動かす
インポートしたユニティちゃんパッケージのunity-chan!→Unity-chan! Model→Prefabs→for Locomotion→unitychanをシーンビューにドラッグ&ドロップしてください。
座標がおかしいと感じた場合はPositionの値をX~Z全て0(ゼロ)にすると真ん中に移動してきます。
この状態で一度真ん中上にある再生ボタンを押して動きを確認してみてください。
このときAutoBlinkスクリプトにエラーが発生する場合があります。このときは8行目をコメントアウトすることでエラーを回避することができます。
1 2 3 |
//←スラッシュ2つでコメントアウトすることができる //以下が記載されている8行目をコメントアウト //using System.Security.Policy; |
エラーなく動作できた場合、上矢印キーで前へ、下矢印キーで後ろへ、右矢印キーで右回転、左矢印キーで左回転するユニティちゃんを召喚できたと思います。
たったこれだけで動くキャラクターを作れるUnityは素晴らしいですね!
次にゲームビューに表示されているUIが邪魔ですので削除します。
その前にユニティちゃんのプレハブ化を解いておきます。ここでは詳しく説明しませんが、Unityにはプレハブというものがあります。これについては以下記事で詳しく紹介していますのでそちらをご参考ください。
参考記事)プレハブについて
プレハブの解き方はヒエラルキーウィンドウのユニティちゃんを右クリックしてUnpack Prefabを選択すれば実行可能です。
ヒエラルキーウィンドウの左のキューブが青色のオブジェクトがプレハブ化されたオブジェクトですので、青から白になっていれば問題ありません。
ここからゲームビューの邪魔なUIを消していきます。
まずはじめにヒエラルキーウィンドウのユニティちゃんを選択して、インスペクターウィンドウのFaceUpdateをオフにします。
オフにする方法は左のチェックマークを外すだけです。
次にプロジェクトウィンドウのunity-chan!→Unity-chan! Model→Scripts→UnityChanControlScriptWithRgidBody.csを編集します。
UnityChanControlScriptWithRgidBody.csの181行目〜190行目のOnGUI()をコメントアウトします。
1 2 3 4 5 6 7 8 9 10 11 12 |
/* ←これで囲った部分がコメントアウトされる void OnGUI () { GUI.Box (new Rect (Screen.width - 260, 10, 250, 150), "Interaction"); GUI.Label (new Rect (Screen.width - 245, 30, 250, 30), "Up/Down Arrow : Go Forwald/Go Back"); GUI.Label (new Rect (Screen.width - 245, 50, 250, 30), "Left/Right Arrow : Turn Left/Turn Right"); GUI.Label (new Rect (Screen.width - 245, 70, 250, 30), "Hit Space key while Running : Jump"); GUI.Label (new Rect (Screen.width - 245, 90, 250, 30), "Hit Spase key while Stopping : Rest"); GUI.Label (new Rect (Screen.width - 245, 110, 250, 30), "Left Control : Front Camera"); GUI.Label (new Rect (Screen.width - 245, 130, 250, 30), "Alt : LookAt Camera"); } これで囲った部分がコメントアウトされる→ */ |
この状態でもう一度実行してゲームビューを確認すると、邪魔なUIが消えていることがわかると思います。
これでユニティちゃんの準備は完了です。
カメラを追従させる
次にユニティちゃんが動いたときに一緒にカメラも追従できるような仕様にします。
まずはじめにメインカメラをユニティちゃんの子オブジェクトに設定します。
ヒエラルキーウィンドウでMain Cameraをユニティちゃんにドラッグ&ドロップしてください。
これでユニティちゃんの座標を基準にカメラが動くようになりました。
次にカメラの位置を調整します。
今回はメインカメラのTransformの値を以下のような数値に設定しました。
以上のように第三者視点でユニティちゃんを追従できるようになりました。
カメラをシフトボタンなどでユニティちゃんの周囲を回転できるようにしたいなど、より詳しいカメラの動かし方を知りたい方は以下記事をご参考ください。
参考記事)Unityカメラの使い方
ゴールオブジェクトを作成する
次にゴールとなるオブジェクトを作成します。
ゴール判定はゴールとなるオブジェクトとプレイヤーであるユニティちゃんが接触した瞬間にゴールとなるような仕様にします。
ですのでここでは一旦球体(Sphere)を作成するのみになりますが、後ほどスクリプトを使用してゴール判定を行います。
ヒエラルキーウィンドウのCreate→3D Object→Sphereを選択して球体を作成してください。
作成したSphereの名前をインスペクターウィンドウで「Goal」に変更してください。
またPositionの数値を以下の値にしておいてください。
次にGoalオブジェクトのSphere ColliderコンポーネントのIs Triggerをオンにします。
これによってオブジェクトが物理的には触れなくても当たり判定を行うことができるようになります。
後ほど詳しく説明しますのでここではこの操作のみを行うだけで問題ありません。
ここまで設定し終えると以下のような位置関係になっていると思います。
このようになっていれば問題ありません。
ゴールしたことを表示するためのテキストを作成する
次にGoalオブジェクトとユニティちゃんが接触したときにゴールしたことを表示するためのテキストを事前に作成しておきます。
ヒエラルキーウィンドウのCreate→UI→Textを選択してください。
するとヒエラルキーウィンドウにはCanvasの子オブジェクトとしてTextが作成されます。UnityのUIは全てCanvasと呼ばれるオブジェクトの子オブジェクトとして作成されます。またEventSystemオブジェクトも作成されますが、ここではそのまま放置しておいて問題ありません。
作成したTextを選択して位置やサイズを調整します。
RectTransformのPos X~Zの値を全てゼロに変更してください。
次にTextコンポーネントの値を変更します。
- Font Size:50
- Alignment:どちらも真ん中
- Horizontal,Vertical Overflow:Overflow
これでゲームビューの真ん中にテキストが出現します。
テキストをもっとおしゃれにしたいという方は以下記事をご参考ください。
参考記事)uGUI テキストの使い方
ゴールする前からテキストがあると邪魔なので一旦非表示にしておきます。
インスペクターウィンドウの一番上のチェックマークを外しておくと非表示にすることができます。
勘の良い方はご理解いただけたと思いますが、ゴールした瞬間にこの設定をオンにすることでゴール表示を出現させます。
後ほどスクリプトにてこのテキストの内容と表示の方法をご紹介します。
ゴール判定を行うスクリプトを作成する
いよいよここからスクリプトの記述を行います。
スクリプトとはオブジェクトに指示を与えたり、オブジェクトの特定の数値を変更したり、様々なことを行うことができるので使いこなせるととても便利です。
ここでは記述してあるスクリプトをそのままコピーするだけで全く問題ありませんが、スクリプトの勉強を基礎部分からしっかりと行いたいという方は以下記事をご参考ください。
参考記事)Unityで学ぶC#入門
本題に入ります。まずはじめにスクリプト用のフォルダを作成します。
プロジェクトウィンドウのAssetsを選択してからCreate→Folderを選択してください。選択したら名前を「Scripts」としてください。
ここまでの一連の流れを今回はGIFでご紹介しますが、以降は省略します。
ここからスクリプトを作成していきます。
今回作成するスクリプトはGoalオブジェクトにアタッチするスクリプトで、ぶつかってきたオブジェクトがプレイヤー(ユニティちゃん)だった場合にゴールしたことを表示して、画面をクリックすると再びゲームがスタートする動作を作成します。
まずはスクリプトを作成します。
先ほど作成したScriptsフォルダを選択してCreate→C# Scriptを選択します。選択したら名前を「GoalManager」としてください。
入力を間違えてしまった場合は作成したスクリプトを右クリックしてRenameを選択すれば再度名前を変更することができます。
作成ができたらダブルクリックしてスクリプトを編集しましょう。
段階を踏んでスクリプトを記述していきます。
Unityの画面上からオブジェクトを登録できるようにする
まずはじめにUnity画面上からオブジェクトを登録できるようにします。
スクリプトを以下のように変更してください。
※ハイライトされた部分が追加された部分です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GoalManager : MonoBehaviour { //ユニティちゃんを格納するための変数 public GameObject player; //テキストを格納するための変数 public GameObject text; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } } |
変数がいまいちよくわからない方は以下記事をご参考ください。
参考記事)C# 変数の使い方
「GameObject」とはUnityで使われるオブジェクトそのものを指します。つまりGameObject型の変数を使うことでユニティちゃんやテキストなどのオブジェクトをスクリプト内で好きなように使用することができます。
また、GameObjectの前に「public」と記述することでUnityエディタ上からオブジェクトを登録することができます。
まずはここまで作成したスクリプトをGoalオブジェクトにアタッチしましょう。
プロジェクトウィンドウのGoalManagerスクリプトをヒエラルキーウィンドウのGoalオブジェクトにドラッグ&ドロップしてください。
今回は一連の流れをGIFでご紹介しますが、以降省略します。
これでオブジェクトにスクリプトをアタッチすることができました。
次にユニティちゃんとテキストをスクリプトにアタッチします。先ほどアタッチしたGoalManagerコンポーネントのPlayerとTextにそれぞれunitychanとtextをドラッグ&ドロップしてください。
今回は一連の流れをGIFでご紹介しますが、以降省略します。
以上のようにアタッチすることでそれぞれのオブジェクトをスクリプト上で操作することが可能になります。
当たり判定を実装する
次に当たり判定を実装します。Unityには当たり判定を行ってくれる関数がすでに準備されているのでとても簡単に当たり判定を実装することができます。
スクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GoalManager : MonoBehaviour { //ユニティちゃんを格納するための変数 public GameObject player; //テキストを格納するための変数 public GameObject text; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } //当たり判定関数 private void OnTriggerEnter(Collider other) { //当たってきたオブジェクトの名前がユニティちゃんの名前と同じとき if(other.name == player.name) { //一旦ログに出力 Debug.Log("ユニティちゃんと接触しました!"); } } } |
まずはスクリプトの変更内容について解説していきます。
26行目について、「OnTriggerEnter()」はアタッチされたオブジェクト(ここではGoalオブジェクト)に接触してきたオブジェクト(ここではユニティちゃん)が「Collider other」として関数に渡されます。
1 |
private void OnTriggerEnter(Collider other){} |
この関数はオブジェクトのコライダーが「IsTrigger = True」になっていないと使用することができません。
コライダー・当たり判定がよくわからないという方は以下記事をご参考ください。
参考記事)当たり判定について
ここで渡されたotherの名前がもしかするとユニティちゃんではない可能性があるので29行目以降の「if」文以降で念のため判定してあります。
1 2 3 4 5 |
if(other.name == player.name) { //一旦ログに出力 Debug.Log("ユニティちゃんと接触しました!"); } |
判定条件は「other.name == player.name」ですので渡されたコライダーの名前とあらかじめ登録しておいたユニティちゃんの名前を比較して同じだった場合のみif文の中身を実行するような仕様になっています。
もし当たった相手がユニティちゃんだった場合は一旦コンソールのログに定型文を出力する仕様になっています。
実際に実行してここまでの動きを確認してみましょう。
コンソールはMac「⌘+Shift+C」、Windows「Ctrl+Shift+C」でコンソールを表示できます。
ゴールしたことを表示する
次にゴールしたことをユーザーに表示します。
まずはスクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GoalManager : MonoBehaviour { //ユニティちゃんを格納するための変数 public GameObject player; //テキストを格納するための変数 public GameObject text; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } //当たり判定関数 private void OnTriggerEnter(Collider other) { //当たってきたオブジェクトの名前がユニティちゃんの名前と同じとき if(other.name == player.name) { //テキストの内容を変更する text.GetComponent<Text>().text = "Goal!!!"; //テキストをオンにして非表示→表示にする text.SetActive(true); } } } |
1 |
text.GetComponent<Text>().text = "Goal!!!"; |
32行目の「GetComponent<Text>()」でtextオブジェクトのTextコンポーネントを取得することができます。
ここだけで理解することは難しいかもしれませんが徐々にこのような考え方を理解するようにするとゲーム開発がしやすくなると思います。
1 |
text.SetActive(true); |
34行目のように「GameObject型の変数.SetActive(bool)」でオブジェクトのオンオフを切り替えることができます。
画面をクリックして再度ゲームをスタートする
次にゴールした後に画面をクリックしてゲームを再スタートする処理を加えます。
まずはスクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class GoalManager : MonoBehaviour { //ユニティちゃんを格納するための変数 public GameObject player; //テキストを格納するための変数 public GameObject text; //Goalしたかどうか判定する private bool isGoal = false; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { //Goalした後で画面をクリックされたとき if(isGoal && Input.GetMouseButton(0)) { Restart(); } } //当たり判定関数 private void OnTriggerEnter(Collider other) { //当たってきたオブジェクトの名前がユニティちゃんの名前と同じとき if(other.name == player.name) { //テキストの内容を変更する text.GetComponent<Text>().text = "Goal!!!\n画面クリックで再スタート"; //テキストをオンにして非表示→表示にする text.SetActive(true); //Goal判定をTrueにする isGoal = true; } } //シーンを再読み込みする private void Restart() { // 現在のScene名を取得する Scene loadScene = SceneManager.GetActiveScene(); // Sceneの読み直し SceneManager.LoadScene(loadScene.name); } } |
スクリプトについて詳しく解説していきます。
今さらですが1行目〜5行目の「using …」という文はUnity特有のクラスや関数を使用するために必要な記述でここでは決まり文句と覚えておいていただければ問題ありません。
1 |
private bool isGoal = false; |
次に15行目の「private」で宣言されたbool型の「isGoal」はゴールしたかどうかを判定するための変数です。「private」というのは「private」とは違いそのスクリプト内でしか値を格納、参照することができません。特に外部から参照する予定のない変数は全て「private」にしておきましょう。
1 2 3 4 5 |
//Goalした後で画面をクリックされたとき if(isGoal && Input.GetMouseButton(0)) { Restart(); } |
次に27行目〜30行目のif文について、これは「isGoal」が「True」、つまりユニティちゃんがゴールした後で、「GetMouseButton(0)」つまり左クリックを認識したときにif文の中身が実行されます。実行されるのは「Restart()」メソッドでこれは後ほど解説します。
また、この部分は「Update()」メソッドのなかで処理されています。この「Update()」メソッドはシンプルに説明すると常に呼び出され続けるメソッドです。詳しくは公式リファレンスをご参考ください。
1 |
text.GetComponent<Text>().text = "Goal!!!\n画面クリックで再スタート"; |
40行目は少しだけ文言を変更しました。「\n」で改行をすることができます。
1 2 3 4 5 6 7 |
private void Restart() { // 現在のScene名を取得する Scene loadScene = SceneManager.GetActiveScene(); // Sceneの読み直し SceneManager.LoadScene(loadScene.name); } |
49行目〜56行目の「Restart()」メソッドはシーンを再読み込みして再スタートするためのメソッドです。
SceneManagerクラスを利用することで簡単にシーンを再読み込みすることができます。ここではこのように記述すればシーンを再読み込みできることだけをご理解いただければ問題ありません。
参考記事)現在のSceneの再読み込みをスマートなコードで書く(「ぱふの自由帳」より)
これで第1部は終了です!
迷路ゲームの基礎部分が完成しました。ここからはどんどんゲーム要素を追加していきます。
第2部:ゲーム要素の追加
第2部ではゲーム要素を追加していきます。
障害物を作成したり、時間制限をつけたり、追いかけてくる敵を作成したり…ここからはUnityの機能をもっと活用して開発を進めていきます!
目次
- 障害物を作成する
- 時間制限を作成する
- 落下したときの処理を作成する
- 追跡してくる敵を作成する
障害物を作成する
まずは障害物を作成します。
今回は2種類の障害物を作成します。1つ目は当たっても問題ない障害物。2つ目は当たるとゲームオーバーになる障害物。この2つを作成していきます。
当たっても大丈夫な障害物を作成する
まずは簡単な方から作成していきます。
その前に現状のままだとフィールドが小さすぎるので3倍くらいの大きさに変更します。
ヒエラルキーウィンドウでPlaneを選択してXとZのScaleを「3」に変更してください。
せっかくなのでユニティちゃんとGoalオブジェクトの位置も調整しておきます。
ユニティちゃんのPositionのZを「-12.5」に、GoalオブジェクトのZの値を「12.5」に変更してください。
これでフィールドを大きくすることができました。
ここから障害物を作成していきます。
ヒエラルキーウィンドウのCreate→3D Object→Cubeを選択して直方体を作成してください。作成したら名前を「Wall」に変更してください。
Transformの値を以下のように変更してください。
PositionのYの値を「1」にする理由はScaleのYの値が「2」のため「0」のままだと半分Planeに埋まってしまうからです。
また、PlaneとWallの色が同じで見づらいので色を変更しましょう。色を変更するためにマテリアルと呼ばれるオブジェクトの色や質感を表現するための部品を作成します。
まずはプロジェクトウィンドウで新しく「Materials」フォルダを作成してください。
作成したらプロジェクトウィンドウのCreate→Materialを選択してください。マテリアルを作成したら名前を「WallColor」としてください。
色を変更します。作成したWallColorを選択してインスペクターウィンドウのAlbedoを選択してください。
選択するとColorウィンドウが表示され好きな色に変更できますので色を選びます。ここでは青系の色にしてください。
今回は一連の流れをGIFでご紹介しますが、以降省略します。
ここで作成したマテリアルをヒエラルキーウィンドウのWallにドラッグ&ドロップすることでWallの色を変更することができます。
このWallを左右に動くようにしましょう。
Scriptsフォルダに「WallController」という名前でスクリプトを作成してください。
作成したらスクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WallController : MonoBehaviour { //オブジェクトの速度 public float speed = 0.05f; //オブジェクトの横移動の最大距離 public float max_x = 10.0f; // Update is called once per frame void Update() { //フレーム毎speedの値分だけx軸方向に移動する this.gameObject.transform.Translate(speed, 0, 0); //Transformのxの値が一定値を超えたときに向きを反対にする if(this.gameObject.transform.position.x > max_x || this.gameObject.transform.position.x < (-max_x)) { speed *= -1; } } } |
スクリプトを解説します。
8行目と10行目でオブジェクトの移動速度と移動距離を定義します。「public」で宣言することでUnityエディタから変更が可能なため好きなように速度を変更することで難易度を変更することができます。
例えばイージーモードとハードモードを選択させてそれぞれの速度を設定しておけば難易度を分けることも容易になります。
このオブジェクトを使い回しができるようにプレハブ化します。
ヒエラルキーウィンドウでWallをプロジェクトウィンドウにドラッグ&ドロップすることでプレハブ化することができます。
ここではプロジェクトウィンドウに「Prefabs」フォルダを事前に作成しておいてからそこにWallのプレハブを作成しましょう。
今回は一連の流れをGIFでご紹介しますが、以降省略します。
これで簡単に動く障害物を複数作成できるようになりました。プレハブを再び使用したいときはプロジェクトウィンドウから使いたいプレハブをシーンビューにドラッグ&ドロップすることで簡単に量産することができます。
ここではもう一つだけWallを作成しておきます。位置は任意です。
同じオブジェクトを量産するとヒエラルキーウィンドウがごちゃごちゃになってしまい見づらくなります。そこでこの複数のオブジェクトをまとめるために空のオブジェクトを作成して複数オブジェクトを子オブジェクトにまとめることができます。
ヒエラルキーウィンドウのCreate→Create Emptyを選択してください。名前を「MovingWall」とします。
先ほど作成したWallをMovingWallにドラッグ&ドロップして子オブジェクト化してください。
今回は一連の流れをGIFでご紹介しますが、以降省略します。
これでヒエラルキーウィンドウを整理することができますのでぜひ積極的に使用してみてください。
ここまでの操作で以下のような状態になりました。
当たるとゲームオーバーになる障害物を作成する
続いて当たるとゲームオーバーになる障害物を作成します。
先ほど作成したWallをベースに作成していきましょう。
まずはWallプレハブをヒエラルキーウィンドウに追加してください。
追加したプレハブのプレハブ化を解除し、名前を「DeadWall」としてください。
プレハブ化の解除はヒエラルキーウィンドウで解除したいオブジェクトを右クリックしてUnpack Prefabを選択すると解除できます。
追加したら色がわかりづらいので新しいマテリアルを作成します。名前を「DeadWallColor」としてください。色は赤系の色で作成してください。
ここまでの操作がわからない場合がわからない場合は「当たっても大丈夫な障害物を作成する」を再度確認してください。
次にスクリプトを変更します。WallControllerをそのまま変更してしまうと、青色のWallの挙動まで変化してしまうため新しいスクリプトを作成します。「DeadWallController」という名前のスクリプトを作成してください。
続いて作成したスクリプトを以下のように変更してください。(WallControllerに追加した部分をハイライトしています)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; using UnityChan; public class DeadWallController : MonoBehaviour { //オブジェクトの速度 public float speed = 0.05f; //オブジェクトの横移動の最大距離 public float max_x = 10.0f; //ユニティちゃんを格納する変数 public GameObject player; //テキストを格納する変数 public GameObject text; //ゲームオーバー判定 private bool isGameOver = false; // Update is called once per frame void Update() { //フレーム毎speedの値分だけx軸方向に移動する this.gameObject.transform.Translate(speed, 0, 0); //Transformのxの値が一定値を超えたときに向きを反対にする if (this.gameObject.transform.position.x > max_x || this.gameObject.transform.position.x < (-max_x)) { speed *= -1; } //ゲームオーバー状態で画面がクリックされたとき if(isGameOver && Input.GetMouseButton(0)) { Restart(); } } //ユニティちゃんとの当たり判定 private void OnCollisionEnter(Collision other) { //接触したオブジェクトがユニティちゃんのとき if(other.gameObject.name == player.name) { //ゲームオーバーを表示する text.GetComponent<Text>().text = "GameOver..."; text.SetActive(true); //ユニティちゃんを動けなくする player.GetComponent<UnityChanControlScriptWithRgidBody>().enabled = false; //アニメーションをオフにする player.GetComponent<Animator>().enabled = false; //ゲームオーバー isGameOver = true; } } //シーンを再読み込みする private void Restart() { // 現在のScene名を取得する Scene loadScene = SceneManager.GetActiveScene(); // Sceneの読み直し SceneManager.LoadScene(loadScene.name); } } |
スクリプトの解説をします。
基本構造はWallControllerとGoalControllerを組み合わせただけですのでご理解いただけると思います。
違う点を数点ピックアップしてご紹介します。
1 |
private void OnCollisionEnter(Collision other) |
43行目の「OnCollisionEnter(Collision other)」はGoalControllerとは違います。こちらはColliderのIsTriggerがオフどうしのオブジェクト、つまり物理的な接触があるオブジェクト同士の当たり判定に使用されるメソッドです。
1 2 3 4 |
//ユニティちゃんを動けなくする player.GetComponent<UnityChanControlScriptWithRgidBody>().enabled = false; //アニメーションをオフにする player.GetComponent<Animator>().enabled = false; |
52行目〜55行目について、ゲームオブジェクトのコンポーネントを「GetComponent<>()」で取得して「enable」を「false」にすることで指定したコンポーネントをオフにすることができます。
これはUnityエディタ上でコンポーネントの左側にあるチェックマークを外すことと同義です。
編集したDeadWallControllerスクリプトをDeadWallオブジェクトにアタッチして必要なオブジェクトをスクリプトにアタッチしたら以下のように動作します。
また、作成したDeadWallもプレハブ化しておくと後で簡単に使用できますのでプレハブ化しておきましょう。
時間制限を作成する
次に時間制限を作成します。
まずは時間を表示するテキストを作成します。
ヒエラルキーウィンドウのCreate→UI→Textを選択してください。
作成したら名前を「Time」に変更してください。
TimeのRectTransformを編集します。アンカーと呼ばれる基準点を左上に設定します。
RectTransform左側にあるAnchorを選択して左上を選択してください。(以下画像参考)
また以下画像の赤枠の数値に合わせると位置とサイズがちょうど良くなります。
これで時間表示用のテキスト作成は完了です。
新しくスクリプトを作成します。名前を「TimeManager」としてください。
作成したスクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityChan; using UnityEngine.SceneManagement; public class TimeManager : MonoBehaviour { //時間表示用テキスト public Text timeText; //制限時間 public float limit = 30.0f; //ゲームオーバー表示用テキスト public GameObject text; //ユニティちゃん格納用 public GameObject player; //ゲームオーバー判定 private bool isGameOver = false; // Start is called before the first frame update void Start() { timeText.text = "残り時間:" + limit + "秒"; } // Update is called once per frame void Update() { //ゲームオーバー状態で画面がクリックされたとき if (isGameOver && Input.GetMouseButton(0)) { Restart(); } //時間制限がきたとき if(limit < 0) { //ゲームオーバーを表示する text.GetComponent<Text>().text = "GameOver..."; text.SetActive(true); //ユニティちゃんを動けなくする player.GetComponent<UnityChanControlScriptWithRgidBody>().enabled = false; //アニメーションをオフにする player.GetComponent<Animator>().enabled = false; //ゲームオーバー isGameOver = true; //ここでUpdateメソッドを終わらせる return; } //時間をカウントダウンする limit -= Time.deltaTime; timeText.text = "残り時間:" + limit.ToString("f1") + "秒"; } //シーンを再読み込みする private void Restart() { // 現在のScene名を取得する Scene loadScene = SceneManager.GetActiveScene(); // Sceneの読み直し SceneManager.LoadScene(loadScene.name); } } |
スクリプトを解説します。
各変数はコメントの通りです。
特別難しい処理はありませんが、今回新しく登場する2点をピックアップします。
1 |
limit -= Time.deltaTime; |
「Time.deltaTime」はそのフレームにかかった時間です。よってこの時間を加算、もしくは減算することでカウント、カウントダウンを行うことができます。
1 |
timeText.text = "残り時間:" + limit.ToString("f1") + "秒"; |
floatには「ToString()」というメソッドが準備されており、桁数を指定してString型に変換することができます。
floatやStringなど、型について深く知りたいという方は以下記事をご参考ください。
参考記事)変数の型について
このスクリプトはどのオブジェクトにアタッチしていただいても問題ありませんが、ここでは新しく空のオブジェクト「TimeManager」を作成してアタッチします。スクリプトに必要なオブジェクトはそれぞれアタッチしておきましょう。
落下したときの処理を作成する
次に落下したときの処理を作成します。
落下したときも時間制限と同じようにゲームオーバーになり、画面をクリックしてリスタートする仕様にします。
また、ここまで2種類のゲームオーバーになるゲーム要素を作成しましたが、ほとんど同じようなスクリプトを記述していただきました。これはコピペすればそれで良いとお考えになるかもしれませんが、仕様を変更したくなった場合に一つ一つ変更していては非常に不便です。
そこで「クラス」という考え方を利用してゲームオーバー、リスタートをする処理を一つのスクリプトに任せる仕様に変更します。
リスタート処理を一つのクラスにまとめる
まずはこちらの処理を作成するために新しいスクリプト「RestartManager」を作成してください。
スクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; using UnityChan; public class RestartManager : MonoBehaviour { private GameObject player; private GameObject text; private bool isGameOver = false; //コンストラクタ public RestartManager(GameObject player,GameObject text) { this.player = player; this.text = text; } public void PrintGameOver() { //ゲームオーバーを表示する text.GetComponent<Text>().text = "GameOver..."; text.SetActive(true); //ユニティちゃんを動けなくする player.GetComponent<UnityChanControlScriptWithRgidBody>().enabled = false; //アニメーションをオフにする player.GetComponent<Animator>().enabled = false; //ゲームオーバー isGameOver = true; } //シーンを再読み込みする public void Restart() { // 現在のScene名を取得する Scene loadScene = SceneManager.GetActiveScene(); // Sceneの読み直し SceneManager.LoadScene(loadScene.name); } //ゲームオーバーしているかどうか確認 public bool IsGameOver() { return isGameOver; } } |
このクラスを作成しておくことで他のクラスでゲームオーバー処理を無駄に記述する必要が無くなります。
また、仕様変更のときもこのスクリプトのみを変更すれば他のスクリプトにも適用されるため効率も良くなります。
それではスクリプトを解説します。
基本的なゲームオーバー処理は先ほどと全く同じですのでピックアップしてご紹介します。
1 2 3 4 5 6 |
//コンストラクタ public RestartManager(GameObject player,GameObject text) { this.player = player; this.text = text; } |
16行目〜20行目には「コンストラクタ」というものがあります。
これはこのクラスで変数が宣言され、インスタンスが生成されたときにあらかじめ特定の処理を行うための記述です。
今回のコンストラクタはプレイヤーとテキストをあらかじめ受け取っておくためのコンストラクタです。
インスタンスとコンストラクタについて詳しく理解したい方は以下記事をご参考ください。
参考記事)クラスの考え方
ではこのクラスを利用する方法を解説します。
ここでは先ほど作成したTimeManagerスクリプトの記述を変更します。
TimeManagerスクリプトを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class TimeManager : MonoBehaviour { //時間表示用テキスト public Text timeText; //制限時間 public float limit = 30.0f; //ゲームオーバー表示用テキスト public GameObject text; //ユニティちゃん格納用 public GameObject player; //RestartManager型 private RestartManager restart; // Start is called before the first frame update void Start() { //インスタンス生成 restart = new RestartManager(player, text); //初期時間を設定 timeText.text = "残り時間:" + limit + "秒"; } // Update is called once per frame void Update() { //ゲームオーバーしていて画面がクリックされたとき if (restart.IsGameOver() && Input.GetMouseButton(0)) { restart.Restart(); } //時間制限がきたとき if(limit < 0) { //RestartManagerに処理を任せる restart.PrintGameOver(); //ここでUpdateメソッドを終わらせる return; } //時間をカウントダウンする limit -= Time.deltaTime; timeText.text = "残り時間:" + limit.ToString("f1") + "秒"; } } |
記述がシンプルになったことがご理解いただけたのではないでしょうか。
それではスクリプトを解説します。
まず「using UnityEngine.SceneManagement;」「using UnityChan;」の記述が無くなりました。理由は「UnityEngine」の「SceneManagement」のメソッドや変数をTimeManagerスクリプトで使用することがなくなったからです。
「using」とはあらかじめ準備された特定のメソッドや変数のセットを利用するための記述であるということです。
1 |
private RestartManager restart; |
18行目の変数宣言でRestartManagerを利用できるようにします。ただしこれだけでは使用することができません。
1 |
restart = new RestartManager(player, text); |
25行目のようにインスタンスを生成する必要があります。インスタンスとはわかりやすく説明すると実体そのものです。つまり、18行目で宣言した変数は実体をしまうための箱で、その実体を「new」で新しく生成しています。
また、このときにそのクラスのコンストラクタが処理されます。ここではユニティちゃんとゲームオーバーのテキストを渡すことでそれぞれのオブジェクトをRestartManagerで扱えるようにしています。
先ほどもご紹介しましたが、クラスやインスタンスの考え方をもっと理解したい方は以下記事をご参考ください。
参考記事)クラスの考え方
他のGoalManagerスクリプトやDeadWallManagerスクリプトも同じようにRestartManagerに処理を任せることができますのでこちらも変更してみてください。
落下処理を実現する
長くなりましたが落下処理を実現していきます。
まずは落下をどのように判断するか考えます。方法は無数に存在しますが、ここではユニティちゃんのPositionのY座標が「-10」より小さくなったときにゲームオーバーにする仕様にします。
新しいスクリプト「DropManager」を作成して以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DropManager : MonoBehaviour { //ユニティちゃんを格納する変数 public GameObject player; //テキストを格納する変数 public GameObject text; //RestartManager型 private RestartManager restart; // Start is called before the first frame update void Start() { //インスタンス生成 restart = new RestartManager(player, text); } // Update is called once per frame void Update() { if(player.transform.position.y < -10) { restart.PrintGameOver(); } if(restart.IsGameOver() && Input.GetMouseButton(0)) { restart.Restart(); } } } |
RestartManagerスクリプトを準備していたおかげでとても楽に記述することができます。
1 |
if(player.transform.position.y < -10) |
ユニティちゃん(ゲームオブジェクト)のポジションのY座標は「ゲームオブジェクト.transform.position.y」で取得することができます。この値が「-10」を下回ったときにゲームオーバーにしています。
このスクリプトをアタッチする新しい空のオブジェクト「DropManager」を作成し、アタッチしてください。
追跡してくる敵を作成する
次に追跡してくる敵を作成します。
一見すると難しそうにみえますが、Unityには勝手に追いかけてくるAI(ナビゲーションシステム)があらかじめ準備されています。
追いかけることが可能な範囲を指定します。
最初にフィールドを静的(Static)に変更します。PlaneのStaticにチェックを入れて静的に変更してください。
次にナビゲーションシステムを扱うためのウィンドウを表示します。
メニューばのWindow→AI→Navigationを選択してください。
すると以下のようなウィンドウが表示されます。
これを利用してステージにNavMeshと呼ばれるエージェントの移動可能範囲を生成します。
ナビゲーションウィンドウの以下赤枠①Objectを選択して、赤枠②NavigationStaticにチェックを入れてください。
次にNavMeshの範囲を設定します。
ナビゲーションウィンドウの以下赤枠Bakeを選択してください。
左下の「Bake」を選択するとNavMeshが生成されます。実際に生成するとシーンビューに青くNavMeshが生成されます。
これで移動範囲を定義することができました。
次に追いかけてくるオブジェクトを作成します。ナビゲーションシステムではこの追いかけてくるオブジェクトをエージェントと呼びます。
ヒエラルキーウィンドウのCreate→3D Object→Cylinderを作成して名前を「Enemy」としてください。また、PositionのYを0.5にしてください。このようにすることでフィールドに埋まらなくなります。
また、今回は物理的な接触ができない状態にしておきたいためCapsule ColliderコンポーネントのIsTriggerにチェックを入れておいてください。
次にエージェントとして動けるようにNavMeshAgentをアタッチします。インスペクターウィンドウ最下部のAddComponent→Navigation→NavMeshAgentを選択してください。
このようにコンポーネントを追加したいときはAddComponentから追加することができます。
次にユニティちゃんをターゲットとして追いかけさせるためのスクリプトを作成します。
新しいスクリプト「EnemyController」を作成し、以下のように編集してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class EnemyController : MonoBehaviour { //目的地となるオブジェクトのトランスフォーム格納用 public Transform target; //エージェントとなるオブジェクトのNavMeshAgent格納用 public NavMeshAgent agent; // Use this for initialization void Update() { //目的地となる座標を設定する agent.destination = target.position; } } |
このスクリプトをアタッチするための新しい空のオブジェクト「EnemyController」を作成し、アタッチしてください。
「target」にはユニティちゃんを、「agent」にはEnemyをそれぞれUnityエディタからアタッチすれば動かすことができます。
一旦ここまでを実行して動きを確認してみましょう。
追いかけてくることを確認できました。
しかし、このままでは障害物を貫通してしまうので障害物を避ける仕組みを作成します。
PrefabフォルダのWallとDeadWallにNavMeshObstacleコンポーネントを追加します。
プレハブを選択するとインスペクターウィンドウに「OpenPrefab」というボタンがありますので選択するとプレハブを編集できます。
ここで編集した内容はすでにシーンビューにあるプレハブにも適用されるのでとても便利です。
アタッチしたコンポーネントのSizeをそれぞれ「1.1」に変更しておくと障害物とエージェントが触れることがなくなりますので、今回はこのように設定します。
この作業をWallプレハブとDeadWallプレハブどちらにも実行してください。
これでエージェントが障害物を避けるようになりました。
このエージェントにゲームオーバー処理を追加すれば完成です。
当たり判定はエージェント自身とユニティちゃんの接触を判定したいので新しくスクリプトを作成してEnemyにアタッチします。
新しく「EnemyHitController」スクリプトを作成して以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyHitController : MonoBehaviour { //ユニティちゃんを格納する変数 public GameObject player; //テキストを格納する変数 public GameObject text; //RestartManager型 private RestartManager restart; // Start is called before the first frame update void Start() { //インスタンス生成 restart = new RestartManager(player, text); } // Update is called once per frame void Update() { if(restart.IsGameOver() && Input.GetMouseButton(0)) { restart.Restart(); } } private void OnTriggerEnter(Collider other) { //接触したオブジェクトがユニティちゃんのとき if (other.gameObject.name == player.name) { restart.PrintGameOver(); } } } |
当たり判定が物理接触をしないときに使用する「OnTriggerEnter」であることに注意してください。
また、Enemyにスクリプトをアタッチしたあと、スクリプトの変数部分にエディタからユニティちゃんとテキストをアタッチすることを忘れると正常に動きませんのでご注意ください。
ここではあくまでも方法のみを記載しましたが、スピードを変更するなど、もっと詳しくナビゲーションを扱いたい方は以下記事をご参考ください。
参考記事)ナビゲーションシステムについて
またこのとき、ゴールしたときにEnemyオブジェクトとEnemyControllerオブジェクトをどちらも削除するか非アクティブにしないとゴール後も追従してくるのでご注意ください。
この処理はGoalControllerに追加しておけば問題ありません。
これで第2部は終了です!
ゲーム要素を複数追加してきましたが、ここまでをご理解いただければゲームオーバーをHP形式にしたり、敵とのレース形式にすることもできます。
ここまで2時間程度で進めることができましたでしょうか?
丁寧に進めていただいた方はもっと時間がかかってしまったかもしれません…
このようにシンプルなゲームにも色々な要素を追加できることをご理解いただければ幸いです!
第3部:ゲームのクオリティを向上させる
第3部ではゲームのクオリティを向上させる方法をご紹介します。
ゲームやアプリは機能がシンプルでもデザインや演出がしっかりしているだけでクオリティが格段に上がります。
難しい作業はほとんどありません。時間に余裕がある方はぜひチャレンジしてみてください!
目次
- 背景を変更する
- オブジェクトをリッチにする
- スタート画面を作成する
背景を変更する
まずは背景を変更します。
ここで再びアセットストアを利用します。
今回は「Starfield Skybox」というアセットをインポートして利用します。
インポートしたらSkyboxをシーンビューにドラッグ&ドロップしてください。
たったこれだけでSkyboxを変更することができます。
Skyboxについて詳しく知りたい方は以下記事をご参考ください。
参考記事)Skyboxを変更する方法
オブジェクトをリッチにする
次にオブジェクトをリッチにしていきます。
具体的にはクオリティを上げるためにオブジェクトをもう少し凝ったものに変更していきます。Skyboxでは宇宙を利用したのでテーマは「宇宙」で作成していきます。
フィールドを半透明にする
まずはフィールドを半透明に変更します。
この処理はシェーダーを利用して実現します。
詳しくは以下記事をご参考ください。
参考記事)シェーダーとは
まずはプロジェクトウィンドウで新しいフォルダ「Shaders」を作成してください。
作成したShadersフォルダの中に新しいシェーダーを作成します。
プロジェクトウィンドウのCreate→Shader→StandardSurfaceShaderを選択して名前を「Glass」としてください。
作成したGlassシェーダーを以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Shader "Custom/Glass" { SubShader { Tags { "Queue"="Transparent" } LOD 200 CGPROGRAM #pragma surface surf Standard alpha:fade #pragma target 3.0 struct Input { float3 worldNormal; float3 viewDir; }; void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = fixed4(1, 1, 1, 1); float alpha = 1 - (abs(dot(IN.viewDir, IN.worldNormal))); o.Alpha = alpha*1.5f; } ENDCG } FallBack "Diffuse" } |
このシェーダーを元にマテリアルを作成してPlaneに適用します。
Materialフォルダに新しいマテリアル「Glass」を作成します。作成したマテリアルのShaderをCustom→Glassに変更すれば作成完了です。作成したマテリアルをシーンビューのPlaneにドラッグ&ドロップすれば完了です。
今回は一連の流れをGIFで紹介しますが、以降省略します。
これでフィールドが半透明になりました。
このシェーダーは以下記事を参考に作成しました。
参考記事)【Unityシェーダ入門】氷のような半透明シェーダを作る
また、シェーダーの知識を習得したい方は以下のサイトがとてもわかりやすいのでぜひご参考ください。
ライトのトーンを落とす
現状のままですとライトが明るすぎるのでトーンを落とします。
とはいうものの色を少し暗くするだけですのですぐに実行できます。
ヒエラルキーウィンドウのDirectionLightを選択します。インスペクターウィンドウのColorの色を暗くします。
これで暗くなりました。
追従する敵、ゴールをライトに変更する
次に追従する敵とゴールのオブジェクトに一工夫加えます。
まずはライトに照らされるとゲームオーバーという演出に変更します。
Enemyを編集します。
まずはMeshRendererコンポーネントをオフにします。
これでシリンダーが画面に表示されなくなります。
次にスポットライトを作成します。
ヒエラルキーウィンドウのCreate→Light→Spotlightを選択してください。
作成したスポットライトをEnemyの子オブジェクトに設定します。すると親オブジェクトにスポットライトが追従するようになります。
子オブジェクトに変更後、スポットライトのPositionを以下のように変更してください。
このように編集することでライトが追従するような仕様に変更することができます。
ゴールも同じようにスポットライトに変更しましょう。
ここでは緑色のオブジェクトに変更しました。
スタート画面を作成する
最後にスタート画面を作成します。
スタート画面があるとより一層ゲームらしさが増しますのでぜひ作成してみてください。
プロジェクトウィンドウのSceneフォルダにCreate→Sceneで新しく「TopMenu」シーンを作成してください。
シーンはダブルクリックすれば開くことができます。
画像を使用する
まずは外部から画像を取得します。
今回はユニティちゃんダウンロード公式ページから適当な画像を使用します。
使用したい画像をUnityのプロジェクトウィンドウのフォルダにドラッグ&ドロップすれば画像をインポートすることができます。
今回は「images」フォルダを事前に作成してそちらに保存しておきます。
インポートが完了したら画像をUnityで使用できる状態にします。
インスペクターウィンドウでTextureTypeをSpriteに変更してください。
スプライト化が完了したら画像をシーンビューにドラッグ&ドロップしてください。
画像の位置は以下のように変更しました。
2D画像の詳しい使用方法につきましては以下記事をご参考ください。
参考記事)2D画像の使い方
テキストを作成する
次にテキストを作成します。
文言は「Unity-Chan!SpaceRun」にします。
クリックしたらゲームがスタートするように「Click To Start!!」の文言も入れておきます。
まずはヒエラルキーウィンドウのCreate→UI→Panelを選択してください。
作成したパネルを以下のように変更してください。
また、色は任意ですが透明度が低めの黒だと文字が見やすくなります。
次にヒエラルキーウィンドウのCreate→UI→Textを選択してください。名前を「StartText」に変更します。
ここで作成したテキストをPanelの子オブジェクトに変更してPositionを全て0に変更してください。
そのほかの設定は以下画像をご参考ください。
お気付きの方もいるかと思いますが、フォントが初期設定のものではありません。フォントの変更方法はとても簡単ですので以下記事を参考にチャレンジしてみてください。
参考記事)フォントの変更方法
シーンを変更する
次に画面をクリックしたらシーンを変更するようにします。
まずは新しく「SceneController」スクリプトを作成して、以下のように変更してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneController : MonoBehaviour { // Update is called once per frame void Update() { //画面がクリックされたとき if (Input.GetMouseButtonDown (0)) { //Gameシーンを読み込む SceneManager.LoadScene ("Game"); } } } |
スクリプトはたったこれだけです。
「SceneManager.LoadScene(“シーン名”)」でシーンを読み込むことができます。
作成したスクリプトを新しく作成する空のオブジェクト「SceneManager」にアタッチしてください。
しかし、このままではまだ利用できません。
Macの場合は「⌘+Shift+B」でビルドセッティングを開いてください。
ここでシーンを追加する必要があります。
それぞれのシーンを開いた状態で右中段の「AddOpenScenes」を選択してください。
すると現在開いているシーンが追加されますのでTopManuシーンとGameシーンどちらも追加してください。
シーンは一番上のシーンが最初に読み込まれますのでTopMenuシーンを最初にしておきましょう。
この状態で実行するとシーン遷移を実行することができます。
これで第3部は終了です!
長くなりましたがこれで簡易的なゲームを作成することができました!
作り込もうと思えばもっとクオリティを上げていくことができます。アセットストアもとても充実していますので、3Dモデリングができない方でも少しお金を出せばとてもクオリティの高いオブジェクトを使用することができます。
まとめ
いかがでしたでしょうか。
2時間で作るユニティちゃんRunゲームをご紹介してきました。
長くなってしまいましたがここまで進めることができればUnityをそこそこご理解いただけたのではないでしょうか。
これをきっかけにUnityにハマって皆さんのゲーム開発ライフがより充実していただければ幸いです!
この記事はいかがでしたか?
もし「参考になった」「面白かった」という場合は、応援シェアお願いします!