【问题标题】:Getting error "Operator '+=' is ambiguous on operands of type 'Vector3' and 'Vector2'"出现错误“运算符 '+=' 在 'Vector3' 和 'Vector2' 类型的操作数上不明确”
【发布时间】:2019-09-14 16:06:13
【问题描述】:

在尝试构建时出现此错误:

运算符“+=”在“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;
    }
}

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

【问题讨论】:

  • Vector2 movement更改为Vector3 movement

标签: c# unity3d


【解决方案1】:

Vector2 具有与 Vector3 的隐式转换,但它们并不完全等价,Vector2 只有 X 和 Y 分量,而 Vector3 有 X、Y 和 Z。

当您尝试使用 someVector3 += someVector2(或反之亦然)时,来自 Vector3 和 Vector2 的 += 运算符均有效。

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

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

  1. 从一开始就使用兼容类型,which is what @Ruzihm already pointed out in the comments
  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)的移动仅在 FixedUpdate 中同步。当您在刚体对象上设置 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;
}

最后一件事,虽然 肯定 premature-optimization?(虽然不是坏事,因为在这种情况下它对可读性的影响为零),是您可以通过在此处执行“vector-last”来保存乘法运算:rigidbody.position += Time.deltaTime * moveSpeed * movement

原因解释in this other answer

【讨论】:

    猜你喜欢
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 2019-08-27
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    相关资源
    最近更新 更多