【问题标题】:Vector3.MoveTowards not working with collisions?Vector3.MoveTowards 不能处理碰撞?
【发布时间】:2021-09-17 00:27:18
【问题描述】:

我正在尝试使平面跟随光标平滑移动。

这是执行此操作的代码:

void Update()
    {
        Vector3 mousePos = Input.mousePosition;
        mousePos.z = 0;
        Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);

        mousePos.x = mousePos.x - objectPos.x;
        mousePos.y = mousePos.y - objectPos.y;

        float angle = Mathf.Atan2(mousePos.y, mousePos.x) * Mathf.Rad2Deg;
        transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle + rotationOffset));

        Vector3 targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        targetPos.z = 0;
        transform.position = Vector3.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);

        if (transform.position == targetPos)
        {
            Die();
        }
    }
    public void OnCollisionEnter2D(Collision2D col)
    {
        Debug.Log("hit");
    }

这本身运行良好,但我遇到了一个无法检测到碰撞的问题。我以前从未在运动中使用过Vector3.MoveTowards,但我猜这就是问题所在。如果有人有任何建议,将不胜感激。

【问题讨论】:

  • 您检测到的确切碰撞是什么?您是否依靠“(transform.position == targetPos)”来检查它们是否发生碰撞?
  • @Armin 我检测到的碰撞是与其他 box coliders 的碰撞,(transform.position == targetPos) 在接触光标时正在破坏 obj,targetPos 是鼠标位置。
  • 碰撞对你有用吗?此碰撞中的对象之一是否有RigidBody2D

标签: c# unity3d


【解决方案1】:

关于 Armin 的评论,transform.position==targetPos 几乎永远不会返回 true。这只是因为浮点数和inherent problems with floating point comparison 的大量精度。

一个简单的解决方案是检查距离是否在某个增量范围内。出于性能原因,我建议使用距离的平方。示例:

const float squareCollisionDistance = 4f;//actual collision distance will be 2
var offsetVector = targetPos-transform.position;
var squareDistance = offsetVector.sqrMagnitude;
if (squareDistance < squareCollisionDistance)
    {
        Die();
    }

还有一点需要研究的是刚体,我认为它们有一个你可以听到的碰撞事件。碰撞检测可能是一项非常棘手的工作,因此值得尽可能使用 Unity 的内置功能。

【讨论】:

  • 如果您查看我在他的回答下发表的评论,您会发现我很笨,但编辑了问题。请参考那个
  • 这不是真的...Vector3 == 使用0.00001 的近似精度,因此已经为浮点精度提供了解决方案MoveTowards 确保在某些时候您将达到足够精确的位置
【解决方案2】:

请阅读Colliders -> Collision Action Matrix

  • 至少有一个对象需要有一个Rigidbody2D 组件
  • 两者都需要一个 2D 对撞机。
  • 两者都必须是非触发器

但这还不是全部:一旦您使用物理,您就不想通过Update 中的Transform 移动对象,因为这会超越物理并因此破坏碰撞检测。

宁可使用例如Rigidbody2D.MovePositionRigidbody2D.MoveRotationFixedUpdate

[SerializeField] private Rigidbody2D rigidbody;

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

void FixedUpdate()
{
    var mousePosScreen = Input.mousePosition;
    var objectPosScreen = Camera.main.WorldToScreenPoint(rigidbody.position);

    var delta = mousePosScreen - objectPosScreen;
    var angle = Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg;
    var targetRotation = angle + rotationOffset;

    var mousePosWorld = Camera.main.ScreenToWorldPoint(mousePosScreen);
    var targetPosWorld = Vector2.MoveTowards(rigidbody.position, mousePosWorld, speed * Time.deltaTime);

    rigidbody.MoveRotation(targetRotation);
    rigidbody.MovePosition(targetPosition);

    if (rigidbody.position == targetPosWorld)
    {
        Die();
    }
}

public void OnCollisionEnter2D(Collision2D col)
{
    Debug.Log("hit");
}

【讨论】:

  • 啊我完全忘记考虑更新方法了,好答案!
猜你喜欢
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
相关资源
最近更新 更多