How to smooth the animator.SetIKPositionWeight?

Hello there,
i have a c# script that controls the hands of my character. In the specific case, when the player is near a wall (the distance is detected with a raycast), he put his hands on that wall, in the exact point where the raycast happens.
The system works, but i’m trying now to smooth the movement of the hands, so that it looks smoother and more realistic.
Here’s the code:

using UnityEngine;
using System;
using System.Collections;

[RequireComponent(typeof(Animator))]  

public class IKCtrl : MonoBehaviour 

{
	
	public Vector3 IKtarget = Vector3.zero;
	protected Animator animator;
	public bool ikActive = false;

	void Start () 
	{
		animator = GetComponent<Animator>();
	}
	


    //a callback for calculating IK
	void OnAnimatorIK()
	{
	      if(animator) 
		{

             //if the IK is active, set the position and rotation directly to the goal. 
			if(ikActive) 
			{

				animator.SetIKPositionWeight(AvatarIKGoal.LeftHand,1.0f);
				animator.SetIKRotationWeight(AvatarIKGoal.LeftHand,1.0f);
				
				var handRotation = Quaternion.LookRotation(IKtarget - transform.position);
				animator.SetIKRotation(AvatarIKGoal.LeftHand, handRotation);   
				animator.SetIKPosition(AvatarIKGoal.LeftHand,IKtarget);
			}
	}	  
}
}

How can i do that?
Since i’m a newbie, i would really appreciate specific examples.

Thanks for your help!

Matt

Edit:
Now i’m using the following function, with no results:

ikweight = Mathf.Lerp(0.0f, 1f, Time.time);
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand,ikweight);

and

ikweight = Mathf.Lerp(1.0f, 0.0f, Time.time);
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand,ikweight);

The second one seem to work for a while when i start the program. I’m confused :S

Can anyone please show a pratical example? I am new to unity and dont know how to config this curves in my animation. I want to grab a remote control, raise it in TV direction, click and put it back where it was (by my side). I have only one animation that does it all. I can put my hand in the exact place of remote, but it happens too fast with IK on. Can someone explain how this ik smooth works, plaease?

2 Answers

2

No, you don’t need the trick, you can use just Mathf.Lerp

public class TestIK : MonoBehaviour
{
    protected Animator animator;

    public bool ikActive = false;
    public Transform rightHandObj = null;
    public Transform lookObj = null;

    float state = 0;
    float elapsedTime = 0;
    public float timeReaction = 0.5f;

    void Start()
    {
        animator = GetComponent<Animator>();
        state = 0;
    }

    // Update is called once per frame
    void Update()
    {

    }


    //a callback for calculating IK
    void OnAnimatorIK()
    {
        if (animator)
        {

            //if the IK is active, set the position and rotation directly to the goal. 
            if (ikActive)
            {

                // Set the look target position, if one has been assigned
                if (lookObj != null)
                {
                    animator.SetLookAtWeight(1);
                    animator.SetLookAtPosition(lookObj.position);
                }

                // Set the right hand target position and rotation, if one has been assigned
                if (rightHandObj != null)
                {
                    //animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1f);
                    //animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0.5f);

                    if (state < 1.0f)
                    {
                        elapsedTime += Time.deltaTime;
                        state = Mathf.Lerp(0, 1, elapsedTime / timeReaction);
                    }
                    else
                    {
                        state = 1.0f;
                        elapsedTime = 0;
                    }
                    //print("elapsedTime:" + elapsedTime.ToString());
                    //print(state);


                    if (lookObj != null)
                    {
                        animator.SetLookAtWeight(state);
                        animator.SetLookAtPosition(lookObj.position);
                    }



                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, state);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, state);

                    animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);
                }

            }

            //if the IK is not active, set the position and rotation of the hand and head back to the original position
            else
            {
                if (state > 0f)
                {
                    elapsedTime += Time.deltaTime;
                    state = Mathf.Lerp(0, 1, elapsedTime / timeReaction);
                    state = 1 - state;

                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, state);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, state);

                    animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);

                }
                else
                {
                    state = 0;
                    elapsedTime = 0;
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
                    animator.SetLookAtWeight(0);

                }

            }
        }
    }
}

Works as expected. Thank you! Now my vr zombies have a smooth head turn and hand grab with a controllable speed. I will use this for all the IK movements that I turn on and off.

i found the solution to this, it’s a bit tricky.
you must have an animation raising the hand and add a curve to it
then insteat of ikweight = mathf etc.
put

 float reach = anim.GetFloat("AimWeight");
//and then
 anim.SetIKPositionWeight(AvatarIKGoal.RightHand,reach);

this page helped me