Hi, please help me with data storage/filling in Unity. For example I have this classes
using UnityEngine;
[System.Serializable]
public class Socket
{
[field: SerializeField] public string socketName { get; private set; }
// some other info and logic
}
using UnityEngine;
[System.Serializable]
public class Cpu
{
[field: SerializeField] public string cpuName { get; private set; }
[field: SerializeField] public Socket socket { get; private set; }
[SerializeField] private coreInfo[] coresInfo;
[System.Serializable]
private class coreInfo
{
[field: SerializeField] public int coresAmount { get; private set; }
[field: SerializeField] public Core core { get; private set; }
}
// soem other info and logic
}
using UnityEngine;
[System.Serializable]
public class Core
{
[field: SerializeField] public float minfrequency { get; private set; } // in MHz
[field: SerializeField] public float maxfrequency { get; private set; } // in MHz
// other info and logic
}
using System.Collections.Generic;
using UnityEngine;
public abstract class BaseDataStorage<T> : ScriptableObject where T : class
{
[SerializeField] private T[] database;
public IEnumerable<T> GetData { get { return database; } }
}
using UnityEngine;
[CreateAssetMenu(fileName = "Database", menuName = "Databases/Socket")]
public class SocketsDatabase : BaseDataStorage<Socket>
{
}
using UnityEngine;
[CreateAssetMenu(fileName = "Database", menuName = "Databases/Cpu")]
public class CpusDatabase : BaseDataStorage<Cpu>
{
}
When I fill the cpu database, coresInfo instances will be created in the cpu instance and that suits me, but in the socket field I don’t want to create a new socket inside the cpu instance, I want instead to be able to paste there a link to the instance from the array from SocketsDatabase. Rroughly the same way as passing gameobjects or monobehaviour scripts is implemented. How to implement this? Are there any third-party assets/plugins or do I need to write an extension for the unity editor? Or any other variants to create databases in Unity?
Well what you describe is impossible with your current code as you only have a list of Cpu. Unity’s by-values serialisation will only ever serialise these directly into the CpusDatabase scriptable object.
Your CPU’s would need to be scriptable objects themselves.
You mean inheritate Cpu and Socket from scriptableobject? That’s not suitable for me because I will create new instances of them during the game and later save them in file(gamesave). Doing all that is bad with scriptableobjects. I want to use scriptableobjects only to store pre-prepared information and not interact with them in any other way.
Well you can’t do what you’re trying to do, not without encapsulating further with something that can differentiate between a straight by-values CPU and a reference to an object that defines a CPU.
You probably just want two storage objects. One for the pre-made CPU’s, and one that you register all runtime generated ones.
I don’t know exactly how to implement what I want. I asked chatgpt to write me something. And he wrote me an editor extension, which in this script
public class Test : ScriptableObject
{
[SerializeField] private Cpu[] cpuDatabase;
[SerializeField] private Socket[] socketDatabase;
}
linked an instance from socketDatabase[num] into the cpuDatabase[num].socket field. This is not what I need, but I think it can be modified to an acceptable level
Chat GPT is useless for a lot of things, like this instance. I’m not sure what that example is even meant to accomplish. Unity’s default by-value serialisation can’t do what you’re trying to do.
Like I said, that most you can do is some kind of encapsulation:
public class CPUDatabase
{
[SerializeField]
private List<CPUInstance> _cpuInstances = new();
}
[System.Serializable]
public sealed class CPUInstance
{
[SerializeReference]
private CPUReference _cpuReference = null;
}
[System.Serializable]
public abstract class CPUReference
{
public abstract CPU { get; }
}
[System.Serializable]
public sealed class CPUReferenceInstance : CPUReference
{
[SerializeField]
private CPU _cpu;
public override CPU => _cpu;
}
[System.Serializable]
public sealed class CPUReferenceAsset : CPUReference
{
[SerializeField]
private CPUScriptableObject _cpuScriptableObject;
public override CPU => _cpuScriptableObject.CPU;
}
Another type of reference is one that can hot-look up from another database as well.