出现错误“运算符‘+=’对于‘Vector3’和‘Vector2’类型的操作数不明确”

4 c# unity-game-engine

在尝试构建时我收到此错误:

运算符“+=”对于“Vector3”和“Vector2”类型的操作数不明确

这是问题所在的脚本的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move2D : MonoBehaviour
{
    public float moveSpeed = 5f;
    public bool isGrounded = false;

    [SerializeField] private Rigidbody2D rigidbody;

    private void Awake()
    {
        if (!rigidbody) rigidbody = GetComponent<Rigidbody2D>();
    }

    public void Jump()
    {
        if (isGrounded)
        {
            rigidbody.AddForce(new Vector3(0f, 5f), ForceMode2D.Impulse);
        }
    }

    public void Move(float value)
    {
        Vector2 movement = new Vector3(value, 0f, 0f);
        transform.position += movement * Time.deltaTime * moveSpeed;
    }
}

Run Code Online (Sandbox Code Playgroud)

非常感谢任何帮助或信息!

Xen*_*oRo 6

Vector2 具有与 Vector3 之间的隐式转换,但它们并不真正等效,Vector2 仅具有 X 和 Y 分量,而 Vector3 具有 X、Y 和 Z。

当您尝试使用someVector3 += someVector2(或反之亦然)时,+=Vector3 和 Vector2 中的两个运算符都是有效的。

编译器无法确定您要使用哪一个,因此该异常是它告诉您它无法安全地做出决定的方式,您需要为其提供一组明确的类型来使用。这种情况下两边都需要是Vector2或者Vector3;不是混合。

您可以通过两种方式做到这一点:

  1. 从一开始就使用兼容类型,这就是@Ruzihm 在评论中已经指出的
  2. 或者您可以就地转换第二个操作数:transform.position += (Vector3)movement * Time.deltaTime * moveSpeed;

除此之外,我还可以在代码的其他部分看到这两种类型的不健康混合。我强烈建议你保持一致。如果您使用 2D,请使用 Vector2s。

Vector2 有它自己的构造函数。而具有 2 个参数的 Vector3 构造函数仅使 Z 默认为零;它不会创建 Vector2。

它首先起作用的唯一原因是编译器正在使用我上面谈到的隐式转换。然而,这会带来性能成本。

  • rigidbody.AddForce(new Vector2(0f, 5f), ForceMode2D.Impulse);
  • Vector2 movement = new Vector2(value, 0f);(或Vector3movement

我最近才了解到的一个细节是,Unity 仅在 Update 中同步 Transforms,而 Rigidbody(2D 或 3D)的移动仅在 FixUpdate 中同步。当您设置Transform.position刚体对象时,这可能会导致问题。

这就是为什么这么多来源告诉您“在FixedUpdate 中做物理工作”的原因之一。然而,虽然可能会发生其他与遗忘相关的事情Time.deltaTime,但只要变换和刚体不不同步,您就可以position直接设置。您可以通过使用Rigidbody.position而不是 来做到这一点Transform.position

另一个好处是它Rigidbody2D.position是一个 Vector2,完全不需要使用 Vector3 或强制转换该+=操作。

public void Move(float value) {
    var movement = new Vector2(value, 0f);
    rigidbody.position += movement * Time.deltaTime * moveSpeed;
}
Run Code Online (Sandbox Code Playgroud)

最后一件事,尽管它绝对 是过早优化 (尽管不是不好的优化,因为在这种情况下它对可读性的影响为零),但您可以通过在此处执行“向量最后”来保存乘法运算:rigidbody.position += Time.deltaTime * moveSpeed * movement

原因在另一个答案中有解释。