【问题标题】:Unity3d: Adding gameobject to List from an arrayUnity3d:将游戏对象从数组添加到列表
【发布时间】:2015-07-15 08:01:04
【问题描述】:

提前感谢您的帮助。这是我遇到问题的代码的简短 sn-p。

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

}

我有一个在开始时创建的游戏对象数组,数组中的每个游戏对象都有一个名为 Pump_event 的脚本。我想要做的是将带有真正布尔值(损坏)的游戏对象添加到列表中,以便我可以创建所有损坏电机的 GUI 列表(然后对这些电机采取进一步措施)。

使用当前代码,它可以很好地实例化数组,但是当其中一个电机布尔值更改为 true 时,列表倾向于在每个更新周期不断地将电机游戏对象添加到列表中。所以我想要的是找出一种将游戏对象添加到列表 ONCE 的方法。

将它放在 update() 中可能不是最好的方法,但我真的被困在如何处理这个问题上。

G


我的问题的解决方案

感谢您的回答,您的回答都经过深思熟虑。我很感激。我没有采用 1 人方法,而是采用了此处找到的逻辑方法来处理我的脚本。

这就是我所做的。 在我的 pump_event 脚本中,事件被分类在一个案例中,并且随着泵上的损坏增加,事件会升级。所以我在该脚本中添加了一个部分,以包括“报告”损坏。

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

这也消除了对包含所有泵事件控制器的阵列的需求。 现在脚本一切正常。它可能不是最有效的,但它正在完成它的工作。

再次感谢所有提供帮助的人。

【问题讨论】:

    标签: c# arrays list unity3d


    【解决方案1】:

    在您的 Pump_event 脚本中,您可以在此 sn-p 中注册一个 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);  
            }
        } 
    }
    

    在您拥有 GameObjects 数组的当前类中:

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

    使用动作是比在更新方法中更好的方法。在更新方法中不断检查迭代中的布尔值对性能不利。并尽量避免更新中的GetComponentFind/FindObjectWithTag 方法。这不是好的做法。我希望这会有所帮助。

    【讨论】:

    • 谢谢,这是对原始问题的正确答案。我已经编辑了我最初的帖子,展示了我是如何解决我自己的问题的,但之后它消除了对数组的需求。您的解决方案也很有效,我确实在我的脚本中进行了检查。
    • 我愿意,但 Stackoverflow 系统说我需要 15 声望才能这样做。 :) 如果可以的话,我会的。 :)
    【解决方案2】:

    根据您发布的代码,问题在于damaged 属性永远不会重置。一种解决方案是在将其添加到列表后重置此属性,如下所示:

        if(motor.GetComponent<Pump_event>().damaged)
        {
            motor.GetComponent<Pump_event>().damaged = false;
            BrokenMotor_list.Add(motor);
        }
    

    但是,如果电机再次损坏,同一对象的多个副本仍可以添加到您的列表中。

    要解决这个问题,您可以使用HashSet。哈希集将只允许一个对象的一个​​副本存在于其中,因此,如果一个对象已经存在,则不会再次添加。

    需要注意的是,您需要覆盖 GameObject 类的 GetHashCodeEquals 方法,因为哈希集将在内部使用这些方法将项目放置在自身内部并识别重复项。

    【讨论】:

    • 您好,我不能将此区域的布尔值更改为损坏 = false,除非电机已修复,该电机位于系统的其他位置。所以我需要一种方法让它在它为假时添加到列表中,但不要在列表中复制自己。
    • @GenGen:在这种情况下,您可以使用HashSet 实现。这将确保您没有 same 对象的多个实例(由GetHashCodeEquals 方法定义)。然后,您可以从修复逻辑中的哈希集中删除该项目,这意味着它可以在将来再次损坏时再次添加。
    【解决方案3】:

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

    if(motor.GetComponent<Pump_event>().damaged)
        {
            if(BrokenMotor_list.Contains(motor))
            { 
               BrokenMotor_list.Add(motor);
            }
        }
    

    虽然在 msdn 上描述了如何实现 IEquatable,以防你想比较不同的对象(具有不同的引用)https://msdn.microsoft.com/ru-ru/library/vstudio/bhkz42b3%28v=vs.100%29.aspx

    【讨论】:

      【解决方案4】:
      if (!BrokenMotor_list.Contains (motor)) {
          BrokenMotor_list.Add (motor);
      }
      

      您最好在损坏事件发生后通过添加委托来执行此操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-11
        • 1970-01-01
        相关资源
        最近更新 更多