2d横版自由射击游戏中的角色头和武器跟随鼠标移动而旋转是如何实现的?

作者:猴与花果山 千猴马的游戏设计之道 2024-05-15
这个做法的核心是分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

最新评论
暂无评论
参与评论

2024 ChinaJoy跑会指南
推广
商务合作 查看更多

编辑推荐 查看更多