- Home /
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 I$$anonymous$$ on. Can someone explain how this ik smooth works, plaease?
You need an animation that raises the hand, doesn't matter if it is precise or not but you'll get better results the closer it is. Then add a new float on the animator, go to the import settings of the animation and add a new curve to it, name the curve exactly as you name the float inside the animator (Important) then add keyframes to the curve, you want towards the end the curve to be 1. Now check my other answer on how to do connect the animator float with the weight of the I$$anonymous$$.
Check this video I made, around the middle it has examples for curves and I$$anonymous$$
https://www.youtube.com/watch?v=T0fA$$anonymous$$FI4oqU
p.s. Everything that has to do with the I$$anonymous$$ system must go inside OnAnimatorI$$anonymous$$()
Answer by OnlyVR · Oct 06, 2016 at 11:09 PM
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.
Answer by nasoukikos · Apr 05, 2014 at 04:38 PM
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 http://docs.unity3d.com/Documentation/ScriptReference/Animator.SetIKPositionWeight.html
Your answer
Follow this Question
Related Questions
Help With Lerping, not larping 2 Answers
Transform.position can't be changed smoothly. 2 Answers
Smooth Camera/Object Movement 1 Answer
Smooth Position Change (Ironsights) 1 Answer