[Havok学习笔记(6)] QUALITY TUTORIAL

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZJU_fish1996/article/details/73330415


        现在我们的角色已经能像我们期待的那样,能随着我们的控制而走动了,但是现在和实际的效果还有一定的差距。

        其中一个差距在于,起始和终止的时动作的质量。如果我们仅让角色移动一点儿,那么角色的步伐会看起来一顿一顿的,或者是在滑动,发生这种情况的原因在于,在行走、停止的状态转移过程中,没有任何限制,我们仅仅是在对应指令下执行相应的操作。所以这一教程中,我们将要做一点设置,使得卡顿的步伐能够和动画制作者的动画匹配。

        另外一个差距在于每次角色停止的时候,总是左腿在前的。这也就意味着有很大可能性出现这样的局面:当人物正在迈右脚向前的时候,使其停止,这时角色会在短时间内变成左脚在前,看起来非常突兀。

        现在我们要做的就是,不应当总是播放左腿在前的停止动画,我们将会介绍一些动画镜像工具来做出正确的变换效果,也就是说,角色开始或者停止的时候,他迈的腿总是正确的那个,这样就能提高它的行为图的质量。

        我们已经有两个脚本,一个在idle状态,另外一个在idle to run的状态。它们的作用是控制一些弹性量的值。在idle状态下,用户移动手柄,当变化达到了一定阈值的时候,我们计算动画的方向,然后立即使得角色开始运动,这时我们从idle状态变化到idle to run状态。

       这时候我们在idle to run的状态下,我们做类似的逻辑判断,区别在于这次我们是松开手柄然后角色停止;这些行为的响应速度很快,但是动画质量并不那么好,因为变换的过程过早地被打断了,所以现在你所得到的结果显得比较笨重。我们所希望的是角色能够完成完整在某一方向上完整的一步动作,而不是立刻就停止了。所以我们需要这两个过程遵循一定的规则。


        我们关注的第一件事情是定时,为了做到这一点,我们选择Idle to Run事件 ,在高级菜单栏中勾选Do Not Interrupt,使之不要被打断,能够完整地播放。

       


扫描二维码关注公众号,回复: 3467421 查看本文章

        此外,对于Idle to Run to Run事件,我们勾选Abut at End of From State,来强制idle to run再返回idle时播放完整。

        


        


        这时候我们演示一下动画,会发现虽然我们勾选了动画播放结束,但是在连贯上依然有些问题,旋转并没有进行到100%。这意味着我们还需要设置一些别的东西。我们点击stop事件(idle to run与idle之间),然后设置Flags为FLAG_IGNORE_TO_WORLD_AND_FROM_MODEL_ROTATION,来排除from/to状态旋转的干扰。我们之所以没有完成完整的旋转动画,是因为from和to两个状态进行了混合运算,由于我们是和没有任何动作的idle状态进行混合计算的,所以我们就丢失了一些旋转的信息。而之所以没有选择FLAG_IGNORE_TO_WORLD_AND_FROM_MODEL,是因为我们仍然希望保留位动作上的插值。

        


        接下来我们要介绍的是动画的镜像。为了做到这一点,我们首先要添加一个变量:

        

        参数设置如上。


        之后,我们在每一帧都去计算这个参数的值,这样它就能精确地指出角色当前的姿态了。现在我们在havok的脚本中加入判断的代码:

	-- called every time the locomotion state is updated
function onLocomotionUpdate()
	
	-- update the gamepad state
	g_gamepadState:update()
	-- update the camera state	
	g_cameraState:update3rdPerson()
	
	-- Compute which foot is forward and store it in a behavior variable
	local leftLegIndex = hkbGetBoneIndex("LeftLegCalf")
	local rightLegIndex = hkbGetBoneIndex("RightLegCalf")
	
	local leftLegModelSpace = hkbGetOldBoneModelSpace(leftLegIndex)
	local rightLegModelSpace = hkbGetOldBoneModelSpace(rightLegIndex)
		
	local leftForward = leftLegModelSpace:getTranslation():dot3(FORWARD_AXIS)
	local rightForward = rightLegModelSpace:getTranslation():dot3(FORWARD_AXIS)
			
	if rightForward > leftForward then		
		hkbSetVariable("IsRightFootForward", 1)		
	else		
		hkbSetVariable("IsRightFootForward", 0)
	end
	
end


      以上代码计算出了左右脚当前在forward方向上的坐标,并根据大小来判断谁在前方,以动态地更新rightForward这个值。

      我们在这一脚本上加上一个选择器:

        


       并将其重命名为Idle Mirror。他所需要做的选择是:左脚在前或者是右脚在前。

      

       进入Idle Mirror,我们双击Generators:

       点击添加新建一个选项:

        


        点击1处的... ,创建一个新的Clip, 选择Idle_0.hkt

        


        双击新的数值进入编辑,将变量重命名为Idle Mirror,并勾选Mirror Animation

        


        这时候我们再来调整选择器,使得IsRightFootForward变量来控制选择器:

        


        同样地,对于run turn 180,我们创建一个选择器,重命名为Run Turn 180 Mirror。

        


       


       为新增的子选择器,勾选single play以及continue事件,并勾选Mirror Animation。和之前一样,我们让IsRightFootForward来控制这一状态。


        不同的是,需要注意一点,我们要把Selected Index Can Change After Activate的选择取消,这样它就不会在每帧都去计算了。

        


        类似地,我们对run这么做:

        


        剩余的操作和前面类似。唯一需要注意的是,我们之前为了匹配上准确的脚的方位,延迟了Start Time,但是在这里我们已经不需要了,因为我们已经判断了当前的正确方向。

猜你喜欢

转载自blog.csdn.net/ZJU_fish1996/article/details/73330415
今日推荐