我目前正在为FPS编写一个武器脚本,我想用鼠标轮切换武器。我创建了一个包含武器的数组,每次我用鼠标滚动时,武器的索引就会增加1。我的问题是,当我到达最后一个武器时,我会得到IndexOutOfBounds错误消息。如果它位于数组的末尾,我尝试将武器索引重置为0,但由于某种原因,它不起作用。我也尝试用while循环,而不是if-语句来完成它,但这也不起作用。下面是代码:
public class WeaponManager : MonoBehaviour
{
[SerializeField]
private WeaponHandler[] weapons;
private int current_weapon_index;
void Start()
{
current_weapon_index = 0;
weapons[current_weapon_index].gameObject.SetActive(true);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
TurnOnSelectedWeapon(0);
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
TurnOnSelectedWeapon(1);
}
if (Input.GetKeyDown(KeyCode.Alpha3))
{
TurnOnSelectedWeapon(2);
}
if (Input.GetKeyDown(KeyCode.Alpha4))
{
TurnOnSelectedWeapon(3);
}
if (Input.GetKeyDown(KeyCode.Alpha5))
{
TurnOnSelectedWeapon(4);
}
if (Input.GetKeyDown(KeyCode.Alpha6))
{
TurnOnSelectedWeapon(5);
}
if(Input.mouseScrollDelta.y > 0)
{
SwitchToNextWeapon();
}
if (Input.mouseScrollDelta.y < 0)
{
SwitchToPreviousWeapon();
}
}
void TurnOnSelectedWeapon(int weaponIndex)
{
weapons[current_weapon_index].gameObject.SetActive(false);
weapons[weaponIndex].gameObject.SetActive(true);
current_weapon_index = weaponIndex;
}
void SwitchToNextWeapon()
{
weapons[current_weapon_index].gameObject.SetActive(false);
current_weapon_index++;
weapons[current_weapon_index].gameObject.SetActive(true);
if (current_weapon_index >= weapons.Length)
{
current_weapon_index = 0;
}
}
void SwitchToPreviousWeapon()
{
weapons[current_weapon_index].gameObject.SetActive(false);
current_weapon_index--;
weapons[current_weapon_index].gameObject.SetActive(true);
}
}
发布于 2021-08-31 12:40:45
实现一个为您处理这个问题的类非常简单,只需维护一个内部的List<>
项。添加Current
属性以读取当前选定的项,以及从鼠标轮处理程序中调用的MoveNext
/MovePrevious
方法
public class ContinuousList<T>
{
private List<T> internalList = new List<T>();
private int currentIndex = 0;
public void Add(T item) => internalList.Add(item);
public T Current { get => internalList[currentIndex]; }
public void MoveNext()
{
currentIndex++;
if(currentIndex >= internalList.Count) currentIndex = 0;
}
public void MovePrevious()
{
currentIndex--;
if(currentIndex <= 0) currentIndex = internalList.Count - 1;
}
}
假设您可能有一些具有基类Weapon
的武器
var weaponList = new ContinuousList<Weapon>();
weaponList.Add(new Sword());
weaponList.Add(new Axe());
var currentWeapon = weaponList.Current; // gets Sword
weaponList.MoveNext();
var currentWeapon = weaponList.Current; // gets Axe
weaponList.MoveNext();
var currentWeapon = weaponList.Current; // Back to Sword
实例:https://dotnetfiddle.net/Ji7rkt
请注意,在这个IEnumerable<T>
上实现ContinuousList
非常容易,这样就可以在任何枚举和LINQ方法中使用它。我不想让一个简单的例子变得复杂,但是我想在这里查看一下:https://dotnetfiddle.net/NtdfDi
发布于 2021-08-31 12:45:45
void SwitchToNextWeapon()
{
weapons[current_weapon_index].gameObject.SetActive(false);
var temp = current_weapon_index + 1;
current_weapon_index = temp >= weapons.Count() ? 0 : temp;
weapons[current_weapon_index].gameObject.SetActive(true);
}
void SwitchToPreviousWeapon()
{
weapons[current_weapon_index].gameObject.SetActive(false);
var temp = current_weapon_index - 1;
current_weapon_index = temp < 0 ? weapons.Count() - 1 : temp;
weapons[current_weapon_index].gameObject.SetActive(true);
}
只需在增加或减少当前武器索引之前添加检查即可。如果达到最大值,则恢复为0,如果达到min (0
),则将索引设置为最大值。
发布于 2021-08-31 13:36:49
使用模(%
)运算符很容易地处理循环值。
int mod = 5;
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i % mod);
}
您将看到输出周期从0到mod-1
:0,1,2,3,4,0,1,2,.
这涵盖了递增一次的情况:
int index = 4;
int mod = myArray.Length; // assume 5 items in the array
// Increment and cycle
index = ++index % mod;
您将看到这个索引现在是0
,因为您在列表的末尾,所以下一个项应该在列表的开头。
然而,周期性价值的下降也存在一些问题。出于一个我不明白的原因,C#选择了允许负模值,即:
-1 % 5 = -1
..。而不是4
,这正是您所期望的。
编辑:评论中认为,4
并不是每个人都期望的那样。从我第一次处理这个问题时的经验来看,我在网上发现了很多关于负面模块化结果的困惑/烦恼,但我不能否认这是我的观察偏见。
我过去曾处理过这个问题,解决这个问题的最简单方法是:
本质上,--如果第一步的结果是负值(例如-1
),我们只需添加模块,从而将值推到零以上。然而,如果第一步已经是一个积极的结果,我们现在已经让这个值太高了。因此,通过再次采取模块化,我们可以抵消潜在的太高的价值。这涵盖了这两种情况。
换言之:
public int Increment(int current, int mod)
{
return ((++current % mod) + mod) % mod;
}
public int Decrement(int current, int mod)
{
return ((--current % mod) + mod) % mod;
}
为了干燥,你可以重塑它,所以你只使用这个复杂的公式一次。
public int Cycle(int current, int mod)
{
return ((current % mod) + mod) % mod;
}
..。但是,您必须首先手动地输入/减少值。你喜欢哪个版本取决于你自己。
https://stackoverflow.com/questions/68998738
复制相似问题