Unity’s research on character going uphill

 Previously, we studied building a 3D scene from a 2D perspective.

https://blog.csdn.net/qq_59141650/article/details/131335713

After the construction is completed, you still need to set up the logic for the character to interact with it.

Unity comes with its own Character Controller component (hereinafter referred to as CC), which can easily implement basic movement and climbing. But at present, CC still has many problems, such as the X-axis not decelerating when going uphill, Slope Limit not working on the capsule, loss of accuracy causing isGrounded to jump repeatedly, etc., so I adopted a ray solution to solve these problems.

↑CC uphill demonstration

 In a realistic uphill climb, in addition to the total speed distributed to the Y-axis, additional potential energy against gravity is also required. That is to say, the X-axis has actually experienced two rounds of deceleration, while CC does not decelerate by default, and it would be very inconsistent to apply it directly.

Therefore, ray detection can be added to calculate the slope angle between the next landing point and the current point, and then the X-axis speed can be decomposed into two partial velocities.

            float vx=1;//X轴移动速度,即每帧的位移
            float vy=0;
            float vz=0;
            float pi=3.14159265f;//圆周率,用于计算坡角
            RaycastHit hitInfo;
            int layerMask= 1 <<6;//射线检测的层级,和地形物件一致
            int maxDistance=10;//射线长度,根据需要设置即可
            float newY=y;//移动后新点位的y值
            float xAdd=0,yAdd=0;//重新计算后的位移
            float r=0;
            int slopeLimit=30;//无法走30°以上的坡
            v3=transform.position;
            v3[1]+=5;
            v3[0]+=vx;
            if(Physics.Raycast(v3,Vector3.down,out hitInfo,maxDistance,layerMask))
            {
                newY=hitInfo.point[1];
            }
            if (newY>y+0.001f)
            {
                r = (float)(Mathf.Atan2(newY-y, Mathf.Abs(vx))/(pi/180));
                if (r<slopeLimit)
                {
                    CalcDirection(vx, r, out yAdd, out xAdd);
                    x+=xAdd;
                    y+=Mathf.Abs(yAdd);
                }
            }
            else{
                x += vx;
            }
public void CalcDirection(float num,float r,out float x,out float z)
{
    float pi=3.14159265f;
    x = num*((float)Mathf.Sin(r * (pi/180)));
    z = num*((float)Mathf.Cos(r * (pi/180)));
}

↑The effect after optimization

It can be seen that the combined speed is successfully decomposed into X speed and Y speed, and slopeLimit can also work on the capsule. This step is basically enough, but if instantaneous speed is used, the sense of dissonance will still exist:

At this time, you need to consider the gravitational potential energy. According to the formula mgh=1/2mv2, we know: Δv=√(2gΔh), a certain speed is subtracted after each frame of displacement.

int gravity=10;
float xAdd=0,yAdd=0;
if (r<slopeLimit)
{
    CalcDirection(vx, r, out yAdd, out xAdd);
    x+=xAdd;
    y+=Mathf.Abs(yAdd);
    vx-=(Mathf.Sqrt(2*gravity*yadd));
}

If you want the continuous speed to be affected by this, you can decelerate first and then calculate the displacement (there will be a certain error when using this code)↓

int gravity=10;
float xAdd=0,yAdd=0;
if (r<slopeLimit)
{
    CalcDirection(Mathf.Abs(vx), r, out yAdd, out xAdd);
    if (vx > 0)
    {
        vx-=(Mathf.Sqrt(2*gravity*yadd));
    }
    else if (vx < 0)
    {
        vx+=(Mathf.Sqrt(2*gravity*yadd));
    }
    CalcDirection(vx, r, out yAdd, out xAdd);
    x+=xAdd;
    y+=Mathf.Abs(yAdd);
}

 

Guess you like

Origin blog.csdn.net/qq_59141650/article/details/131341110