ゴースト機能について


はじめに

今回初めて記事を書かせていただきます。
今回の内容はゴースト機能について書いていきたいと思います。

ゴースト機能について

以下にあるのが自分のゲーム(car race game)で使用しているゴースト機能スクリプトです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;

public class Recorder : MonoBehaviour{
// 操作キャラクター
[SerializeField]
public CarScript CarScript;
// AnimatorController
public Animator animator;
// 現在記憶しているかどうか
public bool isRecord;
// 保存するデータの最大数
[SerializeField]
public int maxDataNum = 90000;
// 記録間隔
[SerializeField]
public float recordDuration = 0.01f;
// 経過時間
public float elapsedTime = 0f;
// ゴーストデータ
private GhostData0 ghostData0 = new GhostData0();
private GhostData1 ghostData1 = new GhostData1();
// 再生中かどうか
public bool isPlayBack;
// ゴースト用キャラ
[SerializeField]
public GameObject ghost;
// ゴーストデータが1周りした後の待ち時間
[SerializeField]
public float waitTime = 2f;
// 保存先フォルダ
public string saveDataFolder = "/Projects/Ghost";
// 保存ファイル名
public string saveFileName = "/ghostdata.dat";
// Start is called before the first frame update
void Start()
{
animator = CarScript.GetComponent ();
}
// Update is called once per frame
void Update()
{
if (isRecord) {

    elapsedTime += Time.deltaTime;

    if (elapsedTime >= recordDuration) 
    {
        ghostData1.posLists.Add (CarScript.transform.position);
        ghostData1.rotLists.Add (CarScript.transform.rotation);

        elapsedTime = 0f;

        // データ保存数が最大数を超えたら記録をストップ
        //if (ghostData1.posLists.Count >= maxDataNum) 
        //{
        //  StopRecord ();
        //}
    }   
  }
}
// ゴーストデータクラス

[Serializable]
public class GhostData0 {
// 位置のリスト
public List posLists = new List();
// 角度リスト
public List rotLists = new List();

}
// ゴーストデータクラス
[Serializable]
public class GhostData1 {
// 位置のリスト
public List posLists = new List();
// 角度リスト
public List rotLists = new List();

}
// キャラクターデータの保存
public void SetupRecord(){
Load();
StartRecord();
StartGhost();
}
public void StartRecord() {
//Debug.Log ("On StartRecord");
// 保存する時はゴーストの再生を停止
//StopAllCoroutines ();
//StopGhost ();
isRecord = true;
elapsedTime = 0f;
ghostData1 = new GhostData1 ();
Debug.Log ("StartRecord");
}

// キャラクターデータの保存の停止
public void StopRecord() {
//Debug.Log ("On StopRecord");
isRecord = false;
Debug.Log ("StopRecord");
}

// ゴーストの再生ボタンを押した時の処理
public void StartGhost() {
//Debug.Log ("On StartGhost");
Debug.Log ("StartGhost");
if (ghostData0 == null) {
Debug.Log ("ゴーストデータがありません");
} else {
Debug.Log("データがあります");
//isRecord = false;
isPlayBack = true;
ghost.transform.position = ghostData0.posLists [0];
ghost.transform.rotation = ghostData0.rotLists [0];
ghost.SetActive (true);
StartCoroutine (PlayBack ());
}
}

// ゴーストの停止
public void StopGhost() {
//Debug.Log ("On StopGhost");
Debug.Log ("StopGhost");
StopAllCoroutines ();
isPlayBack = false;
ghost.SetActive (false);
}
// ゴーストの再生
IEnumerator PlayBack() {
Debug.Log ("On PlayBack");
var i = 0;
var ghostAnimator = ghost.GetComponent ();

Debug.Log ("データ数: " + ghostData0.posLists.Count);

while (isPlayBack) {

    yield return new WaitForSeconds (recordDuration);

    ghost.transform.position = ghostData0.posLists [i];
    ghost.transform.rotation = ghostData0.rotLists [i];
    //ghostAnimator.SetFloat("Speed", ghostData.speedLists[i]);

    //if (ghostData.jumpAnimLists [i]) {
    //  ghostAnimator.SetTrigger ("Jump");
    //}

    i++;

    // 保存データ数を超えたら最初から再生
    if (i >= ghostData0.posLists.Count) {

        ghostAnimator.SetFloat ("Speed", 0f);
        ghostAnimator.ResetTrigger ("Jump");

        // アニメーション途中で終わった時用に待ち時間を入れる
        yield return new WaitForSeconds (waitTime);

        ghost.transform.position = ghostData0.posLists [0];
        ghost.transform.rotation = ghostData0.rotLists [0];

        i = 0;
    }
}

}
public void Save() {
if (ghostData1 != null) {
// GhostDataクラスをJSONデータに書き換え
var data = JsonUtility.ToJson (ghostData1);
// ゲームフォルダにファイルを作成
File.WriteAllText (Application.dataPath + saveDataFolder + saveFileName, data);
Debug.Log ("ゴーストデータをセーブしました");
}
}

public void Load() {

if (File.Exists (Application.dataPath + saveDataFolder + saveFileName)) {
    string readAllText = File.ReadAllText (Application.dataPath + saveDataFolder + saveFileName);
    // ghostDataに読み込んだデータを書き込む
    if (ghostData0 == null) {
        ghostData0 = new GhostData0 ();
    }
    JsonUtility.FromJsonOverwrite (readAllText, ghostData0);
    Debug.Log ("ゴーストデータ"+ readAllText +"をロードしました。");
}

}

void OnApplicationQuit() {
Debug.Log ("アプリケーション終了");
Save ();
}

}

このスクリプトではコースを走っているときに記録する箱とその時に違うデータを呼び出す箱を用意しています
では、なぜ用意するのでしょうか?
それはコースを走っているときに記録する箱と呼び出す箱が同じだと上書きされて呼び出したいデータが今は知っているデータに書き換えられてい舞うからです。

最後に

このスクリプトを使ったcar race ゲームでAOに合格することができました。