Unity - 通过 MouseWheel 锁定位置的武器切换(Arena Shooter 风格)

Unity - Weapon Switching by MouseWheel With Locked Positions (Arena Shooter Style)

我一直在努力弄清楚如何使用鼠标滚轮实现竞技场风格的射击武器切换。

到目前为止,我已经创建了 3 个列表;一个列表是所有可用的枪支(class 枪 [0 = 手枪,1 = 中继器,2 = 狙击手,3 = 火箭发射器]),下一个列表是一个布尔列表,具有固定位置,告诉您是否玩家已经解锁了那把枪(同样 0,1,2,3 是固定的)。我有第三个列表,它以您拥有的枪支开始,当您触摸拾取时会添加一个新的。

我很容易获得 alpha 键武器切换和快速武器切换(在以前的武器和当前的武器之间切换),但是鼠标滚动让我发疯。

我确定我想多了,但我不确定在以下情况下该怎么做: 玩家只有狙击手和手枪,这意味着我不能只做一个简单的 -1,否则会移动到玩家向下滚动时没有的连发器的索引。

我可以让它工作,它会与下一个武器交换(即:从 0 到 3),但如果我随后拿起中继器或狙击枪,它只会通过手枪和火箭发射器继续切换。

我真的不知道我在这里做什么,我猜...我一直在尝试不同的 for 循环来遍历列表。我真正想知道的是,是否有一种简单的方法可以遍历列表并获取下一个索引,或者如果我们到达列表的末尾,则转到第一个索引。

非常感谢任何帮助。

谢谢,

雅各

编辑:(这里要求的是相关代码片段)

这是我的播放器控制器中的变量:

//GUNS GUNS GUNS

public Gun activeGun;
public List<Gun> allGuns = new List<Gun>();
public List<bool> unlockedGuns = new List<bool>();
public List<Gun> gunsAvailable = new List<Gun>();
public int currentGun = 0;
private int previousGun;

在我的 Update() 函数中:

    if(Input.GetAxisRaw("Mouse ScrollWheel") != 0f)
    {
        SwitchGunByMouse(Input.GetAxis("Mouse ScrollWheel"));

    }

这是 SwitchGun() 方法,它可以很好地与字母键或快速切换键配合使用。

public void SwitchGun(int gunNumber)
{
    if (cannotChangeWeapon) return;
    
    //if (currentGun == gunNumber) return;

    if (gunNumber < 0)
    {
        gunNumber = allGuns.Count - 1;
    }

    if (gunNumber > allGuns.Count - 1)
    {
        gunNumber = 0;
    }

    for (int i = 0; i < unlockedGuns.Count; i++)
    {
        if(i == gunNumber && unlockedGuns[i])
        {
            activeGun.gameObject.SetActive(false);
            activeGun = allGuns[gunNumber];
            activeGun.gameObject.SetActive(true);
            previousGun = currentGun;
            currentGun = gunNumber;
            UIController.instance.ammoText.text = "AMMO: " + activeGun.ammo;
        }
    }
}

这是正在调用的方法,它不起作用,这是我上次尝试 fiddle 的来源。

public void SwitchGunByMouse(float direction)
{

    if (direction == 0f) return;

    int nextGun = -1;

    if (gunsAvailable.Count -1 > 0)
    {
        if (direction > 0f)
        {
            for(int i = 0; i < gunsAvailable.Count -1; i++)
            {
                if (currentGun == gunsAvailable[i].idNumber) continue;
                if (currentGun < gunsAvailable[i].idNumber)
                    nextGun = gunsAvailable[i].idNumber;
            }

            if (nextGun == -1)
                nextGun = 0;
        }

        if (direction < 0f)
        {
            //int currentPos = gunsAvailable.idNumber;

            nextGun = gunsAvailable[currentGun].idNumber -1;
            
            List<Gun> g = gunsAvailable;
            
            g.Reverse();

            for(int i = 0; i < g.Count - 1; i++)
            {
                if (currentGun == g[i].idNumber) continue;
                if (currentGun < g[i].idNumber)
                    nextGun = g[i].idNumber;
            }
            
            //Okay so if we still haven't found a gun it means the other gun has a high id than our current gun
            //so now we need to figure out how to cycle again

            if(nextGun == -1)
            {
                nextGun = 0;
            }

        }

        Debug.Log("NextGun: " + nextGun);

        if (nextGun > -1)
            SwitchGun(nextGun);
        else 
            Debug.Log("Something bad happened with SwitchGunByMouse()");

    }
    
}

最后:

public bool WeaponPickup(string gunToAdd, Gun myGun)
{
    switch(gunToAdd)
    {
        case "Repeater":
            if(unlockedGuns[1] == true)
                return false;
            else
            {
                unlockedGuns[1] = true;
                myGun.isCollected = true;
                gunsAvailable.Add(allGuns[1]);
                return true;
            }
        case "Sniper":
            if (unlockedGuns[2] == true)
                return false;
            else
            {
                unlockedGuns[2] = true;
                myGun.isCollected = true;
                gunsAvailable.Add(allGuns[2]);
                return true;
            }
        case "Rocket Launcher":
            if (unlockedGuns[3] == true)
                return false;
            else
            {
                unlockedGuns[3] = true;
                myGun.isCollected = true;
                gunsAvailable.Add(allGuns[3]);

                return true;
            }
        default:
            Debug.Log("Weapon Pickup ran into a problem with gunToAdd not matching a predefined string.");
            break;
    }

    return false;
}

如果您尝试向上或向下搜索数组并在我们找到一个为真的元素时停止搜索怎么办。

public void SwitchGunByMouse(float direction)
{
    if (gunsAvailable.Count > 1)
    {
        int up = 1 ? direction > 0f: -1;
        for(int i = currentGun + direction; i == currentGun; i += direction)
        {
             // first we make sure our index is not going to be under 0 which does not exist in a array element
             if(i < 0)
             { 
                 i = unlockedGuns.Count-1;
             }
             // next we make sure our index doesn't crush the upper bounds of our array
             if(i > unlockedGuns.Count - 1)
             {
                 i = 0;
             }
             // if the index is in the bounds of our array we check if the boolean is true 
             // if yes, the loop will finish and we have our new weapon
             if(unlockGuns[i])
             {
                currentGun = i;
                return;
             }
        }
    }
}

这应该可以解决问题:

    public void SwitchGunByMouse(float direction)
    {
        if (gunsAvailable.Count <= 1 || cannotChangeWeapon)
        {
            return;
        }

        int gunSwitchDirection = Mathf.Sign(direction);
        int gunCandidate = currentGun;
        bool isCorrect = false;

        do
        {
            gunCandidate += gunSwitchDirection;

            if (gunCandidate < 0)
            {
                gunCandidate = allGuns.Count -1;
            }
            else
            {
                gunCandidate %= allGuns.Count;
            }

            isCorrect = gunCandidate != currentGun && unlockedGuns[gunCandidate];
        }
        while (gunCandidate==currentGun || !unlockedGuns[gunCandidate]);

        SwitchGun(gunCandidate);
    }

编辑:

您还可以稍微清理一下 SwitchGun 方法:

    public void SwitchGun(int gunNumber)
    {
        if (cannotChangeWeapon) return;

        //if (currentGun == gunNumber) return;

        if (gunNumber < 0)
        {
            gunNumber = allGuns.Count - 1;
        }
        else if (gunNumber > allGuns.Count - 1)
        {
            gunNumber = 0;
        }

        if (unlockedGuns[gunNumber])
        {
            activeGun.gameObject.SetActive(false);
            activeGun = allGuns[gunNumber];
            activeGun.gameObject.SetActive(true);
            previousGun = currentGun;
            currentGun = gunNumber;
            UIController.instance.ammoText.text = "AMMO: " + activeGun.ammo;
        }
    }