Hello all, I’ve run into an issue that probably comes from my shallow understanding of serialization and how scriptable objects work.
Some of my scriptable objects hold references to an array of other scriptable objects, like so:
using System.Linq;
using UnityEngine;
using static Item;
using static SpellRank;
public class SkillObject : ScriptableObject
{
[Header("About this Skill")]
public string skillName = "Name";
public string skillDescription = "Description";
public AttributeObject[] attributes;
public DamageObject[] damages;
[Header("Spell Ranks")]
[Tooltip("Define if the spell rank modifier requires a specific item type be equipped to be applied")]
public ItemTypes spellRankItemTypes;
[Range(-5, 5)]
public int modifier;
public HandheldSpells handheldSpells;
public Skill Init()
{
var permanentAttributeArray = attributes.Select(a => a.Init()).ToArray();
// problem occurs here - never during the attribute.Init (even when AttributeObject arr. is empty)
var damageArray = damages.Select(d => d.Init()).ToArray();
return new Skill(skillName,
skillDescription,
permanentAttributeArray,
damageArray,
spellRanks);
}
}
Each scriptable object has an Init() method which returns a class that the scriptable object represents, so in our example the SkillObject.Init() method returns an instance of a Skill. AttributeObject.Init() returns a new Attribute, DamageObject.Init() returns a Damage instance, etc.
The problem is every time I change anything on a SkillObject - for example, let’s say I add another AttributeObject to the AttributeObject array:
Unity will now error because it thinks the DamageObject array is null (null, not empty). Here’s the DamageObject code:
public class DamageObject : ScriptableObject
{
[Header("About this damage")]
public string description = "Damage Description";
[Header("Stats")]
public int damageMin = 0;
public int damageMax = 0;
public int damageOverTimeMin = 0;
public int damageOverTimeMax = 0;
public float damageOverTimeDuration = 0;
public DamageTypes damageTypes;
public DamageApplication damageApplicationType;
public Damage Init()
{
return new Damage((damageMin, damageMax),
(damageOverTimeMin, damageOverTimeMax, damageOverTimeDuration),
damageTypes,
damageApplicationType);
}
}
I’ve narrowed it down to this specific scriptable object. Even if adding an attribute, it’s the damage object which for some reason becomes null.
If I right click my Resources folder and hit Reimport, the problem goes away and everything works as expected.
Is it a bad idea to have scriptable objects store references to other scriptable objects? Am I using scriptable objects in a really gimpy way, or am I just missing something obvious in the DamageObject code?
For reference, the AttributeObject never has this problem (tested by commenting out DamageObject array and refactoring the Skill to not require Damage instances). Here is the AttributeObject code:
public class AttributeObject : ScriptableObject
{
[Header("About this attribute")]
public string attributeDescription = "Attribute Description";
[Header("Stats")]
public int attributeAmount = 0;
public AttributeTypes attributeTypes;
public bool isMultiplicative = true;
public Attribute Init()
{
return new Attribute(attributeAmount, attributeTypes, isMultiplicative);
}
}
Would appreciate any insights here - feels like it could be a UnityEditor bug since a reimport fixes everything - but again, maybe not and my workflow is the issue.