ARアプリにセーブ機能を付ける方法

AR

今回は配置したオブジェクトを保存してロードする機能を追加してみようと思います



スクリプト

以下にオブジェクトのセーブに関するスクリプトを示します

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

[System.Serializable]
public class ObjectData
{
    public string objectName;
    public Vector3 position;
    public Quaternion rotation;
    
}

[System.Serializable]
public class GameData
{
    public List<ObjectData> objects = new List<ObjectData>();
}
public class SaveLoadManager : MonoBehaviour
{
    private string filePath;
    public string objectTag = "d_obj"; // オブジェクトに付けられたタグ  

    private void Start()
    {
        filePath = Path.Combine(Application.persistentDataPath, "gameData.json");
    }

    public void SaveGame()
    {
        GameData gameData = new GameData();
        GameObject[] gameObjects = GameObject.FindGameObjectsWithTag(objectTag); // タグを持つオブジェクトを取得  

        foreach (GameObject obj in gameObjects)
        {
            ObjectData data = new ObjectData
            {
                objectName = obj.name,
                position = obj.transform.position,
                rotation = obj.transform.rotation,
               
            };
            gameData.objects.Add(data);
            Debug.Log(obj.name);
            Debug.Log(obj.transform.position);
        }

        string json = JsonUtility.ToJson(gameData, true);
        File.WriteAllText(filePath, json);
        Debug.Log("Game Saved");
    }

    public GameData LoadGame()
    {
        if (File.Exists(filePath))
        {
            string json = File.ReadAllText(filePath);
            GameData gameData = JsonUtility.FromJson<GameData>(json);
            Debug.Log("Game Loaded");
            Debug.Log(gameData);
            return gameData;
        }
        Debug.Log("Save file not found!");
        return null;
    }
}

セーブ時にオブジェクトをタグで検索するようになっています

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

public class GameController : MonoBehaviour
{
   
    
        private SaveLoadManager saveLoadManager;

        private void Start()
        {
            saveLoadManager = GetComponent<SaveLoadManager>();
        }

       
        public void Save()
        {
            saveLoadManager.SaveGame(); 
        }

        
        public void Load()
        {
            GameData gameData = saveLoadManager.LoadGame();
            if (gameData != null)
            {
                foreach (ObjectData data in gameData.objects)
                {
                    GameObject obj = GameObject.Find(data.objectName);
                    if (obj != null)
                    {
                        
                        obj.transform.position  = data.position;
                        obj.transform.rotation  = data.rotation;
                        Debug.Log(data.objectName);
                        Debug.Log(data.position);
                    //Instantiate(obj, obt, obr);

                }
                }
            }
        }
}

こちらがボタン割り当て用のスクリプトです

試しにオブジェクトを2つ配置してセーブしてみると・・・

Consoleからオブジェクト名とその位置情報を取得出来ているのが確認できます

続いて一旦この2つのオブジェクトを消去してからロードを試みると・・・

オブジェクトは読み込まれず、Console上でも情報が表示されませんでした

消去したオブジェクトを再び配置して先ほどとは異なる位置に移動してみます

この状態でロードをしてみると・・・

2つのオブジェクトは先ほどセーブした位置に移動し、Consoleにも名前と位置情報が表示されました

オブジェクト名も位置情報も読み込めているということになります

しかし、いざ生成する時にNull判定になってしまうのです・・・

もふもふ
もふもふ

???

気付き

取得したオブジェクト名

Water_dispenser_U(Clone)

リストに格納されているオブジェクト名

Water_dispenser_U

まさかとは思いつつ、取得したオブジェクト名から(Clone)を取り除く方法を調べました

 prefabName = obj.name.Replace("(Clone)", "").Trim(),

どうやらこのコードを使えばそれが実現できるようなので、藁にも縋る思いでコードを上書きしてみます

実行

成功してしまいました

(Clone)を取り除く必要があるとは夢にも思いませんでしたが、とにかく成功したのでよかったです



まとめ

プログラム実行中に生成されたオブジェクトをロードするには、セーブする時に名前から(Clone)を取り除く

ただし、私がたまたまこの結論に至っただけであって、他によい方法があれば是非教えて頂きたいです

もふもふ
もふもふ

誰に(;゚Д゚)

タイトルとURLをコピーしました