Skip to content

Instantly share code, notes, and snippets.

@HilariousCow
Last active January 30, 2017 17:05
Show Gist options
  • Save HilariousCow/c85047a5044eca036607069cf32703a0 to your computer and use it in GitHub Desktop.
Save HilariousCow/c85047a5044eca036607069cf32703a0 to your computer and use it in GitHub Desktop.
Some Animator extensions I use to reduce the clutter involved in setting up a hashed call to an animator parameter
using System;
using UnityEngine;
using System.Collections;
[Serializable]
public class AnimParam
{
private readonly int _hashed;//a cached off version of the hashed string
private readonly string _paramName;//don't really need but good for debug?
private readonly Animator _anim;
private float _floatValue;
public float FloatValue {
get
{
return _anim.GetFloat(_hashed);
}
set
{
SetFloat(value);
}
}
private bool _boolValue;
public bool BoolValue
{
get
{
return _anim.GetBool(_hashed);
}
set
{
SetBool(value);
}
}
private int _intValue;
public int IntValue
{
get
{
return _anim.GetInteger(_hashed);
}
set
{
SetInt(value);
}
}
public string ParamName
{
get { return _paramName; }
}
public int Hashed
{
get { return _hashed; }
}
public AnimParam(Animator animator, string param)
{
if (animator == null) Debug.LogError("Animator is null");
_anim = animator;
_paramName = param;
_hashed = Animator.StringToHash(param);
}
public void SetFloat(float val)
{
_floatValue = val;
if (_anim.isActiveAndEnabled)
{
_anim.SetFloat(Hashed, val);
}
}
public void SetBool(bool val)
{
_boolValue = val;
if (_anim.isActiveAndEnabled)
{
_anim.SetBool(Hashed, val);
}
}
public void SetInt(int val)
{
_intValue = val;
if (_anim.isActiveAndEnabled)
{
_anim.SetInteger(Hashed, val);
}
}
public void SetTrigger()
{
if (_anim.isActiveAndEnabled)
{
_anim.SetTrigger(Hashed);
}
}
public void ResetTrigger()
{
if (_anim.isActiveAndEnabled)
{
_anim.ResetTrigger(Hashed);
}
}
public override string ToString()
{
return _paramName;
}
}
//useful for setting up 3 parameters for each axis of a vector
[Serializable]
public class AnimParam3
{
private readonly int _hashedX;
private readonly int _hashedY;
private readonly int _hashedZ;
private readonly string _paramName;//don't really need but good for debug?
private readonly Animator _anim;
private Vector3 _vectorValue;
public Vector3 VectorValue
{
get { return new Vector3(_anim.GetFloat(_hashedX), _anim.GetFloat(_hashedY), _anim.GetFloat(_hashedZ)); }
set
{
SetVector(value);
}
}
public static string GetXStringForParam(string param) { return param + "X"; }
public static string GetYStringForParam(string param) { return param + "Y"; }
public static string GetZStringForParam(string param) { return param + "Z"; }
public string XString { get { return GetXStringForParam(_paramName); } }
public string YString { get { return GetYStringForParam(_paramName); } }
public string ZString { get { return GetZStringForParam(_paramName); } }
public AnimParam3(Animator animator, string param)
{
if(animator == null) Debug.LogError("Animator is null");
_anim = animator;
_paramName = param;
_hashedX = Animator.StringToHash(XString);
_hashedY = Animator.StringToHash(YString);
_hashedZ = Animator.StringToHash(ZString);
}
public void SetVector(Vector3 vector3)
{
_vectorValue = vector3;
_anim.SetFloat(_hashedX,vector3.x );
_anim.SetFloat(_hashedY,vector3.y );
_anim.SetFloat(_hashedZ,vector3.z );
}
public override string ToString()
{
return _paramName;
}
}
//useful for eulers. currently only dues pitch/yaw since it's common to not want Roll
//also sets the angle magnitude of the pitch/yaw
[Serializable]
public class AnimParamPitchYaw
{
private readonly int _hashedPitch;
private readonly int _hashedYaw;
private readonly int _hashedMagnitude;
private readonly string _paramName;//don't really need but good for debug?
private readonly Animator _anim;
[SerializeField]
private Vector2 _vectorValue;
public Vector2 VectorValue
{
get { return new Vector2(_anim.GetFloat(_hashedPitch), _anim.GetFloat(_hashedYaw)); }
set
{
SetPitchYaw(value);
}
}
public static string GetPitchStringForParam(string param) { return param + "Pitch"; }
public static string GetYawStringForParam(string param) { return param + "Yaw"; }
public static string GetMagnitudeStringForParam(string param) { return param + "Magnitude"; }
public string PitchString { get { return GetPitchStringForParam(_paramName); } }
public string YawString { get { return GetYawStringForParam(_paramName); } }
public string MagnitudeString { get { return GetMagnitudeStringForParam(_paramName); } }
public AnimParamPitchYaw(Animator animator, string param)
{
if (animator == null) Debug.LogError("Animator is null");
_anim = animator;
_paramName = param;
_hashedPitch = Animator.StringToHash(PitchString);
_hashedYaw = Animator.StringToHash(YawString);
_hashedMagnitude = Animator.StringToHash(MagnitudeString);
}
public void SetPitchYaw(float pitch, float yaw)
{
SetPitchYaw(new Vector2(pitch, yaw));
}
public void SetPitchYaw(Vector2 vector2)
{
if (vector2.x > 180f || vector2.y > 180f || vector2.x < -180f || vector2.y < -180f)
{
Debug.LogWarning("Given angle is outside of range -180..+180. Use '.DeltaAngles' to correct the range");
}
_vectorValue = vector2;
_anim.SetFloat(_hashedPitch, vector2.x);
_anim.SetFloat(_hashedYaw, vector2.y);
_anim.SetFloat(_hashedMagnitude, vector2.magnitude);
}
public override string ToString()
{
return _paramName;
}
public void SetPitchYaw(Quaternion rot)
{
//Vector3 deltaEulers = rot.eulerAngles.DeltaAngles();
Vector3 euler = rot.eulerAngles;
Vector3 deltaEulers = new Vector3(Mathf.DeltaAngle(0.0f, euler.x), Mathf.DeltaAngle(0.0f, euler.y), Mathf.DeltaAngle(0.0f, euler.z));
SetPitchYaw(deltaEulers.x, deltaEulers.y);
}
}
public static class AnimatorExtentions {
public static AnimParam AnimParam(this Animator anim, string ParamName)
{
return new AnimParam(anim, ParamName);
}
public static AnimParam3 AnimParam3(this Animator anim, string ParamName)
{
return new AnimParam3(anim, ParamName);
}
public static AnimParamPitchYaw AnimParamPitchYaw(this Animator anim, string ParamName)
{
return new AnimParamPitchYaw(anim, ParamName);
}
public static int GetLayerNumberForName(this Animator anim, string name)
{
int numLayers = anim.layerCount;
for(int i = 0 ; i < numLayers; i++ )
{
if (anim.GetLayerName(i) == name) return i;
}
Debug.Log("Layer name " + name + " not found in animator " + anim.name);
return -1;
}
}
using UnityEngine;
[RequireComponent(typeof(Animator))]
public class AnimatorFeed : MonoBehaviour
{
private Animator _anim;//we need an animator to register our parameters to at runtime.
//Make some parameters to feed the animator with
//NB you need to set up the Parameters that these produce on your AnimatorController, manually.
private AnimParam _speed; //just magnitude
private AnimParam3 _velocity;//velocity relative to this transform
private AnimParamPitchYaw _headAngles;//head angles relative to this transform
private Vector3 _lastPosition;//store the last position we were at so that we can calculate velocity.
private Transform _transform;//good practice to cache off reference to transform (optimisation)
public Transform HeadTransform;//point at a camera or head that the player is controlling or whatever!
void Awake()
{
_anim = GetComponent<Animator>();
//declare our parameters
_speed = _anim.AnimParam("Speed");//create a parameter, and auto store its hash for better performance.
_velocity = _anim.AnimParam3("Velocity");//create a triad of parameters called "VelocityX", "VelocityY", "VelocityZ"
_headAngles = _anim.AnimParamPitchYaw("HeadAngles");//create three parameters called "HeadAnglesPitch", "HeadAnglesYaw" and also "HeadAnglesMagnitude"
_transform = transform;
_lastPosition = _transform.position;
}
void Update()
{
Vector3 deltaPosition = _transform.position - _lastPosition;
_lastPosition = _transform.position;//lest we forget
Vector3 vel = deltaPosition / Time.deltaTime;
//put into local space
vel = _transform.InverseTransformDirection(vel);
_speed.FloatValue = vel.magnitude;//This will update animator parameter "Speed"
_velocity.Vector3Value = vel;//This will update animator parameters "VelocityX", "VelocityY", "VelocityZ" all at once
Quaternion relativeRotation = Quaternion.Inverse(_transform.rotation) * HeadTransform.rotation;
_headAngles.SetPitchYaw(relativeRotation);//you can also use eulers, but everyone thinks you are more of a cleverer nerd if you use quaternions
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment