【问题标题】:Rigidbody with capsule collider moves on it's own *after* colliding with object带有胶囊对撞机的刚体在*与物体碰撞后自行移动
【发布时间】:2021-05-21 15:46:17
【问题描述】:

首先我会说我对 Unity 和 C# 非常陌生,并且在学习了 Unity 教程系列之后,我正在制作我的第一个个人项目。我开始制作第一人称射击游戏,我让摄像机向下移动,我刚刚编写了一些代码来处理玩家移动和加速。最初在平面上移动时它工作正常,但是一旦我的玩家对象(PlayerColliderParent)碰到我放置在场景中的立方体,它就会开始以恒定的速度和方向自行移动,具体取决于关于它是如何撞到立方体的。除了 PlayerColliderParentScript.cs 之外,没有任何其他脚本可以移动 PlayerColliderParent。

这是出现问题的视频 why is it moving???

这是 PlayerColliderParentScript.cs(附加到 PlayerColliderParent)

using System.Collections.Generic;
using UnityEngine;

public class PlayerColliderParentScript : MonoBehaviour
{
    public Transform cameraRotation;
    public Vector3 directionalInput;
    public float accelerationFactor = 0.1f;
    public float maxSpeed = 6f;
    public Vector3 directionalSpeed;

    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
        //rotate horizontally with camera
        transform.localEulerAngles = new Vector3(0, cameraRotation.localEulerAngles.y, 0);

    }

    void FixedUpdate()
    {
        //accelerate while movement key is held
        //z axis
        if (Input.GetKey(KeyCode.W))
        {
            directionalInput.z = 1;
            if (directionalSpeed.z < maxSpeed)
            {
                directionalSpeed.z += accelerationFactor;
            }
        }
        else if (Input.GetKey(KeyCode.S))
        {
            directionalInput.z = -1;
            if (directionalSpeed.z < maxSpeed)
            {
                directionalSpeed.z += accelerationFactor;
            }
        }
        else if (directionalSpeed.z > 0)
        {
            directionalInput.z = 0;
            directionalSpeed.z -= accelerationFactor;
        }
        else if (directionalSpeed.z < 0)
        {
            directionalInput.z = 0;
            directionalSpeed.z += accelerationFactor;
        }
        else
        {
            directionalInput.z = 0;
        }

        //x axis
        if (Input.GetKey(KeyCode.D))
        {
            directionalInput.x = 1;
            if (directionalSpeed.x < maxSpeed)
            {
                directionalSpeed.x += accelerationFactor;
            }
        }
        else if (Input.GetKey(KeyCode.A))
        {
            directionalInput.x = -1;
            if (directionalSpeed.x < maxSpeed)
            {
                directionalSpeed.x += accelerationFactor;
            }
        }
        else if (directionalSpeed.x > 0)
        {
            directionalInput.x = 0;
            directionalSpeed.x -= accelerationFactor;
        }
        else if (directionalSpeed.x < 0)
        {
            directionalInput.x = 0;
            directionalSpeed.x += accelerationFactor;
        }
        else
        {
            directionalInput.x = 0;
        }

        //move the player according to directional speed
        Vector3 direction = directionalInput.normalized * Time.deltaTime;
        float velocityX = direction.x * directionalSpeed.x;
        float velocityY = direction.y * directionalSpeed.y;
        float velocityZ = direction.z * directionalSpeed.z;
        Vector3 velocity = new Vector3(velocityX, velocityY, velocityZ);
        transform.Translate(velocity);
    }


}


【问题讨论】:

  • PlayerColliderParent 有刚体吗?
  • 如果PlayerColliderParent 确实有一个刚体,它的重力和摩擦设置是什么?
  • @derHugo - 是的,确实如此
  • @DekuDesu 不确定您要使用的重力和摩擦力设置,但它的质量为 1,阻力为 0,角度阻力为 0.05

标签: c# unity3d


【解决方案1】:

确保Rigidbody 具有isKinematic启用。这样您就可以通过transform.TranslateFixedUpdate 中控制它,并且在碰撞检测仍然完好无损时,它不会对任何物理做出反应。


否则,通常只要您有 Rigidbody,您就不想通过 Transform 组件设置值。

我很确定会发生什么,在您已经移动之后,Rigidbody 具有一定的velocity。你永远不会再改变那个速度,所以在碰撞后你有两个,用户输入通过TransformRigidbody自己的velocity应用。

与其使用transform.Translate,不如直接操作Rigidbody.velocity本身。

[SerializeField] Rigidbody _rigidbody;

...

    //accelerate while movement key is held
    //z axis
    if (Input.GetKey(KeyCode.W))
    {
        directionalInput.z = 1;
        directionalSpeed.z += accelerationFactor * Time.deltaTime;
    }
    else if (Input.GetKey(KeyCode.S))
    {
        directionalInput.z = -1;
        directionalSpeed.z -= accelerationFactor * Time.deltaTime;
    }
    else
    {
        directionalInput.z = 0;

        if (directionalSpeed.z > 0)
        {
            directionalSpeed.z -= accelerationFactor * Time.deltaTime;
        }
        else if (directionalSpeed.z < 0)
        {
            directionalSpeed.z += accelerationFactor * Time.deltaTime;
        }
    }

    directionalSpeed.z = Mathf.Clamp(directionalSpeed.z, -maxSpeed, maxSpeed);

    //x axis
    if (Input.GetKey(KeyCode.D))
    {
        directionalInput.x = 1;
        directionalSpeed.x += accelerationFactor * Time.deltaTime;
    }
    else if (Input.GetKey(KeyCode.A))
    {
        directionalInput.x = -1;
        directionalSpeed.x -= accelerationFactor * Time.deltaTime;
    }
    else
    {
        directionalInput.x = 0;

        if (directionalSpeed.x > 0)
        {
            directionalSpeed.x -= accelerationFactor * Time.deltaTime;
        }
        else if (directionalSpeed.x < 0)
        {
            directionalSpeed.x += accelerationFactor * Time.deltaTime;
        }
    }

    directionalSpeed.x = Mathf.Clamp(directionalSpeed.x, -maxSpeed, maxSpeed);

    _rigidbody.velocity = directionalInput;

正如@Rhach 所提到的,轮换也是一个问题。

你可能更应该使用例如

_rigidbody.MoveRotation(new Vector3(0, cameraRotation.localEulerAngles.y, 0));

【讨论】:

  • 这似乎是最有可能出错的事情,所以我不会再回答了。另一件要检查的事情是玩家的轴心点,因为他在 Update 中更改了轮换,没有任何约束或检查。
  • @Rhach 是的,你说得对,这很可能是一个额外的问题!
  • 谢谢,更改为刚体速度有效 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
相关资源
最近更新 更多