unityでbaba is youのようなゲームを作っています。ひとつ前の状況に戻れる設計にするにはどうすればいいですか?

実現したいこと

unityでbaba is youのようなゲームを作っています。
何回でもひとつ前の状況に戻れる実装を行いたいです。

前提

自分が現在どのような状況か説明します。
cameraやlevelmanager以外のオブジェクトに動きがあった場合はその位置をlistで記録する。
戻りたい時は、listの要素数から1マイナスして、記録された場所に該当するオブジェクトを生成することで、ひとつ前の状況を再現している。

発生している問題・エラーメッセージ

はじめに3回オブジェクトを動かし3回戻るボタンを押せば、ちゃんと最初の状況に戻るのですが、そのあと2回オブジェクトを動かして、戻るボタンを押すとオブジェクトがすべて消えてしまいます(cameraやlevelmanager以外)。listの0番目(最初の状況)まで戻れば、オブジェクトは生成されます。

エラーメッセージ

該当のソースコード

public class LevelManager : MonoBehaviour { private List<GameState> gameStates = new List<GameState>(); private int currentStateIndex = -1; [SerializeField] private GameObject uni; [SerializeField] private GameObject uni_Text; [SerializeField] private GameObject is_Text; [SerializeField] private GameObject you_Text; [SerializeField] private GameObject win_Text; // Start is called before the first frame update void Start() { SaveGameState(); } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.U)) { Undo(); Debug.Log(currentStateIndex); } } public void SaveGameState() { GameState state = new GameState(); GameObject[] allObjects = GameObject.FindObjectsOfType<GameObject>(); foreach (GameObject obj in allObjects) { if (obj.name == "UNI") { state.uni.Add(obj.transform.position); } else if (obj.name == "UNI_Text") { state.uni_Text.Add(obj.transform.position); } else if (obj.name == "IS_Text") { state.is_Text.Add(obj.transform.position); } else if (obj.name == "YOU_Text") { state.you_Text.Add(obj.transform.position); } else if (obj.name == "WIN_Text") { state.win_Text.Add(obj.transform.position); } } gameStates.Add(state); currentStateIndex = gameStates.Count - 1; } void Undo() { if (currentStateIndex > 0) { GameObject[] objects = GameObject.FindGameObjectsWithTag("Object"); foreach (GameObject obj in objects) { Destroy(obj); } GameObject[] texts = GameObject.FindGameObjectsWithTag("Text"); foreach (GameObject obj in texts) { Destroy(obj); } gameStates.RemoveAt(currentStateIndex); currentStateIndex--; RestoreGameState(); } } void RestoreGameState() { GameState state = gameStates[currentStateIndex]; foreach (var obj in state.uni) { Instantiate(uni, obj, Quaternion.identity); uni.tag = "Object"; } foreach (var obj in state.uni_Text) { Instantiate(uni_Text, obj, Quaternion.identity); uni_Text.tag = "Text"; } foreach (var obj in state.is_Text) { Instantiate(is_Text, obj, Quaternion.identity); is_Text.tag = "Text"; } foreach (var obj in state.you_Text) { Instantiate(you_Text, obj, Quaternion.identity); you_Text.tag = "Text"; } foreach (var obj in state.win_Text) { Instantiate(win_Text, obj, Quaternion.identity); win_Text.tag = "Text"; } } private class GameState { public List<Vector3> uni = new List<Vector3>(); public List<Vector3> uni_Text = new List<Vector3>(); public List<Vector3> is_Text = new List<Vector3>(); public List<Vector3> you_Text = new List<Vector3>(); public List<Vector3> win_Text = new List<Vector3>(); } 以下はオブジェクトを動かすスクリプト。 public class PlayerController : MonoBehaviour { public LevelManager levelManager; [SerializeField] private GameObject player; private bool play; private bool push; // Start is called before the first frame update void Start() { levelManager = GameObject.Find("LevelManager").GetComponent<LevelManager>(); } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.A)) { transform.position += new Vector3(-1, 0, 0); levelManager.SaveGameState(); } if (Input.GetKeyDown(KeyCode.D)) { transform.position += new Vector3(1, 0, 0); levelManager.SaveGameState(); } if (Input.GetKeyDown(KeyCode.W)) { transform.position += new Vector3(0, 1, 0); levelManager.SaveGameState(); } if (Input.GetKeyDown(KeyCode.S)) { transform.position += new Vector3(0, -1, 0); levelManager.SaveGameState(); } } }

試したこと

ひとつ前の状況に戻るときはgameStates.Removeでlistの中にある現在の状況を削除するようにしたのですが、解決できませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

コメントを投稿

0 コメント