这个做法的核心是分clip,并且每个frame下的不同clip组用对应的逻辑去控制,具体的要看项目的美术制作要求的精度,然后来决定切割方法。这里我就用最简单(要求最低)的例子来说这个问题了。
首先是分Clip的概念
无论是传统的序列帧做法还是后来的骨骼动画做法,都会用到这个技术,就是把角色身上的零件切块,然后在每一帧(frame)利用旋转、拉伸、位置(transform)关系来组合到一起,就形成了一帧的动画:
当然上面的图只是一个范例,还是那句话——要做多精致,看项目,比如我们这里举例,就只分上半身和下半身即可。
你可以“偷换”一下概念,更容易理解这个问题
之前我们说的是经典做法,是每一帧为单位,把clip拼到一起,原理上骨骼动画是类似的,只是骨骼动画还会动uv做一些shader的效果,所以相比序列帧,只能说他比较独特,当然这不是这里的重点。
重点是,我们可以把概念反过来理解——每个角色的其实是有若干个部件组成的, 每个部件都有自己的动画和自己的transform,这样理解起来就更unity一些,也更好理解一些。
利用unity的game object关系的性质,我们做出了这样一个类似骨骼动画的分层,原理都是一样的
上面是我现场在用unity做一个例子,只是没有现成动画,所以上半身就用一个方块,下半身就用一个三角来了。这里有几个细节要注意:
最外层的Character只是一个坐标和逻辑载体,所以他除了transform就只有一个character组件来证明(并且管理)他是一个角色,在概念里,他是一个点——也就是玩家看到的角色的脚下中心坐标,当然这个做法是偷懒的,毕竟问题本意是旋转,所以这里就不说关于移动的事情,就偷个懒。
Upper和Lower是空GameObject,他们作为父类吃transform parent的关系,而Part0则是实际贴图,因为这里的范例很简单,所以贴图只有一个,UpperPart0是方块,LowerPart0是三角。值得注意的是,Upper和Lower的坐标:
因为Lower是脚贴地所以是zero了,而Upper的坐标不仅是因为贴图,还因为这是一个上半身转动的点
Upper的坐标其实就是上半身转动的点,也就是问题的关键所在。而里面的贴图,是基于这个点展开的,根据实际美术制作进行:
UpperPart0的位置
另外一说的是weapon,虽然我们的例子中武器没有复杂的玩法,也不会自己转动,但是还是最最最基本的考虑了换武器的需求。weapon同样应该是个空盒子(Prefab的第一层是空的GameObject带一个Weapon的Component),下面都是weapon贴图,比如枪身、枪托、弹匣这样就可以有组枪玩法,当然这也不是这个问题的内容就不多说了。
Character Component
首先是加入Upper和Lower的引用,拿到他们:
这个Character应该负责很多事情,包括管理它的行动、动画之类的,但是在这个问题下,我们就只关心他的跟枪口旋转,所以就只要这么点的东西,然后要做的事情也很简单——
给一个基准点,这个基准点是用来跟鼠标对的,因为我们的坐标在脚下,鼠标位置如果跟脚下得出向量和玩家想法基本不符合,所以我们要用upper的坐标去和鼠标位置对,当然你也可以用枪的位置,但是手感要比用腰部(就是upper坐标,旋转用的点)差一些。有了基准点就可以来控制角色上半身旋转了:
暴露一个UpperPos做基准点,并且实现上半身旋转
值得注意的是,旋转不是[0.000f, 360.000f)度的旋转,因为横版游戏角色上半身“看向”鼠标才是对的,所以会左右转,所以实际上角色的旋转是-90到90度的,也就是代码里的bodyDegree。
旋转不是角色自己定的,而是游戏给的
跟角色移动一样,这不归角色自己管理,而是Scene或者Game层进行管理,所以我们还需要一个Game的脚本,或者你直接GameManager也可以,但是GameManager为了singleton做了特殊处理(核心玩法必须是唯一的吗?同一时间运行多个就不行?这是一个有意思的问题,但不在这里讨论):
仅针对这个问题,所以用更好凑效果的update,而不是自己维护一个输入缓存
可以看到这个问题下要做的事情很简单,先把角色坐标转屏幕坐标,然后鼠标(屏幕坐标)减去角色坐标传递进去就好了。效果么……
凑合看吧,反正自己吧代码贴进去一样的。
一些trick
值得注意的是一些有意思的trick:
武器的发射弹道最好跟“腰”重叠
这其实也是个手感问题,因为对于玩家来说,最直观的是鼠标指哪儿打哪儿,当然并不是说非要100%精准飞向你那里,在玩家心目中是有一条“弹道”的,也就是子弹顺着旋转中心向鼠标飞就对了。
所以,尽可能让“弹道”和“腰”到鼠标这条向量重叠,如果只是平行的话会瞄不准,如果从枪口向着鼠标去,更会出现“歪把子”。
上面代码里的角度可以作为参数用
上面代码里的bodyDegree的写法并不是绝对的,因为我假设的是q版游戏,所以可以这么转,但如果你画风偏写实,多少得有些“IK”对吧?往正上方(其实可以说是一个80-100度的范围)不是旋转的,是换一个动画也是正常的需求,所以它需要的是一个结构,这个结构体包含的是动画贴图,角度,得到这个结构体可以是f(bodyDegree)。
简单地说,就是要灵活运用所有的值,千万别死脑筋什么“只有这些角度,我动画做不了了”,要做动画前,分析一个你驱动动画所需要的数据,把这些数据包装到一个struct,走已有的数据返回即可。
所以
用骨骼动画、序列帧动画都可,关键是怎么切clip,以及美术做动画的时候注意以clip为单位去做动画(也就是这个范例里面upper和lower各做一套),其实简单的理解就是上下半身融合的做法即可。
文/猴与花果山
来源:千猴马的游戏设计之道
原文:https://mp.weixin.qq.com/s/lwIoxBh5sMcn2vWKtvjMIw
|