最近做了一个小的跑酷游戏,今天就我前几天写的 游戏玩家跟随在跑道上的路点行走的简单逻辑进行一下梳理,希望大家和我自己都能够有一定的进步。
下面我先说一下该款游戏的一些有必要知道的前提。跑道是动态生成的,而路点又是作为跑道子对象waypoints的子对象(简单而言,就是孙子对象)存在。所以,路点也就是动态创建,动态销毁了。我的思路是在游戏刚刚加载时,由RacetrackGenerator脚本类在初始化时先动态生成两个跑道,而每个跑道都有一个自己的WaypointsManager(路点管理器脚本),用来管理自身的所有路点。我们生成跑道的逻辑是这样的:当游戏角色跑到第一个跑道的最后一个路点的时候,在第二段跑道后面动态生成第三段跑道,接在第二段跑道上面,过几秒钟销毁第一段跑道,此时游戏角色在第二段跑道上已经是恣意驰骋了。等到游戏角色跑到第二段跑道最后一个路点时,与前面相同的逻辑,在第三段跑道的末尾接上动态生成的第四段跑道,几秒钟之后,游戏角色已经跑完的第二段跑道就会销毁。此时,跑道上只剩下了第三段和第四段两段跑道。之后,就是重复这样的逻辑,知道玩家跑到想歇一歇喝杯茶的程度。
说到这里,可能大家都感觉逻辑异常简单,但是却不知道如何下手。问题主要是:我们如何能够判断玩家跑到当前跑道的最后面,也就是最后一个路点???
故名思议,我们判断玩家跑道第几个路点,当然不是负责动态生成跑道的脚本负责喽,根据面向对象的单一职责原则,每一个类只要负责好自己的那点儿事就好了,何必替别人操心呢。所以,我自己设计了一个路点管理器类用来管理跑道上的路点waypoint。具体职责是:当游戏角色接近一个路点时,将目标路点设置为当前接近游戏角色路点的下一个路点。负责此功能的函数签名是:public Vector3 GetTargetWayPoint(Transform player)。具体代码我会在后面贴出,大家可以先理顺一下思路。我经常看别人的博客,不怎么看具体思路,直接看代码,然后就云里雾里了,大家可以看懂思路,然后自己写属于自己的代码,我的代码就权当抛砖引玉了。回到那个函数上来,见名知意,这个函数就是用来获取目标路点的,何为目标路点呢,就是游戏角色所要到达的目标点,当然了,当游戏角色接近该目标点,该目标点又会变成了下一个路点。
我的代码有一个局限性,就是路点在跑道上的设置是有讲究的,换句话说,路点必须在跑道上这样设置:就是第一个动态生成的跑道上的waypoint0要设置在游戏角色的后面,此时,游戏角色离waypoint1要远一些作为当前游戏角色的目标路点。
当游戏角色跑到当前跑道最后一个路点时,即目标路点为最后一个路点,在此条件下,当游戏角色距离该目标路点很近时,目标路点变为下一段跑道上的第0个路点(程序员通常都是从0开始计数的 >_<)。
但是问题又来了,我们的路点管理器只能够管理当前跑道的路点,怎么能够管别人的家务事(不能够管理下一个跑道上的路点)。所以,从当前跑道 到 下一段跑道的变换就需要另一个必要的脚本来控制了,负责此功能的脚本类就是RaceTrackGenerator了。我在该类中引用了两个对象: WaypointsManager currentWaypointsManager 和 WaypointsManager nextWaypointsManager。这两个对象从字面上很容易理解,就是游戏角色所在跑道上的路点管理器和下一段跑道上的路点管理器。最关键的是:我们如何正确的取得这两个路点管理器。我们前面说过,跑道生成器脚本类负责在初始化时动态加载两个跑道,那么一开始,currentWaypointsManager 和nextWaypointsManager也就有着落了。就是获取这两个动态生成的跑道游戏对象的路点管理器脚本类组件,哈哈,是不是有点绕,看两遍就理顺了。
跑道生成器脚本类中始终存在着两个游戏对象的引用:
GameObject currentRaceTrack;
GameObject nextRaceTrack;
这样环环相扣的逻辑就是用 简单的 “只需要两个”的逻辑就可以完美的解决。其实,我发现,很多算法都可以只是用 “只需要两个”的思路解决。以后的博客中,我好好整理一下这种解决问题的思路。
路点管理器中引用了一个WaypointsManager脚本类的 nextWaypointsManager对象,并且存在一个set方法,用来在RaceTrackGenerator脚本类中设置路点管理器脚本类对象的下一个路点管理器对象。那我们就看一下代码吧,因为网速原因,早上写得一些文字都没保存上,所以肯定会有衔接不上的地方,等我脑子清醒点儿的时候再改一下,谢谢大家。


1 /* 2 * 负责生成跑道 3 * 具体功能: 1> 游戏开始时初始化创建两段跑道 4 * 2> 创建跑道,并且改变当前跑道和下一段跑道 【耦合了创建障碍物和道具的代码,这是设计不合理的地方】 5 * 3> 获取当前跑道和下一段跑道的引用 6 * 7 */ 8 9 using UnityEngine; 10 using System.Collections; 11 using System.Collections.Generic; 12 13 public class RacetrackGenerator : MonoBehaviour { 14 public GameObject[] raceTrackPrefabs; 15 public ElementsGenerator elementsGenerator; //负责在跑道上动态生成障碍物、钻石、道具、僵尸等等游戏元素 16 17 int maxRaceTrackTypeIndex; 18 19 GameObject currentRaceTrack; 20 GameObject nextRaceTrack; 21 WaypointsManager currentWaypointsManager; 22 WaypointsManager nextWaypointsManager; 23 // Use this for initialization 24 void Start () { 25 maxRaceTrackTypeIndex = raceTrackPrefabs.Length; 26 } 27 28 // Update is called once per frame 29 void<