- Home /
stop animation on a single joint?
Is there a way to tell one joint in an animated character to stop? For example, a shoulder (elbow, wrist...) of an arm holding something should stop swinging with the run cycle and just stay out in front of the character. Thanks!
Answer by MaDDoX · Nov 30, 2010 at 08:30 PM
Your best bet there is simply overriding the animation (ie. in LateUpdate) with something to re-aim your arm to a desired target. I've done a half-baked script that allows me to do just that. Of course you'll have to set a way to toggle and untoggle the script for the animations where you don't want the arm re-aiming forward, you can for instance use triggers in animation clips - ctrl+D them if they're imported to make them editable in the animation window. I've tried the script provided in the FPS example (from the Unity3D site) but I found it too tied to their specific setup, so it wouldn't suit me.
Here goes my script, to set it up what I do is simply drag'ndrop an empty gameobject there and move it around interactively in the editor window (while the game's running) plus tweak the "twist" settings until I find the right resulting orientation for the joint (right forearm in my case). Then i write the coordinates down and set it again out of playtime. Kinda of a lame "designer code" solution I know, but it works heh :) If someone can code a more elegant way to do this, please return the favor - even if this was useful just as inspiration - and share k? Good luck!
using UnityEngine;
using System.Collections;
public class AimFix : MonoBehaviour
{
public Transform target;
public Transform joint;
public bool smooth = true;
public float effect = 1; //6
public Vector3 twist = Vector3.zero;
private Vector3 targetPos;
private Quaternion _finalrotation;
void LateUpdate ()
{
if (effect <= 0) return;
if (target)
{
if (smooth)
{ // Look at and dampen the rotation
Vector3 lerpedRotation_e = Vector3.zero;
Quaternion aimRotation_q;
targetPos = target.position;
targetPos.y = joint.position.y;
targetPos.z = -targetPos.z;
aimRotation_q = Quaternion.LookRotation(joint.position - targetPos);
lerpedRotation_e.x = Mathf.Lerp(lerpedRotation_e.x, aimRotation_q.eulerAngles.x, effect * Time.deltaTime);
lerpedRotation_e.y = Mathf.Lerp(lerpedRotation_e.y, aimRotation_q.eulerAngles.y, effect * Time.deltaTime);
lerpedRotation_e.z = Mathf.Lerp(lerpedRotation_e.z, aimRotation_q.eulerAngles.z, effect * Time.deltaTime);
_finalrotation = Quaternion.Euler(lerpedRotation_e.x + twist.x, lerpedRotation_e.y + twist.y, lerpedRotation_e.z + twist.z);
joint.rotation = _finalrotation;
}
else
{ // Just lookat
joint.LookAt(target);
}
}
}
}