triggers/collides 时定位 GameObjects 属性的最简单方法?

Simplest way to target GameObjects properties when it triggers/collides?

如果我有触发器或碰撞,我想以该 gameObject 为目标并访问它的每个附加脚本的属性。我设法这样做了,但我知道必须有更好的方法,对吗?

在这里,我想将附加到标记为 "BoxManager" 的触发游戏对象的脚本作为目标,然后是 BoxManager 的 属性 "isHeld" 如果在与trigger/collision 我必须使用目标对象,但有没有更好的方法来完成其余的工作?

void OnTriggerStay2D(Collider2D target)
{
    if (target.gameObject.tag == "Box")
    {
        if (target.attachedRigidbody.GetComponent<BoxManager>().isHeld == false)
        {
            target.attachedRigidbody.AddForce(transform.right * thrust);
        }
    }
}

首先,target.attachedRigidbody.GetComponent<BoxManager>()完全没有必要和多余。我见过有人用 target.attachedRigidbody.gameObject.transform.GetComponent<BoxManager>(); 这样的代码做得更糟。这是在做同样的事情,因为它们都附加到一个游戏对象上。

你可以而且应该简单地做到 target.GetComponent<BoxManager>();


至于一直用GetComponent函数在碰撞时获取另一个脚本,那很好。在您可以访问该脚本中的变量之前,获取在碰撞期间附加到游戏对象的另一个脚本是最简单的方法。

尽管如此,我觉得很烦人,因为您必须在 OnTriggerStay2D 中执行 GetComponent。当你有这么多脚本要检查时,它会变得更烦人。

这是你的碰撞函数:

void OnTriggerStay2D(Collider2D target){}

并且您需要在碰撞后从目标访问您的 BoxManager 脚本....

一个棘手的方法是使用 Dictionary。在 Start 函数中初始化 Dictionary 并使用 Collider2D 作为键和 BoxManager 作为值。

在游戏过程中使用 Collider2DBoxManager 实例化和销毁 GameObjects 时更新此字典。

像这样:

Dictionary<Collider2D, BoxManager> scriptID = new Dictionary<Collider2D, BoxManager>();

然后在您的碰撞函数中,使用 TryGetValuetarget 变量作为获取 BoxManager 组件的键。

void OnTriggerStay2D(Collider2D target)
{
    if (target.CompareTag("Box"))
    {
        BoxManager result;
        scriptID.TryGetValue(target, out result);

        if (!result.isHeld)
        {

        }
    }
}

事实上,如果您 %100 确定 该对象附加了 BoxManager 脚本,您可以在一行代码中完成,而无需TryGetValue 函数:

void OnTriggerStay2D(Collider2D target)
{
    if (target.CompareTag("Box"))
    {
        BoxManager result = scriptID[target];
    }
}

您可以像上面那样使用 target.CompareTag 来减少在没有 BoxManager 脚本的情况下检测到对象的机会。请注意我是如何将您的 target.gameObject.tag 更改为 target.CompareTag 的。推荐使用target.CompareTag.

现在代码已经简化为 BoxManager result = scriptID[target];,同时使用target.CompareTag("Box")作为守卫,这样你就不必使用TryGetValueContainsKey 函数。

下面是整个脚本的示例:

Dictionary<Collider2D, BoxManager> scriptID = new Dictionary<Collider2D, BoxManager>();
public BoxManager boxManagerPrefab;

void Start()
{
    //Register your BoxManager instances to the Dictionary
    for (int i = 0; i < 5; i++)
    {
        BoxManager bc = Instantiate(boxManagerPrefab) as BoxManager;
        //Use Isntance ID of the Script as id
        Collider2D cld2D = boxManagerPrefab.GetComponent<Collider2D>();
        scriptID.Add(cld2D, bc);
    }
}

void OnTriggerStay2D(Collider2D target)
{
    if (target.CompareTag("Box"))
    {
        BoxManager result = scriptID[target];

        if (!result.isHeld)
        {
            target.attachedRigidbody.AddForce(transform.right * thrust);
        }
    }
}