实战贴:斗战神龙女链刃骨骼设置

发表于2015-05-01
评论1 3.1k浏览

本文与大家分享龙女链刃骨骼架设遇到的一些问题和具体架设步骤。

1       架设前需要思考和解决的问题

1.1   链刃的表现效果能否达到策划要求。

对于效果,策划要求尽量接近战神奎爷的链子效果。记得之前有个战神的动画师来这边讲课,当时问了他,战神里链子的实现方式,他说是程序模拟的,具体细节不清楚。我和程序同事沟通了下,感觉完全用程序模拟不太好实现,最后还是决定用骨骼动画来制作。我的思路是把链子的骨骼依附在一个曲线上,然后再使用四个控制器来控制这个曲线的形态。初步架设好给动画同事测试了一下,动画同事感觉还行,基本形态都可以实现。

http://km.oa.com/files/post_photo/405/186405/81cdcdc154d7dbe3307aca977014541d.gif

(当时龙女模型还没有做好,拿的神将的模型做的测试,链子也是临时的)

1.2   手持状态和链刃状态如何切换。

龙女武器有手持和链刃两个状态。手持状态时链子会缩在手里,武器回到手上,跟着手运动。 链刃状态时 武器会脱离手, 手和武器中间有链子链接。为了方便切换这两个状态,我给控制曲线的dummy加了position constraintorientation constraint 控制器,通过调整控制器权重来切换这两个状态。

链刃模式:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image002.gif

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image003.jpg

 

手持模式:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image004.gif

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image005.jpg 

备注:P_Hand_R 是手上的挂点, weaponCtrlR02是链子的控制器。状态切换是通过脚本执行的:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image006.gif

 

1.3   如何降低骨骼数带来的性能开销。

主城里同屏玩家数会很多,如果每个龙女手里都握着几十根骨骼的链子,会影响性能。为了减小这一开销,我们采用手持模式下链子不加载不显示,当使用技能时链子才加载显示出来。导出时,链子也是单独导出成一个模型和一套动画的。

没有加载链刃:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image007.gif

加载链刃:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image008.gif

 

 

2       架设步骤:

2.1   创建曲线

打开0.max 。这个文件里包含龙女的基础骨骼和链子武器模型。首先创建两个曲线匹配链子模型。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image009.gif

选择曲线,把曲线三等分。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image010.gifhttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image011.jpg

最后把曲线顶点类型改成smooth

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image012.jpg

2.2   创建dummy

接上或打开 1.max。接下来个曲线创建几个dummy。具体步骤如下:

给曲线加一个Spline IK Control

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image013.jpg

点击Create Helpers生成dummy

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image014.jpg

修改下link types Helper Size

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image015.jpg

dummy统一命名:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image016.jpg

这样就可以通过移动这些dummy来调整曲线形态了。

2.3   创建依附于曲线的point

接上或打开2.max。接下来就是创建骨骼,并让骨骼依附与曲线了。普通的线性IK可以让骨骼依附与曲线,但是线性IK无法改变链子的长度。我这里变通了一下做法,我创建了一些point,让point平均发布在曲线上,并使用path constraint 控制器让point跟着曲线运动。然后使用这些point去约束骨骼。我们先创建并设置这些point

创建一个point,并把position控制器改为 path constraint

 

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image017.jpg

Add Path 选取右边的曲线。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image018.jpg

删除掉path的关键帧。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image019.jpg

勾上follow,这样point的朝向会沿着曲线的切线。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image020.jpg

一根链子我们使用十根骨骼,所以我们需要十一个point把这个曲线十等分,按住shift 移动point,沿曲线复制这些point,并调整Along Path

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image021.jpg

选择这些point,统一命名

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image022.jpg

2.4   创建链子骨骼

接上或打开3.max。在创建链子骨骼之前我先讲解下如何通过两个point来约束骨骼。

首先创建一段骨骼。然后再创建两个point对齐到骨骼的首尾。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image023.jpg

把骨骼的position控制器设置为position constraint,然后add position target,拾取左边的point

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image024.jpg http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image025.jpg

把骨骼的rotation 控制器设置为 LookAt constraint 然后add lookAt target,拾取右边的point

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image026.jpg http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image027.jpg

这是我们移动两个point看看效果,我们发现我们可以通过两个point控制骨骼的位移和旋转,但是骨骼不会根据两个point的距离来改变缩放,接下来我们就来设置缩放。

把骨骼的Scale 控制器设置为 ScaleXYZ

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image028.jpg

我们只要控制X轴向的缩放,所以我们把ScaleXYZ下的X Scale控制器设置成float script

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image029.jpg

这时会弹出一个窗口,先关闭掉。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image030.jpg

接下来我们需要设置X Scale 的属性,为了方便大家操作,我把左边的point名字改为PointL,右边的改为PointR

执行一句脚本 distance $pointL $pointR 得到 两个point之间的初始距离。记录下这个数字。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image031.jpg

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image032.jpg

然后选择骨骼,右键X Scale 在右键菜单里选择 properties。弹出对话框:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image033.jpg

把下面一段脚本复制把Expression下,最后一个数字36.2616是两个point的距离,替换成之前记录的那个数字。然后点击 Evaluate

dependsOn $PointL $PointR

dis = distance $PointL $PointR

dis/36.2616

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image034.jpg

这时候再移动这两个point 骨骼就会有缩放了:

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image035.jpg

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image036.jpg

 

如果我们要这样手动创建和设置每一根链子骨骼,会花费很长时间。这里我写了一小段脚本辅助创建骨骼。首先选择一边曲线上所有point

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image037.jpg

执行脚本 createRigging.ms 或者直接把这个文件拖入到max窗口。这样一边的链子就创建好了。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image038.jpg

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image039.jpg

最后设置一下骨骼的名字 并把父级设置为手上的虚拟体P_Lianzi_R

2.5   添加操作手柄

接上或打开4.max。接下来为链子添加操作手柄,我们通常在操作手柄上key帧控制链子。

首先创建一个样条曲线,什么形状都可以。 我选择Donut形状。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image040.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image041.jpg

把这个Donut对齐到Help_LianziR01 在复制两个,分别对齐到Help_LianziR02Help_LianziR03。把这三个Donut 名字改为 Ctrl_LianziR01Ctrl_LianziR02Ctrl_LianziR03

 

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image042.jpg

 

选择Help_LianziR00Help_LianziR01Help_LianziR02Help_LianziR03alt + 鼠标右键, 选择Freeze Transform。弹出对话框点“是”。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image043.jpg

 

 Help_LianziR00position list 控制器下的 Available设置为Position ConstraintAdd Position Target 拾取 P_Lianzi_R

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image044.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image045.jpg http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image046.jpg

 

 

Help_LianziR01positionlist控制器下的 Available设置为Position ConstraintAdd Position Target 拾取 P_Lianzi_RCtrl_LianziR01。并把P_Lianzi_R的权重设置为0 Ctrl_LianziR01的权重设置为100Help_LianziR02Help_LianziR03也和Help_LianziR01 做相同设置。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image044.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image045.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image047.jpg

复制Ctrl_LianziR03 把名字改为 Ctrl_LianziR04Ctrl_LianziR04是用来控制前端武器的旋转。把Ctrl_LianziR04对齐到P_Hand_R

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image048.jpg

选择 Ctrl_LianziR01Ctrl_LianziR02Ctrl_LianziR03Ctrl_LianziR04alt + 鼠标右键, 选择Freeze Transform。弹出对话框点“是”。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image043.jpg

 

 

Ctrl_LianziR04position list 控制器下的 Available设置为Position ConstraintAdd Position Target 拾取 Line_PathR10

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image044.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image045.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image049.jpg

 

Ctrl_LianziR04rotation list 控制器下的zero euler xyz设置为orientation ConstraintAdd orientation Target 拾取 P_Lianzi_R,然后在点击add World as target。把P_Lianzi_R的权重设置为0 world的权重设置为100

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image050.jpg http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image051.jpg

然后再把available控制器设置为 Euler xyz,并激活它。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image052.jpg

这是再次把Ctrl_LianziR04 对齐到 P_Hand_R

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image053.jpg

选择P_Hand_Ralt + 鼠标右键, 选择Freeze Transform。弹出对话框点“是”。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image043.jpg

 

选择P_Hand_R ,把P_Hand_Rposition list控制器下的 available设置为Position ConstraintAdd Position Target 拾取 Line_PathR10

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image045.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image049.jpg

 

P_Hand_Rrotation list控制器下的available 设置为Orientation ConstraintAdd Orientation Target 拾取 Ctrl_LianziR04

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image054.jpghttp://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image055.jpg

现在右边的链子已经设置完成。左边进行相同的操作。

6. 接上或打开5.max。接下来分别选择链子模型,添加skin修改器,把骨骼添加到skin修改器,调整点的权重。6.max为最终完成文件。

 

3       辅助脚本工具介绍:

longnvWeapon.ms 拖入到max视窗会弹出一个窗口。

http://avocado.oa.com/fconv/files/201312/584d0d289761618529f3b9bc781e9651.files/image056.jpg

LockToHand 手持状态。

UnLockToHand 链刃状态。

ResetCtrl 把链子缩到手里,方便手持状态和链刃状态见的切换。

selectDummy 选择dummy 可以查看上面的关键帧。

 

4       导出相关

导出时最好先把链子的动画bake成逐帧的, 然后再把哪些曲线,pointdummy ,手柄删除掉。

下面这段脚本就是我们导出时需要执行的。

     fn bakeLianzi =         

     (

         lianziBones = $B_Lianzi* as array

         append lianziBones $P_Hand_L

         append lianziBones $P_Hand_R

         animationData = #()

         for b in lianziBones do

         (

              eachData = #()

              for f = animationrange.start to animationrange.end do

              (

                   tempTransformData = at time f b.transform

                   append eachData tempTransformData

              )

              append animationData eachData

         )

        

         for b =  1 to lianziBones.count do

         (

              lianziBones[b].transform.controller =  PRS()

              lianziBones[b].pos.controller = Position_Expression ()

              lianziBones[b].pos.controller = position_xyz()

              lianziBones[b].rotation.controller = linear_rotation ()

              lianziBones[b].rotation.controller = Euler_xyz()

              lianziBones[b].scale.controller = bezier_scale ()

             

              frameTime = 1

              animate on

              (

                   for f = animationrange.start to animationrange.end do

                   (

                       at time f lianziBones[b].transform = animationData[b][frameTime]

                       frameTime += 1

                   )

             

              )

         )

        

         delete $line*

         delete $Help_Lianzi*

         delete $Ctrl_Lianzi*

     )

bakeLianzi()

 

5       小结

链子的动画最终是有操作手柄间接驱动的。中间还有 dummy,曲线和point。

操作手柄 —> dummy—>曲线—>point—>链子骨骼。

创建的过程中运用了几种常见的控制器,大家最好先熟悉和掌握这几种控制器的使用。在设置过程中保持对物体命名的好习惯,这样方便后面脚本使用。

本来只想简单描述下几个关键的步骤,没想到写的过程中一发不可收拾。但感觉后面有些还是不够详细,如果都展开的内容太多了。大家如果遇到不明白的地方可以看看提供的几个过程文件。最后附送我们实际游戏里用的一些动画资源作参考,希望对大家有所帮助。

大家可下载附件视频看下版本中的效果。附件中还包含max文件和脚本文件。

 

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引