さて#1の続編として、動く障害物を実装する例を紹介します。
#1で大まかにUnityを使ったゲーム開発の流れ・仕組みがわかったと思います。
●シーンにオブジェクトを配置して、
各種機能をもつコンポーネント、
プログラミング制御するスクリプトをアタッチする。
●ゲームの画面、ステージの数だけ、シーンを作成し、遷移させる。
という仕組みです。
さらにゲームを作り込み、個性を出していくために
本記事の内容にも、 ぜひチャレンジしてみてください^^
動く障害物の実装
ゲームオブジェクトが自動的に動くようにする方法は、
・スクリプトで制御する方法
・アニメーションを設定する方法
・物理挙動の動きに任せる方法
があります。
ここでは、 よりC#プログラミング学習のためになる
スクリプトで制御する方法を紹介します。
この制御方法について理解できれば、
あなたの数学力をゲーム開発に活かせるようになります。
(数学的に美しいゲームを作る第一歩...)
早速、障害物であるObstacleが動くように、
スクリプトObstacle.csに次のコードを追記します。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Obstacle : MonoBehaviour { [SerializeField] GameObject gameoverText; [SerializeField] GameObject retryBtn; // ここからObstacleを動かすコード Vector3 startPosition; [SerializeField] Vector3 movementVector; float movementFactor; [SerializeField] float period = 2f; void Start() { startPosition = transform.position; } void Update() { if (period <= Mathf.Epsilon) { return; } //およそ0なら動かないようにする float cycles = Time.time / period; // 時間を数値で割る(periodが大きいほど、動きが遅くなる) const float tau = Mathf.PI * 2; float rawSinWave = Mathf.Sin(cycles * tau); // 時間経過でSinの()内の値は増えていくが、Sinなので-1~1を超えることはない) movementFactor = (rawSinWave +1f) / 2f; // 0~1の間を増減するものに変換 Vector3 offset = movementVector * movementFactor; transform.position = startPosition + offset; // Obstacleを動かす } // ここまで void OnTriggerEnter(Collider other) { if(other.CompareTag("Player")) { gameoverText.GetComponent<Text>().text = "GAME OVER"; gameoverText.GetComponent<Text>().color = new Color(0,0,255); gameoverText.SetActive(true); retryBtn.SetActive(true); Time.timeScale = 0; } } } |
プログラミングのコードで表現すると複雑そうに見えますが、
数学的には大したものではありません^^;
MathfはC#で用意された数学的な機能です。
Mathf.PI(円周率π)やMathf.sin()をここでは使っています。
オブジェクトに往復するような動きを実装する場合、
Mathf.sinやMathf.cosを使います。
なぜなら、sinなどの三角関数は、必ず-1〜1の間の値だからです。
sinの()の値は、2πをかけることで、角度に変換され、-1≦sin()≦1となります。
ここでは時間の経過で増える数(Time.time)を自由に変更できるperiodで割って、
cycleという動きの速さに影響する値を制御しています。
cycleはMathf.sinの引数に入れられ、2πを掛けます。
すると、Msthf.sinは時間の経過ととも-1〜1を往復する値になります。
さらに、それに1を足して、2で割ることで、0〜1を繰り返すようにしています。
その後、Vector3であるMovementVectorに計算してきたMovemenFactor(0~1)をかけて移動する方向と移動量を決定します。
それを元のオブジェクトの位置(startPosition)に足して、実際に動かします。
Inspectorにて
MovementVectorが動く範囲・方向を自由に設定できるようになります。
動きの速さに影響を与えるperiodも設定できます。
([SerializeField]としたため)
これで、Obstacleごとに、異なる動きに設定できます。

その他、Obstacleを回転させたい場合は、次のコードを追記します。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Obstacle : MonoBehaviour { [SerializeField] GameObject gameoverText; [SerializeField] GameObject retryBtn; Vector3 startPosition; [SerializeField] Vector3 movementVector; float movementFactor; [SerializeField] float period = 2f; // 回転させるコードpt.1 [SerializeField] float xAngle = 0; [SerializeField] float yAngle = 0; [SerializeField] float zAngle = 0; void Start() { startPosition = transform.position; } void Update() { // 回転させるコードpt.2 transform.Rotate(xAngle,yAngle,zAngle); if (period <= Mathf.Epsilon) { return; } float cycles = Time.time / period; const float tau = Mathf.PI * 2; float rawSinWave = Mathf.Sin(cycles * tau); movementFactor = (rawSinWave +1f) / 2f; Vector3 offset = movementVector * movementFactor; transform.position = startPosition + offset; } void OnTriggerEnter(Collider other) { if(other.CompareTag("Player")) { gameoverText.GetComponent<Text>().text = "GAME OVER"; gameoverText.GetComponent<Text>().color = new Color(0,0,255); gameoverText.SetActive(true); retryBtn.SetActive(true); Time.timeScale = 0; } } } |
1フレームごとに設定した値(角度)分だけ、
回転させるシンプルなコードです。
x軸回転なのか、y軸回転なのか、z軸回転なのか
設定できます。
回転という動きそのものが、繰り返す動きなので、
特にMathfを用いることもなく、実装が簡単ですね^^
というわけで、
オブジェクトが自動的に動くようになったはずです。
こういった数式を活用したスクリプトで、
数学およびゲーム開発をどんどん楽しんでいきましょう^^