How to efficiently have scriptable objects reference other scriptable objects?

Hello! I have a collection of Scriptable Objects, with some representing items and others representing containers. I’m currently working on setting up the container objects to maintain a List of items they allow. However, I’m concerned about the potential performance impact of each container maintaining a List of Scriptable Object items.

For instance, when loading a container or passing around a reference to it, I don’t want it to include the entire data for all the Scriptable Object items in its allowed items list.

How can I prevent this?

My initial idea was to use a List of strings, where each string corresponds to the name of the Scriptable Object item I want to allow. Then, I could perform string comparisons. However, I would really appreciate it if there were a way to establish a dynamic link to the Scriptable Object itself. This way, if I change the name of an item, it will be automatically reflected in all the Lists that reference it.

This is already implemented in Unity and is called Addressables.

Addressables were created to solve many different problems at once (memory, asset management, async, tooling etc.) and this makes most of it’s documentation and tutorials confusing as they provide no clear short answers but lists and examples of solutions to some technical or specific pipeline problems.

Moving all that aside - Addressables is a system to access assets, that’s it. You can make this complicated or you can keep it simple - your choice.

What Addressables allow you to do is to replace list of direct references to Scriptable Objects with lists of indirect ones. Advantage of this being that indirect references do not trigger asset load operations immediately (longer scene start time, fps hiccups when loaded using older APIs) but on explicit async request only.

Alternatively, it’s worth considering, to keep these Scriptable Object references direct but replace all SO’s nested asset fields (GameObject, Texture2D, Sprite, Mesh etc) with indirect references. This is so you can keep all the tiny object’s always loaded in memory for immediate access but restrict loading of all potentially big assets to these explicit calls when they are needed.

Hello @mrVentures,

Using string is kind of a bad idea, you could make mistakes anywhere on the “way” to your item. If you want to have lists I would recommend you to use enum:

public enum ItemType {
   SWORD,
   SHIELD,
   HELMET,
   //...
}

And for your list of allowed item types you could have a custom class with a boolean and your enum:

[Serializable]
public class AuthorizedItems {
   public bool status;
   public ItemType type;
}

//...
public class Container : MonoBehaviour {

   public AuthorizedItems[] authItem;

}

However it all depends on what you need, if all you need is a variable to help you do comparisons then yeah enums are good for that, but if you really need to have those Scriptable Object moved around then you can try what @andrew-lukasik proposed