Unity3d:将游戏对象从数组添加到列表中
本文关键字:添加 列表 数组 游戏 对象 Unity3d | 更新日期: 2023-09-27 18:02:50
感谢您的帮助。以下是我遇到问题的代码的一小段。
GameObject[] allMotor_array;
public List<GameObject> BrokenMotor_list = new List<GameObject>();
void Start()
{
allMotor_array = GameObject.FindGameObjectsWithTag ("Motors");
}
void Update()
{
foreach (GameObject motor in allMotor_array)
{
if(motor.GetComponent<Pump_event>().damaged)
{
BrokenMotor_list.Add(motor);
}
}
}
我有一个在Start上创建的游戏对象数组,数组中的每个游戏对象都有一个名为Pump_event的脚本。我想做的是将具有真正布尔值(损坏(的游戏对象添加到列表中,这样我就可以创建一个所有损坏电机的GUI列表(然后对这些电机采取进一步的操作(。
在当前代码中,它可以很好地实例化数组,但当其中一个马达布尔值变为true时,列表倾向于在每个更新周期不断将马达游戏对象添加到列表中。所以我想要的是找到一种将游戏对象添加到列表中的方法。
把它放在update((中可能不是最好的方法,但我真的很纠结如何处理它。
G
问题的解决方案
谢谢你的回答,你们都有深思熟虑的回答。我很感激。我没有采用一个人的方法,而是采用了这里的逻辑方法来处理我的脚本。
以下是我所做的。在我的pump_event脚本中,事件在Case中排序,并随着泵上损坏的增加而切换,事件会升级。因此,我在脚本中添加了一个部分,包括"报告"损坏情况。
public class Pump_event : MonoBehaviour
//The damage has taken place and event_category=0''
switch (event_category)
{
case 0:
Master_script.GetComponent<Control_room>().AddtoList (gameObject);
event_category = 1;
break;
我接受了不要插入这些类型的程序的建议,并将其放入单独的类中,效果很好。
public class Master_script: MonoBehaviour
public void AddtoList(GameObject motor_tobadded)
{
BrokenMotor_list.Add(motor_tobadded);
}
这也消除了对具有容纳所有泵事件控制器的阵列的需要。现在剧本一切都很好。它可能不是最有效的,但它正在做它的工作。
再次感谢所有的帮助。
在Pump_event
脚本中,您可以在该代码段中注册一个event Action
,每当damaged
设置为true时,您都需要激发该事件。
示例:
// in Pump_event Class
public static event Action<GameObject> OnDamagedValueChanged;
private bool _damaged;
public bool Damaged
{
get { return _damaged;}
set
{
_damaged = value;
if(_damaged)
{
if(OnDamagedValueChanged != null)
OnDamagedValueChanged(gameObject);
}
}
}
在你的当前类中,你有一组游戏对象:
void OnEnable()
{
Pump_event.OnDamagedValueChanged += HandleOnDamagedValueChanged;
}
void OnDisable()
{
Pump_event.OnDamagedValueChanged -= HandleOnDamagedValueChanged;
}
void HandleOnDamagedValueChanged(GameObject obj)
{
if (!BrokenMotor_list.Contains (obj))
{
BrokenMotor_list.Add (obj);
}
}
使用Actions是比在Update Method中执行操作更好的方法。在更新方法的迭代中不断检查bool对性能不利。并尽量避免使用更新中的CCD_ 4和CCD_。这不是一个好的做法。我希望这会有所帮助。
根据您发布的代码,问题在于damaged
属性从未重置。一种解决方案是,一旦您将该属性添加到列表中,就会重置,如下所示:
if(motor.GetComponent<Pump_event>().damaged)
{
motor.GetComponent<Pump_event>().damaged = false;
BrokenMotor_list.Add(motor);
}
但是,如果电机再次损坏,同一对象的多个副本仍可能添加到您的列表中。
要绕过此问题,可以使用HashSet
。哈希集将只允许对象的一个副本存在于其中,因此,如果对象已经存在,则不会再次添加。
问题是,您将需要覆盖GameObject
类的GetHashCode
和Equals
方法,因为哈希集将在内部使用这些方法来在其内部放置项并识别重复项。
检查列表是否已包含电机。
if(motor.GetComponent<Pump_event>().damaged)
{
if(BrokenMotor_list.Contains(motor))
{
BrokenMotor_list.Add(motor);
}
}
尽管在msdn上描述了如何在需要比较不同对象(具有不同引用(的情况下实现IEquatablehttps://msdn.microsoft.com/ru-ru/library/vstudio/bhkz42b3%28v=vs.100%29.aspx
if (!BrokenMotor_list.Contains (motor)) {
BrokenMotor_list.Add (motor);
}
您最好在损坏事件发生后通过添加代理来完成此操作。