Search code examples
unity-game-engineserializationbuild-errorscriptable-object

ScriptableObject build error with Inheritance but runs fine in Unity Editor


here is the error i recieve: enter image description here

the error is on this line.:

 if (pItem.isStackable)
 {
 }

I should note that the error only occurs when I build the game. It does not occur when I run the game in the editor.

I believe the error comes from trying to give the player a weapon in their inventory.

because this runs fine:

 Player.playerInv.AddItem(apple);

and this doesn't:

  Player.playerInv.AddItem(sword2);

the only difference is apple is an item and Sword2 is a weapon... I have reason to believe that the build is expecting an Item to be loaded and not a weapon. (Weapon is a child of item. item inherits ScriptableObject).

here is the code for weapons and items (sorry for large file):

 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 
 [CreateAssetMenu(fileName = "Item", menuName = "StrangeEngine/Item", order = 2)]
 public class Item : ScriptableObject
 {
     public enum ItemType
     {
         Item = 1,
         Skill = 2,
         Equipment = 3
     }
     public ItemType type;
     public int ID;
     public string itemName;
     public string info;
     public int worth;
     public bool isStackable = false;
     //public Sprite icon;
     public Dictionary<string, int> itemStats = new Dictionary<string, int>(); // "stats" that come in pairs, a name (string) and a number. for example ("weight", 22)
 
     public Item(ItemType pType, int pID, string pName, string pInfo, int pWorth, Dictionary<string,int> pStats)
     {
         type = pType;
         ID = pID;
         itemName = pName;
         info = pInfo;
         worth = pWorth;
         itemStats = pStats;
     }
     public Item(ItemType pType, int pID, string pName, string pInfo, int pWorth, Dictionary<string, int> pStats, bool pIsStackable)
     {
         type = pType;
         ID = pID;
         itemName = pName;
         info = pInfo;
         worth = pWorth;
         itemStats = pStats;
         isStackable = pIsStackable;
     }
 }
 
 [CreateAssetMenu(fileName = "Item", menuName = "StrangeEngine/Weapon", order = 3)]
 public class Weapon : Item
 {
     public int Damage;
     public GameObject WeaponModelPrefab;
 
 
     public Weapon(int pID, string pName, string pInfo, int pWorth, Dictionary<string, int> pStatsfloat, int pDamage, GameObject pWeaponPrefab) : base(ItemType.Equipment,pID, pName, pInfo,pWorth,pStatsfloat)
     {
         Damage = pDamage;
         WeaponModelPrefab = pWeaponPrefab;
     }
 }
 

Solution

  • I can see a couple of warning signs here. But, in particular, that error might be related to the fact that you've got constructors in use. For ScriptableObject types, you should let Unity deal with constructing the item.

    ScriptableObject is generally used to serialise data for use at runtime. After that, the SO's can be used throughout your game. But creating new ones should be bone with the CreateInstance method as described here at the Unity Docs.

    Your constructors are all just setting private fields anyway. You could assign them from the calling code instead of passing it through as constructor arguments.

    Another point, you should be aware that Unity won't serialise dictionaries. You CAN serialise a List<T> and use the ISerializationCallbackReceiverinterface to then deserialise the List into a Dictionary<Tk, Tv>, but that's up to you to decide if you need to serialise that data, or you're just using it at runtime. You can find more about the ISerializationCallbackReceiverhere.

    The SO's do listen to a handful of the Unity messages as well. So you could, for example, use the Awake message to do any SO initialisation. A quick rundown of the SO messages can be found on this page.

    To sum up, I believe your problem is that your bypassing constructor setup from the inherited SO, and this causing issues with the serialisation in general.