こんにちは、shiguregakiです!
先日、「Unityの教科書 Unity 2019完全対応版 2D&3Dスマートフォンゲーム入門講座」を読み終え、チョー基礎ですがUnityでのゲーム作りの流れを学ぶことができたと思っています。
せっかくなので、ここで1つのゲームを一から作ってみようと思い、「3D玉転がし」ゲームを作ることに決めました!
別のブログ(【Unity 勉強5】3D玉転がしゲームを作ってみる!(その1))で「3D玉転がし」の簡単な設計を行い、以下のような工程で進める方針となりました。
【3D玉転がしの開発工程】
- 実現方法の検討
- デザインの検討
- デザインの作成(必要あれば)
- プロジェクトの作成
- 外枠の作成
- 操作部分(押し出し棒、バネ)の動作作成
- ビー玉の動作作成
- ステージ(釘や得点スポット)を作成
- Prefabを作る
- 監督スクリプトの作成
このブログでは「9. Prefabを作る」、「10. 監督スクリプトの作成」をしたいと思います。
ソースコード自体は、以下で公開していますので、よろしければご覧ください。
全行程は以下のブログでまとめているので、よろしければご覧ください。
目次
3D玉転がしとは?
小学校の図工のときに作ったあれ ↓ です。
玉転がしゲームB(ビー玉あそび)
Amazon 楽天
Prefabを作る
上で紹介した【3D玉転がしの開発工程】の「9. Prefabを作る」として、Prefabをを作成します。
3D玉転がしでは定期的に作成するのはビー玉のみのため、ビー玉Prefabのみ作成すればよいです。
ビー玉のPrefabを作成する
ヒエラルキーウィンドウにあるビー玉オブジェクトをプロジェクトウィンドウにドラッグ&ドロップすることでPrefab化することができます。
ビー玉の生成トリガーを作成する
Prefabでビー玉を生成するトリガーとして使用するビー玉発射検知の仕組みを作成します。
以下の画像のように空のオブジェクトに「Box Collider」を紐づけることで、ビー玉がそこを通過するとOnTriggerEnter()
で検知できるようになります。
このオブジェクト名は「MarbleDetector」という名前にしました。
ビー玉のジェネレータスクリプトを作成する
ビー玉をPrefabで作成するスクリプトを作成します。
【MarbleGenerator.cs】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class MarbleGenerator : MonoBehaviour
{
public GameObject MarblePrefab;
int[] ratios = new int[3] {1, 1, 1};
string[] MarbleTags;
public void GenerateMarble()
{
GameObject Marble = Instantiate(MarblePrefab);
int dice = Random.Range(0, this.ratios.Sum());
Marble.tag = MarbleTags[dice];
}
public void SetRatios(int[] ratios)
{
this.ratios = ratios;
this.SetMarbleTags();
}
void Start()
{
this.SetMarbleTags();
this.GenerateMarble();
}
private void SetMarbleTags()
{
this.MarbleTags = new string[this.ratios.Sum()];
int j = 0;
for(int i = 0; i < this.ratios[0]; i++){
this.MarbleTags[j] = "RedMarble";
j++;
}
for (int i = 0; i < this.ratios[1]; i++)
{
this.MarbleTags[j] = "BlueMarble";
j++;
}
for (int i = 0; i < this.ratios[2]; i++)
{
this.MarbleTags[j] = "BlackMarble";
j++;
}
}
}
int[] ratios
はビー玉の色を作成する比率を設定する配列です。(赤,青,黒)の順番です。GenerateMarble()
はビー玉を生成するAPIです。ビー玉制御スクリプト(MarbleController.cs)が「MarbleDetector」(ビー玉発射用コライダ)の通過を検出したら、このAPIを実行しビー玉を生成させます。
空のオブジェクト「MarbleGenerator」を作成し、「MarbleGenerator」スクリプトをアタッチしました。
これで、以下の動画のようにビー玉が発射されると自動でビー玉が生成されるようになりました。
(青いビー玉が発射されると、自動で黒いビー玉が生成されているのが分かると思います。)
監督スクリプトを作成する
上で紹介した【3D玉転がしの開発工程】の「監督スクリプトの作成」として、ゲーム実行時シーン用の「GameDirector.cs」とゲーム開始シーン用の「GameStartDirector.cs」を作成します。
「GameDirector.cs」はゲーム時間や得点などのUI制御とシーン制御を行います。
「GameStartDirector.cs」は得点結果のUI制御とシーン制御を行います。
UIを配置する
以下のUIを設置します。
- 時間制限UI
- 得点UI
以下の画像の右上のようにUIを配置しました。
ゲーム開始シーンを作成する
これまでは3D玉転がしゲームができる「ゲーム実行シーン」に対していろいろ準備を進めてきましたが、ゲームの開始を表示させる「ゲーム開始シーン」を作成します。
新しいシーンとして「ゲーム開始シーン」を作成し、以下の画像を張り付けました。
また、カメラや光源の位置を調整し、ゲーム開始シーンは以下のようにしました。
前回ゲームの得点を表示するUIも設置しています。(「Latest Score: -点」のところ)
ゲーム実行中の監督スクリプト(GameDirector.cs)を作成する
以下のようなスクリプトを作成しました。
【GameDirector.cs】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameDirector : MonoBehaviour
{
// ビー玉の比率(赤,青,黒)
int[] ratios = new int[3] { 2, 4, 1 };
// ゲームの時間
float gameTime = 30.0f;
GameObject timerText, scoreText, GameStartDirector;
public static int _score = -1;
int score = 0;
public void UpdateScore(int score, string marbleTypeTag)
{
if(marbleTypeTag == "RedMarble")
{
this.score += score * 5;
}else if(marbleTypeTag == "BlueMarble")
{
this.score += score;
}else if(marbleTypeTag == "BlackMarble" && score != 0)
{
// 黒色ビー玉かつどこかの得点スポットに入った場合
this.score = this.score / 2;
}
}
void Start()
{
this.timerText = GameObject.Find("Time");
this.scoreText = GameObject.Find("Score");
GameObject.Find("MarbleGenerator").GetComponent<MarbleGenerator>().SetRatios(this.ratios);
}
void Update()
{
this.gameTime -= Time.deltaTime;
this.timerText.GetComponent<Text>().text = this.gameTime.ToString("F1");
this.scoreText.GetComponent<Text>().text = this.score.ToString() + " 点";
// 制限時間が過ぎたらゲーム開始シーンへ移動
if (this.gameTime < 0)
{
SceneManager.sceneLoaded += GameStartSceneLoaded;
SceneManager.LoadScene("GameStartScene");
}
}
// 参考: https://note.com/suzukijohnp/n/n050aa20a12f1
private void GameStartSceneLoaded(Scene next, LoadSceneMode mode)
{
// シーン切り替え時に呼ばれる
GameDirector._score = this.score;
SceneManager.sceneLoaded -= GameStartSceneLoaded;
}
}
int[] ratios
はビー玉の色を作成する比率を設定する配列です。起動時にビー玉ジェネレータのSetRatios()
でこの設定値を渡しています。UpdateScore()
は得点確定されたときに、ビー玉コントローラから実行されます。これにより、得点UIに得点が反映されます。Update()
内で得点UIと時間制限UIの変化を制御しています。GameStartSceneLoaded()
は時間制限が0になり、ゲーム実行中シーン→ゲーム開始シーンに遷移する前に実行される関数です。グローバルパラメータの_score
に今回取得した得点を設定しています。
ソースコード自体は、以下で公開していますので、よろしければご覧ください。
ゲーム開始の監督スクリプト(GameStartDirector.cs)を作成する
以下のようなスクリプトを作成しました。
【GameStartDirector.cs】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameStartDirector : MonoBehaviour
{
GameObject latestScoreText;
void Start()
{
this.latestScoreText = GameObject.Find("LatestScore");
if (GameDirector._score >= 0)
{
this.latestScoreText.GetComponent<Text>().text = "Latest Score : " + GameDirector._score.ToString() + " 点";
}
else
{
this.latestScoreText.GetComponent<Text>().text = "Latest Score : - 点";
}
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
SceneManager.LoadScene("GameScene");
}
}
}
- ゲーム開始シーンに遷移されたら、グローバルパラメータ
_score
を読み取り、得点が入っていたらそれを得点結果UIに反映します。 Update()
でマウスの右クリックを待ち、右クリックがあったらゲーム実行中シーンに遷移します。
ソースコード自体は、以下で公開していますので、よろしければご覧ください。
とりあえず、完成!!!
バグ/改善の修正
ゲームをやっているとまだ気になるところが何点かあるので、バグ/改善をしました。
- [バグ] ビー玉が押し出し棒側に戻ってくると、ビー玉が2つになる。
- [バグ] 押し出し棒を操作中に壁下部の動作が不安定になる
- [改善] 得点スポットの色を得点ごとに変える
まとめ
3D玉転がしが完成しました!!!
思ったより時間がかかりましたが、現時点の自分の知識で程よく難しいものにチャレンジできたかと思います。
今回作ってみて知識が足りないと思ったのは以下です。
- 3Dモデリングツール(Blenderなど)について
- レンダリング(マテリアル、シェーダーなど)について
特に、バネのデザインについては螺旋型のものを作りたかったのですが、Unityのデフォルトで用意されているオブジェクトの形では作ることができず断念しました。
Blenderなどの3Dモデリングツールを使えば、実装はできそうなので、次の目標としては3Dモデリングツールの勉強をしていきたいと考えています。
関連動画
次の工程
今のところ、これが最後です。
前の工程
全行程
広告
Unityを初めて勉強するなら「Unityの教科書 Unity 2019完全対応版 2D&3Dスマートフォンゲーム入門講座」がオススメです!
全くUnityが分からなかった状態でも概要を理解することができました。
Unityの教科書 Unity 2019完全対応版 2D&3Dスマートフォンゲーム入門講座
Amazon 楽天
以上!
コメント