我有一个为
GameObject
制作的列表(编辑器下拉列表),这是一个包含两个的列表。我的脚本在两者之间轮换,效果很好。我用 ScriptableObject
s 尝试了同样的方法,但不起作用。我在编辑器中选择对象,这有效,但是当我进行游戏测试时,两个值都变为 None
。
底部的所有垃圾都是浮点数和布尔值。
public int totalWeapons = 2;
int currentWeaponIndex;
public GameObject[] weapons;
public Weapons[] weaponsData;
public GameObject currentWeaponGO;
GameObject weaponHolder;
private void Awake()
{
weapons = new GameObject[totalWeapons];
weaponsData = new Weapons[totalWeapons];
for (int i = 0; i < totalWeapons; i++)
{
weapons[i] = transform.GetChild(i).gameObject;
weapons[i] .SetActive(false);
}
weapons [0].SetActive(true);
currentWeaponGO = weapons[0];
currentWeaponIndex = 0;
refreshWeapon();
currentAmmo = currentWeapon.maxAmmoCapacity;
weaponHolder = this.GetComponent<GameObject>();
}
private void Update()
{
scroll();
}
void scroll()
{
if(Input.GetAxis("Mouse ScrollWheel") < 0f && currentWeaponIndex < totalWeapons -1)
{
currentWeapon = weaponsData[1];
weapons[currentWeaponIndex].SetActive(false);
currentWeaponIndex += 1;
weapons[currentWeaponIndex].SetActive(true);
refreshWeapon();
}
if(Input.GetAxis("Mouse ScrollWheel") > 0f && currentWeaponIndex > 0)
{
weapons[currentWeaponIndex].SetActive(false);
currentWeaponIndex -= 1;
weapons[currentWeaponIndex].SetActive(true);
refreshWeapon();
}
}
void refreshWeapon()
{
cooldown = currentWeapon.timeBetweenShots;
maxAmmo = currentWeapon.maxAmmoCapacity;
maxRange = currentWeapon.Range;
bulletSpread = currentWeapon.spread;
pelletAmount = currentWeapon.projectileAmountPerShot;
hitscanDamage = currentWeapon.HsDamage;
knockBack = currentWeapon.knockBack;
knockBackForce = currentWeapon.knockBackForce;
ammoType = currentWeapon.ammoType;
}
您没有提供此信息,但我可以猜测
Weapons
是您的ScriptableObject
。如果这是正确的,则会发生以下情况:
public Weapons[] weaponsData;
您可以在其中设置数据Awake
中,您用 weaponsData = new Weapons[totalWeapons];
覆盖您设置的数据,这会导致 weaponsData
包含 null
的数组,在 Inspector 中显示为 None
。简短回答
只需删除这一行:
weaponsData = new Weapons[totalWeapons];
长答案
您在 Inspector 中设置的值由 Unity 序列化(作为项目的一部分存储到驱动器中)。当游戏运行时,Unity首先从驱动器中读取这些值,然后调用
Awake
。
知道这一点,您还可以避免覆盖
weapons
数组:
private void Awake()
{
weapons[0].SetActive(true);
for (int i = 1; i < totalWeapons; i++)
{
weapons[i].SetActive(false);
}
currentWeaponGO = weapons[0];
currentWeaponIndex = 0;
refreshWeapon();
currentAmmo = currentWeapon.maxAmmoCapacity;
weaponHolder = this.GetComponent<GameObject>();
}
但是如果您想在代码中而不是在 Inspector 中完成所有操作该怎么办?您需要在
weapons
数组旁边填充您的 WeaponsData 数组。一个简单的方法是这样的:
for (int i = 0; i < totalWeapons; i++)
{
weapons[i] = transform.GetChild(i).gameObject;
weapons[i] .SetActive(false);
weaponsData[i] = ScriptableObject.CreateInstance<Weapons>();
}
weapons[0].SetActive(true);
但这会创建 ScriptableObjects 的新实例,而不是使用项目中存储的实例。
要使用存储的 ScriptableObject 资源,您需要将它们移动到 Resources 文件夹(如果不存在则创建一个),然后通过该文件夹中的路径加载它们。比方说,您将 ScriptableObject 资源移动到“Assets/Resources/Weapons”文件夹,它们被命名为“Weapons1”和“Weapons2”,您可以像这样加载它们:
for (int i = 0; i < totalWeapons; i++)
{
weapons[i] = transform.GetChild(i).gameObject;
weapons[i] .SetActive(false);
weaponsData[i] = Resources.Load<Weapons>("Weapons/Weapons" + i);
}
weapons[0].SetActive(true);