尝试构建时,我收到此错误:
运算符 '+=' 在类型为 '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具有与 Vector3 之间的隐式转换,但它们并不是真正等价的,Vector2 只有 X 和 Y 分量,而 Vector3 有 X、Y 和 Z。
当您尝试使用someVector3 += someVector2
(反之亦然(时,来自 Vector3 和 Vector2 的+=
运算符都是有效的。
编译器无法确定要使用哪一个,因此例外是它告诉您它无法安全地做出决定的方式,您需要为其提供一组非歧义的类型。在这种情况下,双方都需要是 Vector2 或 Vector3;不是混合。
您可以通过两种方式执行此操作:
- 从一开始就使用兼容类型,这就是 @Ruzihm评论中已经指出了。
- 或者,您可以就地强制转换第二个操作数:
transform.position += (Vector3)movement * Time.deltaTime * moveSpeed;
除此之外,我还可以在代码的其他部分看到这两种类型的不健康混合。我强烈建议你保持一致。如果您使用的是 2D,请使用 Vector2s。
Vector2 有自己的构造函数。而具有 2 个参数的 Vector3 构造函数仅使 Z 默认为零;它不会创建 Vector2。
它首先工作的唯一原因是编译器正在使用我上面谈到的隐式转换。但是,这会产生性能成本。
rigidbody.AddForce(new Vector
2(0f, 5f), ForceMode2D.Impulse);
Vector2 movement = new Vector
2(value, 0f);
(或Vector
3movement
(
我最近才了解到的一个细节是,Unity 只在更新中同步变换,而刚体(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;
}
最后一件事,虽然它绝对是过早优化🤣(虽然不是坏的那种,因为在这种情况下它对可读性的影响为零(,但你可以通过在那里"vector-last"来保存乘法运算:rigidbody.position += Time.deltaTime * moveSpeed * movement
原因在另一个答案中解释。