景安怎么把网站做别名,青岛网站推广公司排名,注册科技有限公司经营范围,网站美食建设图片文章目录 前言实现顶层地面状态四方向混合树计算动画所需参数 空中状态分层动画 前言
最近打算做个Rougelike RPG 塔科夫 混搭风格的冒险游戏。暂且就当是一个有随机元素#xff0c;有基地#xff0c;死亡会掉落物品的近战塔科夫罢。
花了三天时间#xff0c;整合了Mixa… 文章目录 前言实现顶层地面状态四方向混合树计算动画所需参数 空中状态分层动画 前言
最近打算做个Rougelike RPG 塔科夫 混搭风格的冒险游戏。暂且就当是一个有随机元素有基地死亡会掉落物品的近战塔科夫罢。
花了三天时间整合了Mixamo的动画和模型资源通过改动一点Unity自带的第三人称模板的控制器实现移动和动画控制然后自己做了个动画状态机。写这篇主要是记录制作动画状态机时出现的问题状况和解决方案。
当下动画状态机实现了以下特性
基于人物速度的站立到奔跑的混合动画基于人物朝向和速度的四方向混合动画行走和蹲伏基于人物速度的跳跃和坠落的混合动画站立跳跃和奔跑跳跃通过分层动画实现不同的武器装备和攻击动画
我自我认为这个动画状态机写的还算是比较简洁的一开始接触Unity的动画系统第一感觉就是这也不好复制那也不好复制一直在重复赋值缺乏批量操作。现在呢现在也这么觉得。
Unity状态机如果不维护好切换关系和划分层级很快就会连的跟个蜘蛛网一样。我基于之前写过的角色状态机的经验决定将动画状态机和角色状态机分一样的层维护基本一致的转换关系并且条件尽量只和角色自身属性有关尽可能少的通过操作来判断转换条件。
在具体说明这个动画状态机前先看一下Unity官方给的这个ThirdPersonController这东西把所有东西都塞进了一个类中东西全是挺全就是写和扩展肯定是地狱级别的我在添加控制的Animator的参数时需要修改多处代码十分甚至九分的麻烦现在只是原型设计后续肯定会把它重构成状态机结构的。 实现
顶层
先看一下状态机的拓扑图 顶层拓扑图维护了最高层的关系即玩家从地面到空中的转换引起这种变化的原因只有两个
玩家输入Jump操作玩家悬空
而从空中状态返回到地面状态则只有一种原因即玩家落地 地面状态
接下来再看看子状态机GroundState 这一层主要维护所有的地面操作包括正常的四方向混合和蹲下的四方向混合二者之间通过玩家是否按下下蹲操作进行转换。
因为外层的状态机不会在条件满足时自动终止内部的操作因此仍需要重复对二者进行判断是否离开地面或者玩家是否跳跃的条件进行判断进而确定何时离开状态机。
四方向混合树
Idle/Walk/Run看名字就知道是个混合树。其内部长这样 先通过方向混合得到四方向动画再通过速度应用动画。这里只做了向前的奔跑操作是我个人需求。在我的操作方式中玩家默认是会自动朝向移动方向的也是官方示例的默认功能因此不需要其他的奔跑方向。但是我额外添加了一个瞄准操作该操作会使玩家始终面向摄像机方向此时玩家向前方以外的方向移动时速度会被限制无法奔跑因此只需要其他方向的行走动画也不需要其他方向的奔跑动画。
当然四方向的移动效果并不好如果有条件肯定是八个方向会更好因为只有四方向对于斜向移动会导致插值出滑步。
下蹲和这个大同小异由于下蹲时不能奔跑速度恒定因此也无需混合速度这一维数据。
这里再说一下如何获得图上的DirectionX和DirectionY参数。
计算动画所需参数
玩家速度和朝向一致时得到向量{0, 1}相反得到{0, -1}垂直且速度在朝向的右边得到{1, 0}左边则是{-1, 0}。这个是最终得到的输入要求通过这个要求我们就可以得到这样的函数
private Vector2 GetXYDirectionRelativeControllerRotation()
{// 获取玩家控制器的前向方向面向方向Vector2 facingDirection new Vector2(_controller.transform.forward.x, _controller.transform.forward.z);// 获取玩家的速度方向并且进行归一化Vector2 velocityDirection new Vector2(_controller.velocity.normalized.x, _controller.velocity.normalized.z);// 如果速度为零返回 0 或者其他默认值表示没有移动if (velocityDirection.sqrMagnitude 0f){return Vector2.zero; // 玩家没有移动时角度为 0可以自定义}// 计算面向方向和速度方向之间的夹角float angle Vector2.SignedAngle(facingDirection, velocityDirection);Quaternion quaternion Quaternion.Euler(0, 0, angle);return (quaternion * Vector2.up).normalized;
}计算两个向量的夹角再按照两个夹角的角度去旋转一个(0, 1)向量。十分简单也是踩了不少的坑
这里是有问题的通过这个获取的向量变化非常快对于玩家角色而言就是很容易出现角色动画的跳变因此需要在修改参数时额外进行一次插值如下
Vector2 direction GetXYDirectionRelativeControllerRotation();
Vector2 curDirection new Vector2(_animator.GetFloat(_animIDDirectionX), _animator.GetFloat(_animIDDirectionY));
Vector2 smoothDirection Vector2.Lerp(curDirection, direction, 10f * Time.deltaTime);
_animator.SetFloat(_animIDDirectionX, smoothDirection.x);
_animator.SetFloat(_animIDDirectionY, smoothDirection.y);这样就可以获得比较好的方向混合效果了。 空中状态
下面是空中状态的拓扑图 空中拓扑实际上和官方的跳跃流程是差不多的只是有两个比较明显的区别
区别一使用Switch判断是玩家跳跃输入还是玩家悬空导致的进入该状态机区别二除Switch是空节点外其余三个都是基于速度的混合树用于混合从静止跳跃到奔跑跳跃的动画。
这个就比较常规了但是因为涉及到不同动画片段的混合尽量不要使用固定持续时间尽量使用百分比持续时间因为动画长短不一容易导致在一个状态中绕不出去。退出时间也是同理。
分层动画
以上动画都工作在BaseLayer层我的预期是用作下半身移动和空手时的移动操作。
接下来是WeaponLayer层即玩家装备物品时会需要的层
这一层使用了AvatarMask进行蒙版但在使用这玩意儿的时候遇到了个史诗级大坑。Mask的详细面板有两个条目Humanoid和Transform按照官方文档的说法第一个可以大致选定蒙版的区域手啊躯干啊头啊。第二个可以更加细致的调整哪些骨骼会收到影响。
我兴致勃勃的先用Humanoid进行蒙版嗯工作的很好。然后调整Transform让WeaponLayer只能影响到躯干的上半身。结果呢是的完全没有反应。
上网扒拉半天得到的结果是导入的骨骼网格体如果使用Generic则可以使用Transform使用Humanoid则可以使用Humanoid。搞了半天这个Mask的两个选项甚至不能同时用而且和导入的骨骼设置有关。多有意思我只好把骨骼改成Generic才能使用Transform。并且编辑这个Transform时对号还得一个一个自己取消也没个取消父级自动取消子级的。
是的这就是Unity随手一做就能发现一个6年前就有人在问的问题。
总之分层是可以工作了这一层目前还没做多少东西只是导了个武器和待机动作更多东西等做出来过几天再发。