著者:山内 真仁
以前、ゲームエンジン「Unity」を使ったレースゲームをSLPのチーム活動で
作成しました。その経験を生かして今回は、Unityとプログラミング言語「C#」を使って、簡単なレースゲームを作成する方法を紹介します。Unityの物理エンジンを使用することで、複雑なコードを書かなくてもリアルな挙動のゲームを作成できます。
シェルスクリプトマガジン Vol.67は以下のリンク先でご購入できます。![]()
![]()
図12 「CarController.cs」ファイルに記述する内容
using UnityEngine;
public class CarController : MonoBehaviour
{
public GameObject[] wheelMeshes = new GameObject[4]; // ホイールオブジェクトを格納する配列
public WheelCollider[] wheelColliders = new WheelCollider[4]; // Wheel Colliderを格納する配列
public float maxMotorTorque = 300f; // 車輪に加える最大トルク
public float brakeTorque = 500f; // ブレーキのトルク
public float maxSteerAngle = 25f; // ステアリングの最大舵角
float accel, steer; // アクセルとステアリングの入力値
bool brake; // ブレーキをかけているかどうか
// 画面を描画するたびに実行されるメソッド(実行間隔はフレームレートに依存)
void Update()
{
steer = Input.GetAxis("Horizontal"); // ←→で旋回
accel = Input.GetAxis("Vertical"); // ↑↓でアクセル
brake = Input.GetKey(KeyCode.Space); // スペースでブレーキ
// Wheel Colliderの動きを見た目に反映する
for (int i = 0; i < 4; i++) {
wheelColliders[i].GetWorldPose(out Vector3 position, out Quaternion rotation);
wheelMeshes[i].transform.position = position;
wheelMeshes[i].transform.rotation = rotation;
}
}
// フレームレートに依存せず、定期的に実行されるメソッド(0.02秒に1回)
void FixedUpdate()
{
// Wheel Colliderに各パラメータを代入
for(int i = 0; i < 4; i++) {
if (i < 2) wheelColliders[i].steerAngle = steer * maxSteerAngle; // ステアリング(前輪)
wheelColliders[i].motorTorque = accel * maxMotorTorque; // アクセル
wheelColliders[i].brakeTorque = brake ? brakeTorque : 0f; // ブレーキ
}
}
}
図14 CarController.csファイルに追加する記述
GameObject brakeLight, headLight; // ランプ類のオブジェクトを格納する変数
// ゲーム開始時に1回のみ実行されるメソッド
void Start()
{
// ランプ類のオブジェクトを探して取得
brakeLight = GameObject.Find("SkyCarBrakeLightsGlow");
headLight = GameObject.Find("SkyCarHeadLightsGlow");
}
void Update()
{
// ランプ類の点灯・消灯
brakeLight.SetActive(brake);
if (Input.GetKeyDown(KeyCode.H)) {
headLight.SetActive(!headLight.activeSelf);
}
図16 「Timer.cs」ファイルに記述する内容
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Timer : MonoBehaviour {
public Text timeText; // タイム表示用のテキスト
float startTime; // 計測開始の時刻
bool start, check, goal; // 各地点の通過フラグ
void Start() {
// オブジェクトのコンポーネントを取得
timeText = GameObject.Find("TimeText").GetComponent<Text>();
timeText.text = "TIME 00.000"; // テキストの初期化
}
void Update() {
// スタートしてからゴールするまでタイムを表示
if (!goal && start)
timeText.text = "TIME " + (Time.time - startTime).ToString("00.000");
// ゴール後に[R]キーを押すとリスタート
if (goal && Input.GetKey(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
// トリガーオブジェクトに侵入した時に呼び出されるメソッド
void OnTriggerEnter(Collider other) {
if (other.gameObject.name == "StartPoint") {
if (check) {
goal = true; // チェックポイント通過済みならゴール
timeText.color = Color.red;
} else if (!start && !check) {
start = true; // チェックポイントを通過していない場合、タイム計測開始
startTime = Time.time;
}
} else if (start && other.gameObject.name == "CheckPoint")
check = true; // チェックポイントを通過
}
}