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);
} 

这也消除了对具有容纳所有泵事件控制器的阵列的需要。现在剧本一切都很好。它可能不是最有效的,但它正在做它的工作。

再次感谢所有的帮助。

Unity3d:将游戏对象从数组添加到列表中

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类的GetHashCodeEquals方法,因为哈希集将在内部使用这些方法来在其内部放置项并识别重复项。

检查列表是否已包含电机。

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);
}

您最好在损坏事件发生后通过添加代理来完成此操作。