Unity:昂贵的方法调用和 null 比较昂贵 - 解决方案 (RIDER IDE)?

Unity: Expensive Method Invocation AND null comparison expensive - solutions (RIDER IDE)?

我收到 "Expensive Method Invocation" 和 "Null comparison expensive" 警告,我想知道如何解决这些问题。

    void Update()
    {       
        CheckCollision();
    }

在 CheckCollison 中发生错误的地方,如下面的评论所示。

    void CheckCollision()
    {
        var topHit = Physics2D.OverlapCircle(topCollision.position, 0.2f, playerLayer);

        if (topHit != null) // ***<<<< NULL COMPARISON EXPENIVE!***
        {
            if (topHit.gameObject.CompareTag("Player"))
            {
                if (!stunned)
                {
                    var rigidBodyTopHit = topHit.gameObject
                    .GetComponent<Rigidbody2D>();  // ***<<<< EXPENSIVE METHOD INVOCATION!***

                    rigidBodyTopHit.velocity = new Vector2(rigidBodyTopHit.velocity.x, 7f);
                    canMove = false;
                    _myBody.velocity = new Vector2(0,0);
                    _animator.Play("SnailStunned");
                    stunned = true;
                }
            }
        }
        if (!Physics2D.Raycast(downCollision.position, Vector2.down, 0.1f))
        {
            ChangeDirection();
        }
    }

这些不是警告,而是信息亮点。它们旨在通知您,您正在做一些已知代价高昂的事情,在性能敏感的上下文中(Update 方法),您可以在必要时重新评估您的方法.

"if necessary" 位很重要 - 只有您可以决定此 Update 方法的性能特征是否适合您的 game/application。如果这种情况发生在很少使用的选项屏幕中的单个游戏对象中,那么它很可能不是问题。但是如果它在一个被多次实例化并在核心游戏中使用的对象中,可能这些昂贵的方法会加起来并降低性能(或影响电池寿命)。

一般来说,编写没有任何这些信息亮点的代码可能会非常困难(而且没有必要),但是如果您发现您有很多代码有很多亮点,那么这是一个很好的迹象,你应该分析一下,看看你对结果是否满意。

您可以通过使用 Alt+Enter、展开检查选项项并选择 "Why is Rider/ReSharper suggesting this?" 项。这将打开一个网页,其中包含有关该特定亮点的更多详细信息。

This page also has an overview and more details,也可以在 首选项 | 中禁用检查。编辑|检查设置 |检查严重程度 | C# 设置页面(在 Unity | Performance indicators 下)。

查看代码示例中标记的项目,相等比较是昂贵的,因为它还检查底层引擎对象是否已被销毁,这意味着转换为本机代码。如果您知道该对象尚未被销毁(并且看到它是从 Unity API 返回的,我认为这是一个安全的选择),那么您可以将其替换为:

if (!Object.ReferenceEquals(topHit, null)) {
  // … 
}

但请记住,在您的用例中,这是一个可能不必要的微优化。

(用if (!topHit)调用隐式bool运算符与if (topHit != null)both operators call the private Object.CompareBaseObjects method完全一样)

第二项是对 GetComponent 的调用,众所周知,这很昂贵,但在这种情况下是必要的。没关系 - 这只是信息性的,并不是告诉你做错了什么。