【问题标题】:What is the cleanest / efficient way to reference a child GameObject? Via grabbing or just searching by name / tag?引用子游戏对象的最干净/有效的方法是什么?通过抓取或仅按名称/标签搜索?
【发布时间】:2019-10-07 18:21:25
【问题描述】:

我一直在考虑在我的脚本中引用对象的子对象的最佳、更简洁和有效的方法。我的意思是,我有一个名为 Player 的 GameObject,它有一把枪。我知道他会一直坚持下去,我需要把它放在一个变量中来做一些事情。我有类似的东西:

myGun.shoot();

我有两种获取 myGun 对象的方法。

第一个:通过公开 myGun 并将其抓取到脚本中。 第二:通过使用 findObjectWithTag 或类似方法搜索参考。

哪一种是最好的方法,为什么?

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    对于常规组件

    就我而言,在这种情况下,最佳实践是创建带有链接的字段。为什么?

    1. 如果您将使用标签 - 在某些时候会创建许多标签,并且在管理它时很容易产生错误
    2. 如果您将使用按名称查找 - 在某个时间点之后,您会发现更新层次结构时遇到的巨大问题。例如,将来您将删除/重命名子项 - 您知道脚本何时会抛出空引用异常。
    3. 如果您使用字段 - 您始终知道每个孩子何时以及如何使用。这也是您在团队中工作时非常好的做法 - 您无需描述团队成员如何与您的代码交互。
    4. 如果您使用字段 - 您可以使用隐藏字段明确控制器,以避免孩子直接绕过控制器编辑(通过使用 [SerializeField] 隐藏指向孩子的链接)。

    对于小型组件

    对于小型组件,按组件查找也是很好的做法。例如,如果您的 UI 计时器由 1 个文本标签和 2-3 个游戏对象构成 - 通过gameobject.GetComponentInChild<Text>(); 更容易找到文本字段。

    对于动态创建的组件

    在这种情况下,更好的方法是创建带有根对象链接的字段,并在运行时管理动态创建的子对象的链接。 例如,创建

    [SerializeField] private GameObject _leftWeaponRoot;
    [SerializeField] private GameObject _rigthtWeaponRoot;
    

    并在运行时将武器添加为子项。

    【讨论】:

    • 好答案,我只是补充一点,在我们的游戏中玩家拥有动态武器,所以当我们创建玩家时,我们实例化对象,将其放置在正确手骨中的“武器持有人”变换下,并将引用存储在类中。 (这里是使用SerializedFieldAttribute 发挥作用的地方)
    猜你喜欢
    • 2011-01-01
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2019-01-21
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多