【问题标题】:How to collide two objects without moving either object in Unity如何在 Unity 中碰撞两个对象而不移动任何一个对象
【发布时间】:2021-03-12 16:12:32
【问题描述】:

我的 3D Unity 游戏中有一个类似于 this mockup 的设置。

每个对象都有一个对撞机和一个刚体。我正在使用简单的鼠标输入事件使用鼠标移动对象

private void OnMouseDown()
    {
        isSelected = true;
    }

    private void OnMouseDrag()
    {
        if (!isSelected) return;
        Vector3 touchLocation = InputController.Instance.getTapLocation(); // Gets touch/mouse location using Raycast
        _transform.position = track.GetPositionOnPath(touchLocation); //Uses vector projection math
    }

    private void OnMouseUp()
    {
        if (isSelected)
            isSelected = false;
    }

使用矢量投影将对象移动限制在路径

public Vector3 GetPositionOnPath(Vector3 touchLocation)
    {
        //Make the vector for the track u
        Vector3 u = end.position - start.position;
        //Make the touch location vector from the track start position v
        Vector3 v = touchLocation - start.position;

        float uv = Vector3.Dot(u, v);
        float uMagSqr = Mathf.Pow(u.magnitude, 2);
        Vector3 p = (uv / uMagSqr) * u; //Projection Formula (u.v)/(|u|^2) * u
        Vector3 finalVector = start.position + p;

        //Clamp the final vector to the end.positions of the track
        if (start.position.x > end.position.x)
            finalVector.x = Mathf.Clamp(finalVector.x, end.position.x, start.position.x);
        else
            finalVector.x = Mathf.Clamp(finalVector.x, start.position.x, end.position.x);
        if (start.position.z > end.position.z)
            finalVector.z = Mathf.Clamp(finalVector.z, end.position.z, start.position.z);
        else
            finalVector.z = Mathf.Clamp(finalVector.z, start.position.z, end.position.z);

        return finalVector;
    }

我想以这样一种方式制作它,即其他物体会阻碍所选物体的移动,如模型中所示。我想到的解决方案是增加对象的权重,以便它们在碰撞时不会飞走,或者保持除当前选定对象之外的每个对象运动。但它们都有一个相同的问题,即对象只是相互滑过。

这似乎是一件简单的事情,但我似乎找不到任何资源来帮助我。对于如何解决这个问题并按照我的意图实施机制,我真的很感激。提前致谢。

【问题讨论】:

  • 您可以检查碰撞是否发生碰撞,您可以在rigidbody2d 约束中使用冻结位置。
  • @ArtZolinaIII 嗨。我实际上考虑过这个选项。但即使 RigidBody(我使用的是 3D。我将在问题中对其进行编辑)位置被锁定,我仍然可以将对象移动通过另一个对象,因为它正在被平移。
  • 您可以使用Sweeptest 并在允许移动之前检查您是否撞到东西
  • @derHugo 嗨,这看起来很有希望。这次真是万分感谢。我会试一试。
  • @derHugo 我尝试使用扫描测试。但是由于物体是直接平移的,而且扫描测试必须有一个短距离,这样物体才能尽可能靠近,所以物体移动得如此之快以至于被碰撞的物体永远不会进入范围内是很常见的。扫描测试并开始重叠。

标签: c# unity3d game-engine game-physics game-development


【解决方案1】:

我还没有找到我正在寻找的确切解决方案。但是由于非常不鼓励移动刚体对象的位置,因此我根据在thisthis 线程上找到的信息切换到基于物理的移动。这是我当前的实现:

private void OnMouseDown()
    {
        isSelected = true;
        _rigidbody.isKinematic = false;
    }

    private void OnMouseDrag()
    {
        if (!isSelected) return;
        Vector3 target = InputController.Instance.getTapLocation();
        //_rigidbody.MovePosition(target);
        force = _track.GetPositionOnPath(target) - _transform.position;
    }

    private void OnMouseUp()
    {
        if (!isSelected) return;
        isSelected = false;
        _rigidbody.isKinematic = true;
        force = Vector3.zero;
    }

    private void FixedUpdate()
    {
        _rigidbody.velocity = force;
    }

但是,这样做的代价是移动无法完全响应玩家给出的输入,如 gif 所示。

这是一个修复,因此我将其发布为答案,但非常感谢任何其他更好的选择。

【讨论】:

  • 这个实现似乎反应迟钝。性能还可以,但动作落后于输入相当多。我尝试提高速度,但无济于事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 2018-02-18
  • 2015-04-03
  • 1970-01-01
  • 2015-12-04
  • 2015-07-26
  • 1970-01-01
相关资源
最近更新 更多