这只是我觉得目前比较重要且在项目中遇到的知识点
想要更详细了解可以去看看Randy的博客:https://zhuanlan.zhihu.com/p/105029905
还可以去b站搜傅老师学黑魂复刻,也是会学到不少3D动画系统的东西
所遇问题及解决
- 问题:单个方向没有问题,斜着走时速度会达到1.414,也就是根号2
在B站学习傅老师的黑魂复刻教学学到的
float input = Mathf.Sqrt(Dright * Dright + Dup * Dup);
Dmag = input>1.0f?1.0f:input;//控制输入大小
缺点:在未到1.0f前曲线平滑,但在1.0f~1.414突然强制转换为1.0f,导致原本的增速整体变快
椭圆映射法
public Vector2 SquareToCircle(Vector2 input)
{
Vector2 output = Vector2.zero;
output.x = input.x * Mathf.Sqrt(1 - (input.y * input.y) / 2.0f);
output.y = input.y * Mathf.Sqrt(1 - (input.x * input.x) / 2.0f);
return output;
}
- 问题:trigger触发变量快速连续按两下时会累计,然后连续播放两次
在切换动画机的状态添加脚本,使用On Enter和On Exit函数重置trigger
知识点
Animator窗口
Avatar:动画节点导引替身,与动画复用(尤其是人形动画复用)有关,通过配置和应用Avatar,可以实现不同FBX模型之间的动画复用
Apply Root Motion:是否将动画中的根节点位移,植入到Unity中的物体位移上
简单来说就是:是否要让动画师来决定角色的位移
RootMotion模式
-
勾选上时:导入的动画自带位移(动画师先前做动画时设置好的),优点:不会出现滑步现象(即是位移速度和动画不匹配)
-
不勾选上时:不带位移,若无脚本控制则是原地做动作,比如原地走路,优点:可以进行模型的位置修正
-
用OnAnimatorMove来使用脚本控制何时Apply,何时不用,当动画需要某些条件或者修正时
Update Mode:状态机播放动画的时间模式
Normal:使用游戏Upadte的更新模式,一般常用于普通角色动画
Animate Physics:使用物理周期的更新模式,用于角色与物体有物理交互或有物理位移时
Unscaled Time:不受TimeScal影响的更新模式,常用于GUI界面的动画
Culling Mode:剔除模式
Always Animate:无论物体是否被摄像机可见,总是计算所有节点的运动,完整的进行动画播放,常用于主角
Cull Update Transforms:当物体不被摄像机可见时,仅计算根节点的位移植入,保证物体位置上的正确,常用于配角以优化游戏,如GTA的路人
Cull Completely:当物体不被摄像机可见时,完全终止动画的运行,用于消耗性能较高的动画
状态面板
图为动画控制器里状态机的一个状态面板
Motion:这个State所引用的动画片段,Unity中的动画片段,分为两种
-
通过剪辑FBX中的整段动画生成的动画切片(Clip)
-
由Unity提供的Animation窗口创建出的动画片段(Clip)
Speed:控制动画的播放速度,1为正常速度,-1倒着放
可选中用Parameter控制:
-
Multiplier:Speed的一个倍率因子,可用float
-
Normalized Time:片段播放位置,取值0到1之间,可用float获取播放进度
-
Mirror:是否进行左右翻转,可用bool控制
-
Cycle Offset:偏移量,可用float
Foot IK:脚部的IK反向力学修正,如楼梯,上坡,爬梯
优先级
Transitions:从一个状态出发的过渡,存在优先级的顺序,越靠上方的过渡,优先级越大,我们可以通过拖动过渡来排列优先顺序
动画过渡面板
选中任意过渡线Gizmo,会出现如上动画过渡面板
用于调试
-
Solo:勾选时,该State只能进行该过渡,其它过渡将无效
-
Mute:勾选时,这个过渡将无效,当测试某两个动画间的过渡时,可用这个将其中可能过渡到别的动画的过渡线无效化
Settings:对过渡的加强版设置,可调整过渡细节
Interruption Source:打断来源,允许该过渡被来自CurrentState或NextState的其它过渡打断
动作游戏需注意此点掌握
Conditions:过渡条件,可添加多个动画参数,则最终决定于其所有参数交集
中间时间条就是二者过渡时的融合比例,可手动拉拽选择融合比例大小
Has Exit Time
勾选时上一个状态对于的动画片段必须被播放到末尾,才允许这个过渡被触发,不勾选可以在任意时刻进行过渡
如果你发现动画过渡有延迟或者是不流畅时,很大可能就是这个勾选了,但一般是有过度参数才将其选择取消勾选,若无过渡的Parameters参数,则大部分情况是对该过渡速度要求不高,建议勾选上
动画事件的插入
-
通过剪辑FBX中的整段动画生成的动画切片
可以在FBX面板的Events处添加关键帧事件,对着想插入的时间点右键即可,还可选择参数和事件
-
Animation窗口创建出的动画片段
可以在Animation窗口先用白线确定事件插入时间点,再点击插入事件
-
StateMechineBehaviour提供的状态事件脚本
选中任意状态,用Add Behaviour添加即可
每个状态事件脚本都有如下五个接口:
-
OnStateEnter:当进入该状态的过渡被触发时调用
-
OnStateUpdate:进入该状态时循环调用
-
OnStateExit:如果曾进入过该状态,之后进入到其它状态时被调用
-
OnStateMove:相当于Mono脚本中OnAnimatorMove的作用,使用之前提到的RootMotion模式三,但仅针对这个State状态运行时
-
OnStateIK:相当于Mono脚本中的OnAnimatorIK的作用,但仅针对这个State状态运行时
Enter和Exit很适合用于动画开始和结束的音效控制
-
-
通过普通脚本控制动画的进行和过程中的事件触发
脚本中获取动画参数的方法
Parameters动画参数分为四种:float,int,bool,trigger
Trigger的触发必须对当前状态机的运行状态进行判断
int runHash=Animator.StringToHash("Run");//这里的名称要与Animator窗口中,动画参数的名称对应
//通常对于调用频繁的动画参数我们使用哈希值进行快速访问
//下面设置/获取动画参数均有使用String参数名称进行映射的重载和使用哈希值进行映射的重载
//获取设置Float类型参数,通常结合Input轴线
animator.GetFloat(floatHash);
animator.SetFloat(floatHash, Input.GetAxis("Horizontal"));
//获取设置Int类型参数
animator.GetInteger(intHash);
animator.SetInteger(intHash,Number);
//获取设置Bool类型参数
animator.GetBool(boolHash);
animator.SetBool(boolHash, true / false);
//触发,取消触发Trigger的方法
animator.SetTrigger(triggerHash);
animator.ResetTrigger(triggerHash);
AnimatorStateInfo 动画器状态信息
animator.GetCurrentAnimatorStateInfo(layerID);
用来获取一个 AnimatorStateInfo 对象,有关当前或下一个状态zd的动画器信息版。
属性
fullPathHash 该状态的完整路径哈希值,层名+状态名
length 该状态的当前持续长度。
loop 该状态是否循环。
normalizedTime 该状态的归一化时间。
shortNameHash 使用Animator.StringToHash生成的哈希值。传递的字符串不包含父层的名权字。
tagHash 该状态的标签
Animator.StringToHash("Base Layer.Walk");//获得state的fullPathHash
Animator.StringToHash("Walk");//获得state的shortNameHash
Animator.StringToHash("Walking");//获得Parameters变量
如果state和Parameters变量用一个名称"Walk",然后用Animator.StringToHash("Walk")将获得一样的哈希值
如果不用同一名称,然后Animator.StringToHash将获得不同的哈希值