【问题标题】:Is there a way to write a method to call 'AddForce' to either a Rigidbody or a Rigidbody2D parameter?有没有办法编写一个方法来调用“AddForce”到 Rigidbody 或 Rigidbody2D 参数?
【发布时间】:2020-10-29 03:32:21
【问题描述】:

我正在尝试在 Unity 中创建一个适用于 2D 和 3D 刚体的类。一切正常,直到我得到一个 InvalidCastException 的“addForce”方法,因为我要么将 2D 转换为 3D,反之亦然。对于那些不知道的人,Rigidbody 和 Rigidbody2D 都有 'addForce' 方法。

我研究了动态类型(而不是使用,因为它不适用于 ios)、泛型和接口,但仍然无法找到解决方案。将不胜感激任何帮助。谢谢。

public class Scroller : MonoBehaviour {

    ScrollController _scrollController;
    Object _rb;

    public enum SCROLL_MODE {
        TRANSLATION,
        PHYSICS_2D = 2,
        PHYSICS_3D = 3
    }

    public SCROLL_MODE scrollMode = SCROLL_MODE.TRANSLATION;

    // Start is called before the first frame update
    void Start()    {
        _scrollController = ScrollController.Instance;

        switch (scrollMode) {
            case SCROLL_MODE.TRANSLATION:
                break;
            case SCROLL_MODE.PHYSICS_2D:
                _rb = GetComponent<Rigidbody2D>();
                break;
            case SCROLL_MODE.PHYSICS_3D:
                _rb = GetComponent<Rigidbody>();
                break;
        }

        if (!_scrollController)
            logFatalError("Error: There is no ScrollController within the scene.");
    }

    void Update() {
        if (scrollMode == SCROLL_MODE.TRANSLATION)
            transform.Translate(_scrollController.scrollDirection * _scrollController.scrollSpeed * Time.deltaTime);
    }

    void FixedUpdate() {
        if (scrollMode == SCROLL_MODE.PHYSICS_2D || scrollMode == SCROLL_MODE.PHYSICS_3D) {
            if (!_rb) {
                logFatalError("Error: " + gameObject.name + " has no Rigidbody" + scrollMode.ToString("d") + "D");
                return;
            }

            applyScrollForce(_rb);
        }
    }

    void applyScrollForce(Object rb) {
        ((Rigidbody)rb).AddForce(_scrollController.scrollDirection * _scrollController.scrollSpeed * Time.fixedDeltaTime);
    }

    void logFatalError(string msg) {
        Debug.Log(msg);

        enabled = false;
    }
}

【问题讨论】:

  • 回到牛顿定律:F = ma。在两个 2D 中,没有质量。那么如何增加力量呢?在 2D 中,您只需假设质量是常数。因此,当您从 2D 转到 3D 时,您只需使 Z = 0。当从 3D 转到 2D 时,您必须找到重心,这样您就可以给对象一个均匀的质量,并从加速度中移除 Z 元素。

标签: c# unity3d 3d 2d rigid-bodies


【解决方案1】:

泛型无济于事,因为令人惊讶的是,AddForce 没有共同的父类。 Rigidbody 和 Rigidbody2D 都继承自 Component。

我认为您有两种选择:

首先,也是最简单的,仅使用 Rigidbody 并在需要时使用 constraints 将其保持为 2D。

如果这不是一个选项,一个简单的“if”语句就可以了:

void applyScrollForce(Object rb) {
    var force = _scrollController.scrollDirection * _scrollController.scrollSpeed * Time.fixedDeltaTime;
    if(rb.GetType() == typeof(Rigidbody))
        ((Rigidbody)rb).AddForce(force);
    else if(rb.GetType() == typeof(Rigidbody2D))
        ((Rigidbody2D)rb).AddForce(force);
}

当然,您可能希望缓存类型,而不是检查和转换每一帧。

【讨论】:

    【解决方案2】:

    虽然 Rigibody 和 Rigidbody2D 都有 AddForce 方法,但它们不仅签名不同,而且 Rigidbody 和 Rigidbody2D 之间没有任何关系。

    您可以检查 documentation 并看到它们都继承自 Component 类,但这只是它们的相似之处。

    您可以在基本组件上使用switch 命令,以找出您正在处理的两个组件中的哪一个。两个项目的switch 声明有点矫枉过正,但它很简洁,而且对性能没有太大影响。选角也少了很多。

    Component _c = null;
    
    void Start ( )
    {
        _scrollController = ScrollController.Instance;
    
        switch ( scrollMode )
        {
            case SCROLL_MODE.PHYSICS_2D:
                _c = GetComponent<Rigidbody2D> ( );
                break;
            case SCROLL_MODE.PHYSICS_3D:
                _c = GetComponent<Rigidbody> ( );
                break;
        }
    
        if ( !_scrollController )
            logFatalError ( "Error: There is no ScrollController within the scene." );
    }
    
    
    void applyScrollForce ( )
    {
        if ( _c == null )
        {
            Debug.LogWarning ( "The Component is null." );
            return;
        }
    
        var force = _scrollController.scrollDirection * _scrollController.scrollSpeed * Time.fixedDeltaTime;
        switch ( _c )
        {
            case Rigidbody rb:
                rb.AddForce ( force );
                break;
    
            case Rigidbody2D rb2D:
                rb2D.AddForce ( force );
                break;
    
            default:
                Debug.LogError ( $"Component {_c.name} is neither a Rigidbody or Rigidbody2D."  );
                return;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-03
      • 2017-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多