【问题标题】:Unity3D: Get Velocity after collisionUnity3D:碰撞后获取速度
【发布时间】:2016-09-23 03:31:22
【问题描述】:

我正在做台球游戏,我有两个问题:

当两个球相互碰撞时,我如何找到它们的速度以及如何将其应用于两个球?

我已经知道它们要移动的角度,我只需要找到它们在这些方向上移动的速度。

我从来不擅长物理/物理编程,所以如果能提供任何帮助,我将不胜感激!顺便说一句,我的游戏是 3D 的。

感谢您的宝贵时间!

编辑:我要做的是使移动方向与我使用此脚本计算的方向相匹配:

if (Physics.Raycast(ray, out hit, Mathf.Infinity, lmm))
{
    location = new Vector3(hit.point.x, 1.64516f, hit.point.z);
}

if (Physics.SphereCast(transform.position, 0.77f, location - transform.position, out hitz, Mathf.Infinity, lmm2))
{
    if (hitz.collider.tag == "Ball")
    {
        Vector3 start = hitz.point;
        end = start + (-hitz.normal * 4);
        lineRenderer2.SetPosition(1, end);
    }

}

【问题讨论】:

  • 您是否正在考虑 3d 中的摩擦、非弹性碰撞、角动量和角速度?我认为您真的应该研究运动学,我想您会喜欢的。如果你想走简单的路,就用这个en.wikipedia.org/wiki/Elastic_collision
  • 嗨,你有什么理由要通过代码控制物理而不是依赖于 Unity 原生物理?这将帮助我理解上下文:基本上你是在使用设置为运动学的刚体吗?
  • 我之所以使用它们,是因为在这种工作方面,Unity 确实存在问题,至少对我而言。到目前为止,我一直在使用原生 Unity 物理,但我决定进行更改以避免错误,但这不是唯一的原因。我希望游戏是基于多人的,所以我想仅在球相互碰撞时使用 RPC 调用(更新运动),而不是每帧都更新它。
  • 另外,我尝试发送单个 rpc 调用来更新母球方向和功率,但结果在其他客户端中不一样(这非常奇怪)。
  • 你应该只在服务器上计算物理,并用刚刚插值的位置更新客户端,这样结果总是一样的。

标签: c# unity3d physics collision velocity


【解决方案1】:

您可以通过对每个球施加一个冲量来计算新的速度。我们可以应用牛顿第三定律来做到这一点。伪代码:

    RelativeVelocity = ball1.velocity - ball2.velocity;
    Normal = ball1.position - ball2.position;
    float dot = relativeVelocity*Normal;
    dot*= ball1.mass + ball2.mass;
    Normal*=dot;
    ball1.velocity += Normal/ball1.mass;
    ball2.velocity -= Normal/ball2.mass;

然而,这并没有考虑两个球之间的摩擦,也没有考虑它们的角动量。

【讨论】:

  • 您好,谢谢您的回答!你认为我应该先停止他们的运动,然后再应用新的速度吗?否则我认为它只会增加它们的速度,因为 Unity 的本机系统在它们相互碰撞时已经增加了速度。
  • 对不起,我忘了你使用的是统一。统一在接触时究竟做了什么。是阻止他们的渗透吗?如果你保持足够低的恢复原状,我很确定统一物理能够模拟这一点。
  • 好吧,在接触时,我认为它会改变它们的速度和角速度。我一回到家就测试你的方法,我现在不在。谢谢!
  • 嘿,刚刚有机会测试您的代码。不幸的是,它给了我与原生统一体的物理系统相同的结果,这真的很奇怪。方向与我预测轨迹时得到的方向不同,我将在主帖中添加脚本。
  • 碰撞看起来不正确吗?也许你的预测是错误的。这个代码和统一的行为是一样的,因为这是牛顿所预测的,一个相等的相反力。我对unity的工作方式不是很熟悉,恐怕我帮不上忙。
【解决方案2】:

如果我理解正确,您要做的是将“A 球”的速度作为“B 球”的力,反之亦然。如果是这样的话,我会建议这样的事情:

将此脚本附加到所有球上:

public class BallCollisionScript : MonoBehaviour 
{   
    public Rigidbody Rigid_Body;

    void Start()
    {
        Rigid_Body = this.GetComponent<Rigidbody>();
    }

    void OnCollisionEnter(Collision collision) 
    {
        if (collision.gameObject.tag.Equals("Ball"))
        {
            BallScript otherBall = collision.gameObject.GetComponent<BallScript>();
            Rigid_Body.AddForce(otherBall.Rigid_Body.velocity);
        }
    }
}

确保所有球都标有“球”。

【讨论】:

  • 您好,谢谢您的回答!你认为我应该先停止他们的运动,然后再应用新的速度吗?否则我认为它只会增加它们的速度,因为 Unity 的本机系统在它们相互碰撞时已经增加了速度。 (从新答案复制粘贴)
  • 你是对的。 Unity 已经为您做到了(我出于某种原因忘记了这一点)。无论如何,您可以尝试两种方式,首先停止它们然后应用速度,或者只是应用它们的速度,然后看看会发生什么。尽管我认为停止他们是正确的方法。
  • 嘿,感谢您抽出宝贵时间,并对延迟回复表示抱歉,我尝试阻止它们,但最终得到了相同的结果。您对我如何解决此问题有任何其他想法吗?顺便说一句,问题已更新。谢谢!
猜你喜欢
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-20
相关资源
最近更新 更多