-
Notifications
You must be signed in to change notification settings - Fork 38
FAQ
It's really hard to make sure those features work perfectly with the system since it depends on to catch up the GUIDs of the collectables, ALWAYS try to use the Add New / Deleting by the inspector itself
For most of the cases, you don't need these objects to be fully serialized when using the references on Save Data and other cases, I recommend taking a look into the fsCollectableScriptableObjectConverter
inside the package, this uses FullSerializer to only serialize the necessary data, and rebuild the connection properly when serialize/deserialize the object
Since the CollectionsRegistry is inside the Resources folder, every reference this has to a collection and to all the collectables will be inside the Unity Resources bundle, and if have a lot of references for expensive stuff, this can decrease your startup time significantly, there's 2 things you should keep in mind:
- Use the Automatically Loaded items for items that should be available for the lifetime of your game
2.- If you want to use this for more expensive stuff, let's say all the gameplay prefabs, you can uncheck the automatic initialization of this collection, and register the collection on your loading by using
CollectionsRegistry.Instance.RegisterCollection(Collection);
and removing it when they are not necessary anymore.
You can use the Collection Creating Wizzard by right click on the project panel and going into: Assets/Create/Scriptable Object Collection/New Collection
this will create 3 items and respective folder: YourCollectionName.cs
YourCollectableName.cs
and the Collection Scriptable Object
When your collection it's selected you can Add/Remove items and re-organize their position on the list:
When you add a reference to a Collectable you may choose how you want this to be displayed by adding [CollectionItemEditorOptions]
.
There are two Draw Types for now:
-
DropDown
the default option which displays all the available options in a convenient drop-down, like an enum field -
AsReference
standard Scriptable Object field where you select the asset in a browser
You can generate a static file that will enable you to access any of your collections by code, for doing that, just click on the Generate Static File
on Inspector:
For non automatically loaded items, I suggest using the TryGetAccess static generation type, you can define this on the CollectionRegistry
file, this will provide TryGet methods instead of direct access to the collections itself, I think this helps since those objects can be not loaded in memory, so you are more conscious about it.
Any addressable asset that has a reference to a scriptableObject
, when is bundled a copy of that scriptable object will be created inside of the bundle, so if you are not doing anything fancy with the scriptableObject
should be fine, but if you are updating references or anything else, I recommend using the indirect reference. When creating a new Collection by the wizard, make sure you let the Generate Indirect Access
toggle on, and when adding references inside the scriptable objects, make sure you use the CollectableIndirectReferece
this only store the GUIDs of the target collectable without the actual reference to the object, so avoiding creating a relationship between items and avoiding bundling then together.
Some scriptable objects that you want to manage may inherit from a Scriptable Object-derived type that you yourself do not manage. Either one from Unity or perhaps from some plugin. This does not stop you from managing those items via a Scriptable Object Collection
. The SOC system internally manages its items via the ISOCItem
interface. ScriptableObjectCollectionItem
in turn implements that interface for an 'out-of-the-box' implementation of SOC functionality.
So if you wish to make a Scriptable Object usable, you need only make your class implement ISOCItem
and then copy the implementation of that interface from ScriptableObjectCollectionItem
. Here's an example of that:
public sealed class SomeCustomScriptableObject : ScriptableObject, ISOCItem
{
#region ISOCItem implementation
[SerializeField, HideInInspector]
private LongGuid guid;
LongGuid ISOCItem.GUID
{
get
{
if (guid.IsValid())
return guid;
((ISOCItem)this).GenerateNewGUID();
return guid;
}
}
[SerializeField, HideInInspector]
private LongGuid collectionGUID;
[NonSerialized] private bool hasCachedCollection;
[NonSerialized] private ScriptableObjectCollection cachedCollection;
public ScriptableObjectCollection Collection
{
get
{
if (!hasCachedCollection)
{
if (collectionGUID.IsValid())
{
cachedCollection = CollectionsRegistry.Instance.GetCollectionByGUID(collectionGUID);
}
else
{
CollectionsRegistry.Instance.TryGetCollectionFromItemType(GetType(), out cachedCollection);
if (cachedCollection != null)
{
collectionGUID = cachedCollection.GUID;
ObjectUtility.SetDirty(this);
}
}
hasCachedCollection = cachedCollection != null;
}
return cachedCollection;
}
}
void ISOCItem.SetCollection(ScriptableObjectCollection collection)
{
cachedCollection = collection;
collectionGUID = cachedCollection.GUID;
ObjectUtility.SetDirty(this);
}
void ISOCItem.GenerateNewGUID()
{
guid = LongGuid.NewGuid();
ObjectUtility.SetDirty(this);
}
}
#endregion ISOCItem implementation
You can now define a collection like so:
[CreateAssetMenu(menuName = "ScriptableObject Collection/Collections/Create SomeCustomScriptableObjectCollection", fileName = "SomeCustomScriptableObjectCollection", order = 0)]
public class SomeCustomScriptableObjectCollection : ScriptableObjectCollection<SomeCustomScriptableObject>
{
}