使用Unity制作3D无尽跑酷游戏(下)
发表于2017-04-25
此前为大家分享了使用Unity创建3D无尽跑酷游戏的上半部分,今天这篇文章将继续分享下半部分。 下载示例工程: littlehill,如果您要查看本帖隐藏内容请回复 关卡 本文将讲解如何构建关卡。先从“直线型道路”关卡开始。 Straight Paths Level 层级结构列表中的游戏对象: Straight Paths Level中游戏对象的层级结构 所有的路径都是通过预制件(见上图蓝色的WideStraightPath)来复制的,直线型道路的路径要比旋转型道路更宽。场景中还有一些立方体状的3D对象(上图中的Cubes),作为路径的地板。另外还有一些简单的3D坐标,NewPathSpawn以及SpawnPoints。SpawnPoints用于指定生成新物体的位置,例如糖果、障碍物等。 为了节省内存资源,游戏不会在一开始就生成所有路径。实际上,游戏需要生成N+1条路径,N是当前Max所在的路径位置。可以利用一个简单的碰撞器BoxCollider,当Max与它发生碰撞, 则通过PathSpawnCollider脚本生成新路径。在直线型道路的关卡中,新生成的路径位于“NewPathSpawn”坐标,这个坐标就是当前路径的终点。 当玩家与PathSpawnCollider发生碰撞时,在NewPathSpawn位置生成新路径 NewPathSpawn的位置就是新路径的生成点 Character游戏对象下包含相机和Max模型,此外还有Character Controller 组件和CharacterSidewaysMovement脚本。通过该组件和脚本的控制,相机会始终保持在Max上方的位置,这是第三人称视角游戏中的常见角色控制方式。 Canvas包含两个文本对象。Directional Light就是很简单的平行光光照,ScriptHolder对象包含了本教程上半部分介绍的GameManager单例脚本。 PathSpawnCollider类——路径生成器 此脚本适用于两种关卡,主要功能是根据Max当前奔跑位置来生成下一段路径。 [C#] 纯文本查看 复制代码
脚本首先设置了几个公共变量,可以在Unity编辑器中设置。
[C#] 纯文本查看 复制代码
当Max与PathSpawnCollider对象碰撞时,游戏会随机决定下一段路径是往左、往右还是笔直前行。在“直线型道路”关卡中,PathSpawnPoints数组只需一个路径对象(对应直行位置),将randomSpawnPoint参数设置成0,则会笔直生成下一段路径。在“旋转型道路”关卡中,在选定位置生成下一段路径,并在另外2个位置生成RedBorder障碍物,将其旋转90度以正确摆放。 Stuff Spawner类——道具生成器 Stuff Spawner脚本用于生成糖果、障碍物等游戏道具,两个关卡均有用到。首先声明一些可以在Unity编辑器中设置的公共变量。 [C#] 纯文本查看 复制代码
[C#] 纯文本查看 复制代码
CreateObject方法用于在选定位置实例化一个新的预制件,并且判定是否要沿X轴方向移动一段距离(仅“直线型道路”关卡)。 [C#] 纯文本查看 复制代码
Start方法 决定是否在当前路径创建障碍物(50%概率)。如果判定通过,它将随机选取一个障碍物预制件并创建。 StuffSpawnPoints数组中的其它位置(即非obstacleIndex的位置),会决定是否创建糖果(33%的概率)。如果判定通过,它会随机在Bonus数组中选取一个预制件并创建。 CharacterSidewaysMovement类——角色横向移动控制类 该脚本仅用于在“直线型道路”关卡中移动Max。Max带有CharacterController组件。如果想了解如何对带有CharacterController组件的游戏对象进行移动控制,请查阅Unity文档。 [C#] 纯文本查看 复制代码
声明一些变量,通过其名称就能很容易了解它们的用途。 [C#] 纯文本查看 复制代码
在Start中设置moveDirection向量,用于帮助Max以给定的速度直线前进。然后为组件的相关变量设置正确的值,并更改游戏状态以开始游戏。 [C#] 纯文本查看 复制代码
因为Max是可以进行跳跃操作的,所以很有可能造成人物跳跃出路径之外。CheckHeight方法检测Max是否掉落到平台的高度之下,如果是,则游戏失败。 [C#] 纯文本查看 复制代码
DetectJumpOrSwipeLeftRight方法首先检测玩家是否转向或跳跃(即是否按左、右或者上方向键)。如果游戏已经检测到玩家按上方向键,则再检测当前Max是否正在落地或切换路径(这里禁止2次跳跃)。在通过了这些检测之后,再设置moveDirection向量的y值,并播放Max的跳跃动画。 [C#] 纯文本查看 复制代码
然后,检测玩家是否左右滑动。如果Max当前不是跳跃状态,也未移动至道路边缘,则检测到左或右方向键输入后,让Max向左或右移动。接着,通过为moveDirection向量的x值加或减SideWaysSpeed变量值,来实现以上操作。在路径切换完成的同时,保存Max的最后位置。 接下来看看Update。这里通过switch语句处理3种不同的游戏状态。 [C#] 纯文本查看 复制代码
在Start状态中,游戏会检测玩家是否点击屏幕。如果检测到点击后,将AnimationStarted的值设为true,将Max的状态切换为run,此时游戏状态也会切换为Playing。 [C#] 纯文本查看 复制代码
在Playing状态中,首先检查Max的Y方向位置。然后根据玩家的具体操作,控制Max左右移动或跳跃。如果Max正在切换路径,则判断Max当前的X轴位置,并对比切换路径的目标位置。如果两者之间相差不大,则表示Max成功完成了移动,系统可以安全地将isChangingLane参数设置成false并防止Max移动过头。最后,使用CharacterController的Move方法将Max移动到下一段路径。 [C#] 纯文本查看 复制代码
Update方法的最后一部分在Max死亡时调用,即Dead状态。当Max死亡,系统会将AnimationStarted参数设置成false,并提示玩家点击屏幕重新开始游戏。 [C#] 纯文本查看 复制代码
OnControllerHit仅用于“直线型道路”关卡。路径的左右边界设置标签为WidePathBorder,当Max与其产生碰撞,系统会判定转向结束,因为已经碰到边缘了。如果这里不做判断,Max会继续移动直至穿墙,这就会导致严重Bug。 Rotated path关卡 “旋转型道路”关卡与“直线型道路”关卡有些相似,但路径的预制件不一样。对比“直线型道路” 关卡,“旋转型道路”关卡中包含了更多的NewPathSpawns,以及一个SwipeCollider。 Rotated path关卡的层级结构 PathSpawnCollider用作生成下一段路径和RedBorder预制件的触发器。SwipeCollider是唯一允许玩家进行滑动操作的地方。SpawnPoints就是糖果及障碍物的生成点。 当Max进入PathSpawnCollider时,从数组NewPathSpawn的3个位置中随机选择一个位置,实例化一段新的路径。 NewPathSpawnPoint左边 NewPathSpawnPoint右边 NewPathSpawnPoint前方 在这三个位置中随机选择一个作为下一段路径的起点,并在其它两个位置生成RedBorder障碍物。 Stuff Spawner 与Path Spawn Collider 这些脚本都仅用于“直线型道路”关卡,在此不多做描述。 Swipe Collider类——滑动碰撞体 在“旋转型道路”关卡中,当玩家位于路径中途时不允许滑动,只有到达某个特定空间才可以通过滑动让Max转向。可以在场景中放置一个隐形碰撞体Swipe Collider,当Max与Swipe Collider对象进行碰撞时,玩家才能进行滑动动作。代码如下: [C#] 纯文本查看 复制代码
SwipeCollider脚本只用于设置GameManager对象的公共变量,该变量控制Max是否可以左右滑动。当Max进入到碰撞体时执行OnTriggerEnter方法,当Max离开碰撞体时,执行OnTriggerExit方法。 CharacterRotateMovement类——角色转向移动控制类 该脚本与之前“直线型道路”关卡中的CharacterSidewaysMovement脚本非常相似,主要区别在于DetectJumpOrSwipeLeftRight方法,游戏通过Quaternion.AngleAxis来实现Max的转向。 [C#] 纯文本查看 复制代码
从阅读代码片段可以发现,这里之所以没有使用OOP的继承来创建所有的移动类,是因为这里涉及的移动比较简单。如果您游戏的移动机制比较复杂,建议使用继承会更加便于代码管理。 总结 以上示例虽然包含了3D无尽模式跑酷游戏的基本机制,但也还有一些可以继续改善的地方。例如,加入对象池、增加关卡难度、完善Max的死亡动画动作等,希望大家可以自行发挥。 关于本教程如有任何疑问,也请在下方留言提问。 |