Hash是一种由系统根据字符串生成的整形数据,可以方便通过操作hash数字来操作相应的动画状态机的参数、状态机、动画层。
功能说明:通过新建的HashIDs脚本,实现对动画状态控制器Animator中的状态机、过度参数、动画层等映射。
using UnityEngine;
usingSystem.Collections;
publicclassHashIDs : MonoBehaviour
{
publicint dyingState; // 表示Base Layer中Dying状态的hash id
publicint locomotionState;
publicint shoutState;
publicint deadBool;
publicint speedFloat;
publicint sneakingBool;
publicint shoutingBool;
publicint playerInSightBool;
publicint shotFloat;
publicint aimWeightFloat;
publicint angularSpeedFloat;
publicint openBool;
void Awake ()
{
dyingState = Animator.StringToHash("BaseLayer.Dying");
locomotionState = Animator.StringToHash("BaseLayer.Locomotion");
shoutState = Animator.StringToHash("Shouting.Shout");
deadBool = Animator.StringToHash("Dead");
speedFloat = Animator.StringToHash("Speed");
sneakingBool = Animator.StringToHash("Sneaking");
shoutingBool = Animator.StringToHash("Shouting");
playerInSightBool = Animator.StringToHash("PlayerInSight");
shotFloat = Animator.StringToHash("Shot");
aimWeightFloat = Animator.StringToHash("AimWeight");
angularSpeedFloat = Animator.StringToHash("AngularSpeed");
openBool = Animator.StringToHash("Open");
}
}
建立好了参数映射之后,接下来就是在游戏主角player进行控制和设置了,实现通过操作HashIDs中的成员变量间接操作动画控制状态机中的参数值。这里需要给跑步的动画添加声音。若是游戏对象比较多,为方便访问建立标签类tags.cs.
using UnityEngine;
usingSystem.Collections;
publicstaticclassTags
{
publicstaticstring Player = "Player";
publicstaticstring MainLight = "MainLight";
publicstaticstring AlarmLight = "AlarmLight";
publicstaticstring GameController = "GameController";
publicstaticstring Fader = "Fader";
publicstaticstring Enemy = "Enemy";
publicstaticstring Siren = "Siren";
}
using UnityEngine;
usingSystem.Collections;
publicclassPlayerMovement : MonoBehaviour
{
publicAudioClip shoutingClip;
publicfloat turnSmoothing =15f;
publicfloat speedDampTime =0.1f;
privateAnimator animator;
privateHashIDs hash; //应用之前建立的动画参数映射类
voidAwake()
{
animator = GetComponent<Animator>();
hash = GameObject.FindWithTag(Tags.GameController).GetComponent<HashIDs>();
animator.SetLayerWeight(1, 1f); // 设置动画层第一层权重为1,否不会运行
}
voidRotating(float h, float v)
{
Vector3 targetDir = newVector3(h, 0, v);
Quaternion targetRotation = Quaternion.LookRotation(targetDir,Vector3.up);
Rigidbody r = GetComponent<Rigidbody>();
Quaternion newRotation = Quaternion.Lerp(r.rotation,targetRotation,
turnSmoothing * Time.deltaTime);
r.MoveRotation(newRotation);
}
voidMovementManagement(floath, float v, bool sneaking)
{
animator.SetBool(hash.sneakingBool, sneaking);
if(h != 0 || v != 0)
{
Rotating(h, v);
animator.SetFloat(hash.speedFloat, 5.5f,speedDampTime, Time.deltaTime);
}
else
{
animator.SetFloat(hash.speedFloat, 0f);
}
}
voidFixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
bool sneak = Input.GetButton("Sneak");
MovementManagement(h, v, sneak);
}
voidAudioManagement(boolshout)
{
AudioSource audioSource = GetComponent<AudioSource>();
if(animator.GetCurrentAnimatorStateInfo(0).fullPathHash ==hash.locomotionState)
{
if(! audioSource.isPlaying)
audioSource.Play();
}
else
audioSource.Stop();
if(shout)
AudioSource.PlayClipAtPoint(shoutingClip,transform.position);
}
voidUpdate ()
{
bool shout = Input.GetButtonDown("Attract");
animator.SetBool(hash.shoutingBool, shout);
AudioManagement(shout);
}
}
注释:
1. Quaternion.LookRotation
LookRotation 的两个参数,第一个参数 forward,是一个三元组,也就是三个浮点数的组合,这个三元组可以确定世界坐标系下的一个点,从世界坐标系的坐标原点到这个定点就构成了一个三维空间矢量,当我们忽略这个矢量的长度时,它就退化为一个纯粹的方向指示,换句话说,这第一个参数 forward 确定了一个世界坐标系下的方向,而这个方向就是物体转动后 +z 轴所要指向的方向;第二个参数 upwards,也是个三元组,这个三元组同样可以确定一个世界坐标系下的方向,物体转动后 x 轴必须与这个方向垂直(如果转动前物体的x轴不满足此条件,那么物体除了改变朝向外还会绕 z 轴旋转以确保转动结束后 x 轴与此方向垂直)。