ScriptableObjects 未出现在列表中

问题描述 投票:0回答:1

我有一个为

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;
}
c# unity-game-engine integer scriptable-object
1个回答
0
投票

您没有提供此信息,但我可以猜测

Weapons
是您的
ScriptableObject
。如果这是正确的,则会发生以下情况:

  1. 您有您的检查器字段
    public Weapons[] weaponsData;
    您可以在其中设置数据
  2. 然后,在
    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);
© www.soinside.com 2019 - 2024. All rights reserved.