环境配置
这里导入了第三方库Starter Assets(第三人称)来获取模型和动画,因此需要提前导入这个包,通过Window->Package Manager来管理这些包:
项目结构
这次的项目包括素材、代码、第三方库和场景。
1. 动画部分,包含PlayerController。是根据第三方库的动画剪辑素材,自己制作的Animator,用于控制动画流程。
2. Material部分,一些渲染的素材。
3. 预制部分,包括Player、Guard和Cell的预制。这些预制中包含了应当有的脚本、组件(动画、刚体、碰撞体等)。
4. 场景部分,只包含此次的场景。不过在重新开始功能中,需要重新加载这个场景。
5. 代码部分,下文会说明。
6. 第三方库部分
代码结构
本次的代码结构如下。
分为三个部分,GuardControllers、MainControllers、PlayerControllers。
在主控部分基本与之前的项目相同,这里不赘述。
巡逻兵控制采用了动作分离模式,两个动作分别是走动和跑动(GuardWalkAction和GuardRunAction),还包括了动作管理器GuardActionManager。
巡逻兵的产生采用了工厂模式(GuardFactory和GuardData)。
玩家控制器的PlayerController是一个通过用户输入控制人物移动的角色控制器,不涉及设计模式。
玩家和巡逻兵、主控器之间的通信采用了订阅/发布模式。
玩家的SSEventPublishier是基类,PlayerEventPublishier是子类,可以将游戏结束或进出区域的信息发送给巡逻兵或主控制器。
巡逻兵的IEventHandler是接口,由GuardData来实现这个接口(因为这里有控制Guard运动的数据,可以直接在这里进行修改)。
主控器一直被放在脚本中,因此可以随时通信。
模型和动画预制
Cell预制
采用12*12的场地,在周围分别搭建围墙,作为每一个cell。当运行时可以直接加载多个cell,设置好位置并加载到地图中。
动画制作
-
制作动画状态。这里只有走、跑、站立三个状态。首先需要导入动画剪辑,然后需要设定一些变量来控制这些状态:
-
状态转换需要根据变量的变化进行转换,例如:
Player预制
1. 从第三方库导入model,并添加material
2. 添加Animator:
3. 添加刚体,方便控制运动。
4. 添加碰撞体,注意这里可以调整一下碰撞体的大小和位置。
5. 添加脚本,这里只需要添加角色控制器和发布者即可。
Guard预制
-
直接将Player稍加修改。保留了Model、Animator、RigidBody和Collider。
2. 添加脚本,这里需要添加GuardData。
代码分析
FirstController主控制器
加载资源:
PlayerController角色控制器
- 动画控制,这里的三个变量分别对应动画控制器中的三个变量。
2. 角色移动控制:
3. 镜头控制,需要写在LateUpdate函数中:
GuardData巡逻兵数据和事件处理器
- 所需数据:
2. 响应函数,详见注释:
GuardFactory工厂
- 每次获得随机位置
2. 导入资源
GuardWalkAction巡逻模式下的动作
- FixedUpdate的检测:
2. Walk函数的智能移动方案:
3. 碰撞墙壁时转向:
GuardRunAction追击模式下的动作
- FixedUpdate的检测:
2. Run跑动方案:
GuardActionManager动作管理器
- 这里是我一开始出现的问题,因为没有给他一个初始运动方式。因此,需要一个初始函数来让巡逻兵先走动巡逻:
2. 动作切换:
效果演示