【问题标题】:Polishing a Character Controller collision detection to make it flush with surfaces抛光角色控制器碰撞检测,使其与表面齐平
【发布时间】:2020-06-29 03:59:06
【问题描述】:

我一直在查看 Source SDK 并阅读了它如何处理玩家与周围空间的碰撞。受此启发,我一直在编写一个应该具有类似行为的角色控制器。

我有代码来控制变换transform,通过计算它的速度vecVelocity 并尝试沿着该向量移动它。我用半径为capsuleRadius 和球心capsuleStart, capsuleEnd 的胶囊来代表玩家,但我还没有给它一个合适的对撞机

在尝试处理碰撞时,我想出了以下函数

void TryPlayerMove()
    {
        Vector3 transDirection;
        float transMagnitude;

        Vector3 translation;
        Vector3 currentMotion = Vector3.zero;
        int i, j, maxHits = 4; //Bump up to 4 times before giving up
        RaycastHit capsule;
        bool collision;

        Vector3[] collNormal = new Vector3[maxHits];
        float collDistance;


        //Find starting translation vector
        translation = vecVelocity * Time.deltaTime;

        //Store initial displacement
        Vector3 oldTranslation = translation;

        for (i = 0; i < maxHits; i++)
        {
            //Find translation vector magnitude and direction
            transDirection = translation.normalized;
            transMagnitude = translation.magnitude;

            //If we wouldn't move anyway, feel free to break the loop
            if (transMagnitude == 0)
            {
                break;
            }

            //Shoot a capsule to desired endpoint
            collision = Physics.CapsuleCast(capsuleStart + currentMotion, capsuleEnd + currentMotion, capsuleRadius, transDirection, out capsule, transMagnitude);

            if (collision)
            {
                //If we hit something, hug it and take off what is left of translation in that direction
                collNormal[i] = capsule.normal.normalized;
                collDistance = capsule.distance;

                //currentMotion += transDirection * collDistance; //WHY DOESN'T THIS WORK???

                translation = ClipVector(translation*(1f-collDistance/transMagnitude), collNormal[i]);

                Debug.Log(transDirection.magnitude);

                //If we're going towards something we've hit before, stop moving so we don't go into weird corner loops
                for (j = 0; j < i; j++)
                {
                    if (Vector3.Dot(translation, collNormal[j]) < 0) 
                    {
                        translation = Vector3.zero;
                        break; 
                    }
                }

            }
            else
            {
                //Just move
                currentMotion += translation;
                break;
            }
        }
        

        //Translate the player character and take note of its velocity for future computation
        vecVelocity = currentMotion / Time.deltaTime;
        transform.Translate(currentMotion, Space.World);
    }

剪裁功能只是确保我们的向量真的没有指向对撞机

Vector3 ClipVector(Vector3 inputVector, Vector3 normalVector)
    {
        float projection;
        Vector3 outputVector;

        //Determine how much to take out
        projection = Vector3.Dot(inputVector, normalVector);

        //Subtract the perpendicular component
        outputVector = inputVector - normalVector * projection;

        //Iterate once more just to make sure
        float adjust = Vector3.Dot(outputVector, normalVector);

        if (adjust < 0f)
        {
            outputVector -= normalVector * adjust;
        }

        return outputVector;
    }

这可以正常工作,并且控件的响应与我预期的一样,但有一个外观错误:每次玩家“碰撞”某物时,它都会停在与物体不同的距离处,我'已经记录了它,它在距离玩家的胶囊半径的 5-10% 左右波动。

TryPlayerMove() 函数中,有一个命令我希望让它拥抱对撞机,它被注释并装饰着绝望的音符

//currentMotion += transDirection * collDistance; //WHY DOESN'T THIS WORK???

每当我取消注释时,控制器总是会通过它接触到的任何对撞机,并完全打乱它应该具有的任何运动。不过,我不知道为什么会这样。

我如何为我的玩家实现一个功能来拥抱它所接触的碰撞器,看到这似乎根本不起作用?

【问题讨论】:

    标签: c# unity3d collision-detection linear-algebra


    【解决方案1】:

    我突然发现了一个 hacky 修复。我有一个float deltaGround我用来检查地面。我将命令更改为

    currentMotion += transDirection * (collDistance-deltaGround/20f);

    但 20 可能是任何合理大小的数字。这使它更加一致,但当我尝试将自己撞到墙上时,会在玩家动作中引入一些抖动。仍在接受更多建议。

    顺便说一句,我试过Mathf.Epsilon,但它没有解决任何问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多