前言:
本文为跑酷系列的完结篇。前两期传送门:
炫酷跑酷教程(1)——简单的动态地图生成与人物动作
炫酷跑酷教程(2)——多样化的道路生成与简单UI
前2篇文章中主要讲解的是如何搭建地图,文本显示,以及简单的人物控制。本期我们从游戏的细节入手,让角色的动作更多,使之更接近一个商业化游戏的完成度。Let's begin:
动作分析:
通过参照神庙逃亡游戏,我们可以分析出该游戏有一下动作:
1.前跑
2.左右移动
3.左转
4.右转
5.跳跃
6.下滑
其中1,2已经在第一篇文章的时候实现。3,4虽然没有写出来,但是在第二篇文章的时候就已经实装了,这次会重新讲解一下。本篇文章着重实现5,6功能。
动画状态机:
工欲善其事必先利其器。在开始动作功能实现之前,先搭建好我们玩家的的动画状态机。选择我们之前新建好的动画控制器,打开视图,将我们需要使用的动作拖入其中。如图:
在旁边的菜单新建2个BOOL控制开关,并命名为 与.如图:
然后将新建的2个状态应用到动作之上,并去掉Has Exit Time的勾选,如图:
代码实现:
完成上面准备工作后,就可以进行我们的实现环节了。
左转右转功能:
左转右转,就是将玩家自身绕Y轴旋转正或负90度的效果。但是要是在一帧内直接修改完成的话,效果就会很突兀。于是我们使用插件来完成这个功能,于是先引用插件。然后在 .cs文件中写入以下代码:
if (Input.GetKeyDown(KeyCode.J) && isTurnleftEnd) //如果按下J键且左转完成
{
isTurnleftEnd = false; //更新转向状态
transform.Rotate(Vector3.up,-90);
Quaternion tmpQuaternion = transform.rotation; //计算转向后的四元数并保存
transform.Rotate(Vector3.up, 90); //角度回滚
Tween tween = transform.DORotateQuaternion(tmpQuaternion, 0.3f); //使用DoTween插件进行转向的平滑运动
tween.OnComplete(() => isTurnleftEnd = true); //动画结束后转向状态更新
}
通过这段代码,我们实现了在游戏中按下J键人物向自己的方向左转,右转也是同理,这里就不再细说。
跳跃功能:
跳跃功能有以下2部分组成:
1.跳跃动作播放
2.玩家位置升高
首先我们先实现玩家的跳跃动作的播放,我们在函数中写入以下代码:
if (Input.GetKeyDown(KeyCode.Space) && playController.isGrounded)
{
isJumpState = true; //更新跳跃状态
playAnimtor.SetBool("IsJump", true); //播放跳跃动画
}
按下空格,就会看到玩家已经能够播放跳跃这个动作了,但是这还不够,我们还需要将玩家的位置身高才算完成,那么我们这个时候还需要在代码中写入以下代码,才能够实现这个功能。如下:
if (isJumpState) //如果现在正在进行跳跃
{
MoveIncrements.y += jumpPower*Time.deltaTime;//根据设置好的跳跃高度进行平滑运动
}
else
{
MoveIncrements.y += playController.isGrounded ? 0f : -5.0f * Time.deltaTime * 1f; //更新重力
}
playController.Move(MoveIncrements);
可能有同学看不懂这一段,我来解释一下。我们这个游戏里面使用的是.move();函数。这个函数移动是通过调用函数时的参数来进行移动的,它是一个增量的移动函数。如果你在玩家的坐标为(1,1,1)时调用这个函数,并给了一个(1,1,1)参数。那么下一帧,玩家的坐标就会改变为(2,2,2)。我们在代码中更改了的Y值,那么下一帧玩家的坐标就会在前进的基础上,向上运动设置好的Y值,就实现了玩家高度的改变。
下滑功能:
原理与跳跃动画播放相同,只不过不需要进行高度差调整。只需要简单的在代码中写入如下代码就行了。如下:
if (Input.GetKeyDown(KeyCode.K))
{
playAnimtor.SetBool("IsSlide", true);
}
完成后:
动画事件:
经过了以上的步骤,细心的同学会发现我们只对动画的开关进行了打开操作,并没有进行关闭操作。而且我们还去掉了Has Exit Time的勾选,这样就会导致我们在播放一个动画完成后,不能够退出这个动画,出现人物停止的情况。有多种方法可以解决这个问题,例如写一个延时函数,延迟的时间为动画的播放时间,当打开动画播放开关的时候,调用这个函数,这样在动画播放完成后就能够顺利的关闭动画了。但是我们这使用的是不同的方法,我们采用的是给动画添加一个事件,在动画播放到一定进度,就执行这个事件。为了实现这个功能,我们需要先获得运行时动画控制器oller,与当前角色的能够播放的动画数组。如下:
RuntimeAnimatorController nowController; //现在的运行时动画控制器
AnimationClip[] cilps; //播放的动画数组
void Start ()
{
nowController = playAnimtor.runtimeAnimatorController;
cilps = nowController.animationClips;
}
添加成功后,事件的具体实现:
for (int i=0;i<cilps.Length; i++)
{
if (cilps[i].events.Length<=0)
{
switch (cilps[i].name) //通过动画的名字进行设置
{
case "JUMP00": //是跳跃
AnimationEvent endEvent = new AnimationEvent(); //实例化一个动画事件
endEvent.functionName = "JumpEnd"; //事件的方法是“JumpEnd”
endEvent.time = cilps[i].length - (20.0f / 56.0f) * 1.83f; //事件的执行时间(这个可按需求进行调节)
cilps[i].AddEvent(endEvent); //这个跳跃动画添加这个事件
break;
}
}
}
public void JumpEnd()
{
playAnimtor.SetBool("IsJump", false); //动画状态回滚
}
这样完成后,我们就可以在动画播放到设置好的进度时,关闭动画的播放开关,使得游戏人物动作切换更加流畅了。
结语:
经过这3期文章,我们已经实现了一个跑酷小游戏的DEMO,是不是觉得很有趣?要是你看到这还没有完成的话,那就加把劲干吧。本期的工程地址还是上2期的地址,已经进行了更新,有兴趣的同学可以下载试玩一把哦。
好了,末尾老规矩(滑稽),打个广告:想学习游戏开发的同学,欢迎来/围观哦。
评论(0)