Unity notes-29-ARPG game project-04-climbing system optimization and IK animation

Unity notes-29-ARPG game project-04-climbing system optimization and IK animation

IK was not mentioned in the previous article. This article supplements IK animation and some other optimization parts

Why add IK animation

First of all, if there is no IK animation, the action will wear the mold. The distance setting of the code can solve the problem to a certain extent, but it can not completely solve it. Therefore, IK animation is necessary. Secondly, especially when climbing to the top of the wall, without IK animation, the character's hands are usually floating, which is very bad for players, just like floating to the top. Is it strange

Secondly, some optimizations have been made, first about optimization, and then IK

Climbing code optimization

The detection code of climbing the top of the wall in the previous article has been optimized and is no longer detected by the auxiliary coordinates of the top of the head, which is prone to die piercing or floating bugs and is difficult to repair. Therefore, this article will change the way

        lh = ani.GetBoneTransform(HumanBodyBones.LeftHand);
        rh = ani.GetBoneTransform(HumanBodyBones.RightHand);

First, find the left-hand and right-hand Transform components of the character model in Awake through the GetBoneTransform method. We use ray detection through the left-hand and right-hand of the character towards the wall to detect whether there is a wall. If no wall is detected, it means that we can climb the top, otherwise we can't;

    /// <summary>
    ///Climbing wall top detection - optimized version 2.0
    /// </summary>
    public void ClimbUpToLand_2()
    {
        if (!Physics.Linecast(lh.position-transform.forward.normalized*upCheckLength, lh.position + transform.forward.normalized * upCheckLength, environmentLayerMask)|| !Physics.Linecast(rh.position - transform.forward.normalized * upCheckLength, rh.position + transform.forward.normalized * upCheckLength, environmentLayerMask))
        {
            canClimb = false;
            ani.CrossFade(GameConst.CLIMBTOUP_STATE, 0f);
            transform.position += transform.up.normalized * climbUpOffset;
            Invoke("ExitClimb", ani.GetCurrentAnimatorStateInfo(1).length);
        }
    }

However, I use line segment detection here, because in the actual test process, the ray will inexplicably fail to detect the wall, so it is no problem to replace it with line segment.

In this way, it will not lead to the problem of hanging hands when climbing the top.

IK animation settings

The IK settings for climbing involve left and right hands and feet, so you also need to get left and right feet

        lf = ani.GetBoneTransform(HumanBodyBones.LeftFoot);
        rf = ani.GetBoneTransform(HumanBodyBones.RightFoot);

First, write the setting method of IK animation

    public void SetIKPosition(Transform p,AvatarIKGoal goal,float weight,float offset)
    {
        RaycastHit hit;
        if (Physics.Raycast(p.position, transform.forward, out hit, fixedCheckLength, environmentLayerMask))
        {
            ani.SetIKPositionWeight(goal,weight);
            ani.SetIKPosition(goal,hit.point+hit.normal.normalized*offset);
        }
    }

The parameters are: Transform, ikload, weight and offset of the corresponding part

Detect the wall currently climbed by hands and feet through radiographic testing, set the weight, and stick the hands and feet of the characters on the wall through offset debugging at the setting position.

Then call in OnAnimatorIK

    public void OnAnimatorIK(int layerIndex)
    {
        if (ani.GetCurrentAnimatorStateInfo(1).shortNameHash == GameConst.CLIMB_STATE)
        {
            SetIKPosition(lh, AvatarIKGoal.LeftHand,handIKWeight,handIKOffset);
            SetIKPosition(rh, AvatarIKGoal.RightHand,handIKWeight,handIKOffset);
            SetIKPosition(lf, AvatarIKGoal.LeftFoot, footHopIKWeight, footHopIKOffset);
            SetIKPosition(rf, AvatarIKGoal.RightFoot, footHopIKWeight, footHopIKOffset);
        }
        else if (ani.GetCurrentAnimatorStateInfo(1).shortNameHash == GameConst.CLIMBHOP_STATE) 
        {
            SetIKPosition(lh, AvatarIKGoal.LeftHand, handHopIKWeight, handHopIKOffset);
            SetIKPosition(rh, AvatarIKGoal.RightHand, handHopIKWeight, handHopIKOffset);
            SetIKPosition(lf, AvatarIKGoal.LeftFoot, footHopIKWeight, footHopIKOffset);
            SetIKPosition(rf, AvatarIKGoal.RightFoot, footHopIKWeight, footHopIKOffset);
        }
        else
        {
            ResetIKPositionWeight(AvatarIKGoal.LeftHand);
            ResetIKPositionWeight(AvatarIKGoal.RightHand);
            ResetIKPositionWeight(AvatarIKGoal.LeftFoot);
            ResetIKPositionWeight(AvatarIKGoal.RightFoot);
        }
    }

When the animation is playing climbing or jumping, set the IK animation of the left and right hands and feet, and reset the IK animation weight when not climbing

Reset weight

    public void ResetIKPositionWeight(AvatarIKGoal goal)
    {
        ani.SetIKPositionWeight(goal, 0);
    }

Keywords: C# Unity Game Development

Added by glassroof on Tue, 23 Nov 2021 03:06:31 +0200