0

After running the following loop (one iteration), battleshipParts.Count returns 2.

The code is ran once in the ScriptableObject.Awake

for (byte i = 0; i < 1; i++)
{
    var battleshipPart = CreateInstance<BattleshipPart>();
    battleshipPart.battleshipData = this;
    battleshipParts.Add(battleshipPart);
}

I tried using the debugger and walking through the code, after the execution of

battleshipPart.battleshipData = this;

battleshipParts.Count is already 1

battleshipPart.battleshipData is used to hold a reference to its battleship parent. Implementation:

public class BattleshipPart : ScriptableObject
{
    public Vector2 gridPosition;
    public BattleshipData battleshipData;
    public bool isHit = false;
}

The battleshipParts list isn't modified anywhere else besides this code. Besides. Why would it update itself with a null value after running battleshipPart.battleshipData = this;?

Phillip Zoghbi
  • 512
  • 3
  • 15
  • 2
    Where is `battleshipParts` declared and initialized? Where else is it used in any code anywhere? – Retired Ninja Jun 07 '23 at 21:41
  • At the top of the caller class (`this` in the code provided) `public List battleshipParts = new List();` – Phillip Zoghbi Jun 07 '23 at 21:57
  • 1
    Consider putting together a [mcve] so we can see the full picture. – Retired Ninja Jun 07 '23 at 22:13
  • 2
    as the list is not cleared before the loop if that code runs twice you would have 2, or 3 or more depending on how many times it ran – BugFinder Jun 07 '23 at 22:27
  • @BugFinder Clearing the list worked, but not for the reason I would've thought. Surprisingly enough, `ScriptableObject.Awake` was invoked from assigning the reference to this object in the inspector. According to [Unity's docs](https://docs.unity3d.com/ScriptReference/ScriptableObject.Awake.html) that should've only happened when the game runs. – Phillip Zoghbi Jun 07 '23 at 23:16
  • A scriptable object retains its state variables until explicitly set. It is easy to see this by adding a bool, press play and set it true, then hit stop in the editor. The bool will stay true. This is a bit different than monobehaviours, which may be the cause of confusion. – hijinxbassist Jun 08 '23 at 00:06
  • You're right, values stay remembered in the `.asset` files. However, I'm cloning the instance, and `Awake` shouldn't have been called by the inspector. At least not according to the docs. – Phillip Zoghbi Jun 08 '23 at 03:25

1 Answers1

0

This error because you create Instance not Asset and trying to save it into list.

Just create .asset(ScriptableObject) file with AssetDatabase in project.

    for (byte i = 0; i < 1; i++)
    {
        BattleshipPart battleshipPart = ScriptableObject.CreateInstance<BattleshipPart>();
        AssetDatabase.CreateAsset(battleshipPart, $"Assets/BattleshipPart_{i}.asset");
        AssetDatabase.SaveAssets();

        battleshipPart.battleshipData = this;
        battleshipParts.Add(battleshipPart);
    }

If you don't want to create asset file in your project, just use simple serialized class not ScriptableObject.

Dellivi
  • 26
  • 2