Then thatâs not âwriting to disk via codeâ. Thatâs manually writing JSON, which you really shouldnât do as it will be glacial.
Lets get more to the point, you said you wanted:
Yes you can do that, but you actually⌠need to write the name to disk to make that possible.
I think this will just be easier if I just make an example:
PersistenceExample.unitypackage (20.7 KB)
The code for anyone who doesnât want to download the package:
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public sealed class PersistanceExample : MonoBehaviour
{
#region Inspector Fields
[SerializeField, Min(0.1f)]
private float _spawnRadius = 1.0f;
[SerializeField]
private List<GameObject> _prefabs = new();
#endregion
#region Internal Members
private readonly List<GameObject> _prefabInstances = new();
#endregion
#region Properties
public static string SavePath => Application.persistentDataPath + "/PrefabInstanceData.txt";
#endregion
#region Unity Callbacks
private void Awake()
{
TryLoadExistingInstanceData();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R) == true)
{
ClearAllActivePrefabs();
}
if (Input.GetKeyDown(KeyCode.Space) == true)
{
SpawnRandomPrefab();
}
if (Input.GetKeyDown(KeyCode.S) == true)
{
SaveActiveInstances();
}
}
private void OnDrawGizmosSelected()
{
#if UNITY_EDITOR
UnityEditor.Handles.color = Color.blue;
UnityEditor.Handles.DrawWireDisc(transform.position, transform.up, _spawnRadius);
#endif
}
#endregion
#region Internal Methods
private void TryLoadExistingInstanceData()
{
string path = SavePath;
bool exists = File.Exists(path);
if (exists == false)
{
return;
}
string json = File.ReadAllText(path);
var instanceData = JsonUtility.FromJson<PrefabInstanceData>(json);
foreach (PrefabInstance prefabInstance in instanceData.PrefabInstances)
{
string name = prefabInstance.Name;
if (TryGetPrefabByName(name, out var prefab) == true)
{
Vector3 position = prefabInstance.Position;
Quaternion rotation = prefabInstance.Rotation;
SpawnPrefab(prefab, position, rotation);
}
}
}
private void SpawnRandomPrefab()
{
int index = Random.Range(0, _prefabs.Count);
var prefab = _prefabs[index];
Vector2 spawnPoint2D = Random.insideUnitCircle * _spawnRadius;
Vector3 position = new (spawnPoint2D.x, 0, spawnPoint2D.y);
SpawnPrefab(prefab, position, Quaternion.identity);
}
private void SpawnPrefab(GameObject prefab, Vector3 position, Quaternion rotation)
{
var prefabInstance = Instantiate(prefab, position, rotation);
_prefabInstances.Add(prefabInstance);
}
private void ClearAllActivePrefabs()
{
foreach (var prefabInstance in _prefabInstances)
{
Destroy(prefabInstance);
}
_prefabInstances.Clear();
}
private bool TryGetPrefabByName(string name, out GameObject prefab)
{
prefab = null;
foreach (GameObject p in _prefabs)
{
bool nameMatch = name.StartsWith(p.name); // instances have names ending with (Clone)
if (nameMatch == true)
{
prefab = p;
return true;
}
}
return false;
}
private void SaveActiveInstances()
{
var instanceData = new PrefabInstanceData();
foreach (GameObject prefabInstance in _prefabInstances)
{
instanceData.AddPrefabInstance(prefabInstance);
}
string savePath = SavePath;
string json = JsonUtility.ToJson(instanceData, prettyPrint: true);
File.WriteAllText(savePath, json);
}
#endregion
#region Nested Types
[System.Serializable]
public sealed class PrefabInstanceData
{
#region Internal Members
[SerializeField]
private List<PrefabInstance> _prefabInstances = new();
#endregion
#region Properties
public IReadOnlyList<PrefabInstance> PrefabInstances => _prefabInstances;
#endregion
#region Methods
public void AddPrefabInstance(GameObject prefabInstance)
{
var instance = new PrefabInstance(prefabInstance);
_prefabInstances.Add(instance);
}
#endregion
}
[System.Serializable]
public struct PrefabInstance
{
#region Internal Members
[SerializeField]
private string _name;
[SerializeField]
private Vector3 _position;
[SerializeField]
private Quaternion _rotation;
#endregion
#region Properties
public readonly string Name => _name;
public readonly Vector3 Position => _position;
public readonly Quaternion Rotation => _rotation;
#endregion
#region Constructors
public PrefabInstance(GameObject prefab)
{
_name = prefab.name;
_position = prefab.transform.position;
_rotation = prefab.transform.rotation;
}
#endregion
}
#endregion
}
Spawn a prefab with Space, reset them with R, and save the current ones with S. It will attempt to spawn prefabs from existing data in Awake.
Example of the JSON:
{
"_prefabInstances": [
{
"_name": "Sphere(Clone)",
"_position": {
"x": 2.902937173843384,
"y": 0.0,
"z": -3.939030170440674
},
"_rotation": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 1.0
}
},
{
"_name": "Sphere(Clone)",
"_position": {
"x": 4.597560882568359,
"y": 0.0,
"z": -0.8488390445709229
},
"_rotation": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 1.0
}
},
{
"_name": "Sphere(Clone)",
"_position": {
"x": 1.465227723121643,
"y": 0.0,
"z": -0.9499194622039795
},
"_rotation": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 1.0
}
},
{
"_name": "Capsule(Clone)",
"_position": {
"x": -2.340095043182373,
"y": 0.0,
"z": -3.0521860122680666
},
"_rotation": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 1.0
}
},
{
"_name": "Cube(Clone)",
"_position": {
"x": -4.0832319259643559,
"y": 0.0,
"z": -0.263769268989563
},
"_rotation": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 1.0
}
}
]
}