带有继承的 ScriptableObject 构建错误,但在 Unity 编辑器中运行良好
ScriptableObject build error with Inheritance but runs fine in Unity Editor
这是我收到的错误:
错误在这一行。:
if (pItem.isStackable)
{
}
我应该注意到错误只发生在我构建游戏时。当我在编辑器中 运行 游戏时,它不会发生。
我认为错误是因为试图在玩家的物品栏中给他们一把武器。
因为这个 运行 很好:
Player.playerInv.AddItem(apple);
而这不是:
Player.playerInv.AddItem(sword2);
唯一的区别是 apple 是一个物品,而 Sword2 是一个武器...我有理由相信这个版本需要加载一个物品而不是武器。 (武器是 item 的子项。item 继承 ScriptableObject)。
这是武器和物品的代码(抱歉文件太大):
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;
}
}
我可以在这里看到几个警告标志。但是,特别是,该错误可能与您使用了构造函数这一事实有关。对于 ScriptableObject
类型,您应该让 Unity 处理项目的构建。
ScriptableObject
一般用于序列化数据,以便在运行时使用。之后,SO 可以在您的游戏中使用。但是创建新的应该使用 CreateInstance
方法,如 Unity 文档中 here 所述。
无论如何,您的构造函数都只是设置私有字段。您可以从调用代码中分配它们,而不是将其作为构造函数参数传递。
还有一点,你应该知道Unity不会序列化字典。您可以序列化 List<T>
并使用 ISerializationCallbackReceiver 接口,然后将列表反序列化为 Dictionary,但这由您决定是否需要序列化该数据,或者您只是在运行。您可以找到有关 ISerializationCallbackReceiverhere.
的更多信息
SO 也会收听一些 Unity 消息。因此,例如,您可以使用 Awake 消息进行任何 SO 初始化。可以在 this 页面上找到 SO 消息的简要说明。
总而言之,我认为您的问题是您绕过了继承 SO 的构造函数设置,这通常会导致序列化出现问题。
这是我收到的错误:
错误在这一行。:
if (pItem.isStackable)
{
}
我应该注意到错误只发生在我构建游戏时。当我在编辑器中 运行 游戏时,它不会发生。
我认为错误是因为试图在玩家的物品栏中给他们一把武器。
因为这个 运行 很好:
Player.playerInv.AddItem(apple);
而这不是:
Player.playerInv.AddItem(sword2);
唯一的区别是 apple 是一个物品,而 Sword2 是一个武器...我有理由相信这个版本需要加载一个物品而不是武器。 (武器是 item 的子项。item 继承 ScriptableObject)。
这是武器和物品的代码(抱歉文件太大):
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;
}
}
我可以在这里看到几个警告标志。但是,特别是,该错误可能与您使用了构造函数这一事实有关。对于 ScriptableObject
类型,您应该让 Unity 处理项目的构建。
ScriptableObject
一般用于序列化数据,以便在运行时使用。之后,SO 可以在您的游戏中使用。但是创建新的应该使用 CreateInstance
方法,如 Unity 文档中 here 所述。
无论如何,您的构造函数都只是设置私有字段。您可以从调用代码中分配它们,而不是将其作为构造函数参数传递。
还有一点,你应该知道Unity不会序列化字典。您可以序列化 List<T>
并使用 ISerializationCallbackReceiver 接口,然后将列表反序列化为 Dictionary
SO 也会收听一些 Unity 消息。因此,例如,您可以使用 Awake 消息进行任何 SO 初始化。可以在 this 页面上找到 SO 消息的简要说明。
总而言之,我认为您的问题是您绕过了继承 SO 的构造函数设置,这通常会导致序列化出现问题。