C# 为什么我的角色在地板上翻来翻去?

C# 为什么我的角色在地板上翻来翻去?,c#,unity3d,game-physics,C#,Unity3d,Game Physics,我正在编写一个简单的巡逻脚本,一切都正常,但角色在转身时会在地板上随机滚动。这里是他们的一个简短剪辑 这是我的剧本 public class Patrol : MonoBehaviour { public float speed = 5; public float directionChangeInterval = 1; public float maxHeadingChange = 30; public bool useRootMotion; Cha

我正在编写一个简单的巡逻脚本,一切都正常,但角色在转身时会在地板上随机滚动。这里是他们的一个简短剪辑

这是我的剧本

public class Patrol : MonoBehaviour
{
    public float speed = 5;
    public float directionChangeInterval = 1;
    public float maxHeadingChange = 30;
    public bool useRootMotion;

    CharacterController controller;
    float heading;
    Vector3 targetRotation;

    Vector3 forward
    {
        get { return transform.TransformDirection(Vector3.forward); }
    }

    void Awake()
    {
        controller = GetComponent<CharacterController>();

        // Set random initial rotation
        heading = Random.Range(0, 360);
        transform.eulerAngles = new Vector3(0, heading, 0);

        StartCoroutine(NewHeadingRoutine());
    }

    void Update()
    {
        transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, targetRotation, Time.deltaTime * directionChangeInterval);
        if (useRootMotion)
        {
            return;
        }
        else
        {
            controller.SimpleMove(forward * speed);
        }
    }

    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        if (hit.gameObject.tag == "Player")
        {
            // Bounce off the obstacle and change direction
            var newDirection = Vector3.Reflect(forward, hit.normal);
            transform.rotation = Quaternion.FromToRotation(Vector3.forward, newDirection);
            heading = transform.eulerAngles.y;
            NewHeading();
        }
        if (hit.gameObject.tag == "Boundary")
        {
            // Bounce off the obstacle and change direction
            var newDirection = Vector3.Reflect(forward, hit.normal);
            transform.rotation = Quaternion.FromToRotation(Vector3.forward, newDirection);
            heading = transform.eulerAngles.y;
            NewHeading();
        }
    }


    /// Finds a new direction to move towards.
    void NewHeading()
    {
        var floor = transform.eulerAngles.y - maxHeadingChange;
        var ceil = transform.eulerAngles.y + maxHeadingChange;
        heading = Random.Range(floor, ceil);
        targetRotation = new Vector3(0, heading, 0);
    }

    /// Repeatedly calculates a new direction to move towards.
    IEnumerator NewHeadingRoutine()
    {
        while (true)
        {
            NewHeading();
            yield return new WaitForSeconds(directionChangeInterval);
        }
    }
}
公共类巡逻:单一行为
{
公共浮动速度=5;
公共浮点方向更改间隔=1;
公共浮点数maxHeadingChange=30;
公共bool用户ootMotion;
字符控制器;
浮动航向;
矢量3定向;
矢量3前进
{
获取{return transform.TransformDirection(Vector3.forward);}
}
无效唤醒()
{
控制器=GetComponent();
//设置随机初始旋转
航向=随机范围(0,360);
transform.eulerAngles=新矢量3(0,标题,0);
start例程(NewHeadingRoutine());
}
无效更新()
{
transform.eulerAngles=Vector3.Slerp(transform.eulerAngles,targetRotation,Time.deltaTime*directionChangeInterval);
if(useRootMotion)
{
返回;
}
其他的
{
控制器。SimpleMove(前进*速度);
}
}
控件碰撞无效(控件碰撞无效)
{
如果(hit.gameObject.tag==“玩家”)
{
//跳出障碍物并改变方向
var newDirection=Vector3.Reflect(向前、击中、正常);
transform.rotation=四元数.FromToRotation(Vector3.forward,newDirection);
heading=transform.eulerAngles.y;
新标题();
}
如果(hit.gameObject.tag==“边界”)
{
//跳出障碍物并改变方向
var newDirection=Vector3.Reflect(向前、击中、正常);
transform.rotation=四元数.FromToRotation(Vector3.forward,newDirection);
heading=transform.eulerAngles.y;
新标题();
}
}
///找到一个新的前进方向。
void NewHeading()
{
var floor=transform.eulerAngles.y-maxHeadingChange;
var ceil=transform.eulerAngles.y+maxHeadingChange;
标题=随机范围(楼层、天花板);
targetRotation=新矢量3(0,航向,0);
}
///反复计算要向哪个方向移动的新方向。
IEnumerator NewHeadingRoutine()
{
while(true)
{
新标题();
返回新的WaitForSeconds(directionChangeInterval);
}
}
}

我曾尝试在角色中添加刚体并限制旋转,但这不起作用。奇怪的是,角色控件根本没有旋转。在场景视图中,我可以看到角色碰撞器保持其应有的状态,但角色会自行翻转网格。

这似乎是因为他们正走进一个角落,并不断在两堵墙之间反弹,导致他们的行为异常。我将添加一种方法来检查一系列非常快速的碰撞,以检测它们是否在拐角处或被卡住,然后相应地进行调整,也许可以使用一种方法来旋转180度并保持行走或类似的方式

您可以这样做:

float fTime = 0.1f
float fTimer = 0;
int iCollisionCounter;
if(collision){
   if(fTimer > 0) iCollisionCounter++;
   if(iCollisionCounter >= 5) //Character is stuck
   fTimer = fTime;
}
Void Update(){
    fTimer -= time.deltaTime;
}
这意味着,如果在0.1秒内发生多个碰撞,您可以处理它


希望这有帮助

我尝试将其添加到OnColliderHit方法中,但我无法使其抛出调试消息。您是否可以尝试让场景中的一个角色每次与墙碰撞时都抛出调试,以检查它们是否在角落中快速碰撞?