常量合法性测试
为了防止在游戏中配置的协议常量、事件常量的值出现重复,我们添加一个测试脚本。
MsgEventTest在Scripts文件夹内新建Test文件夹。在其中新建ITest脚本
1234public interface ITest{ void Execute();}
再新建MsgEventTest脚本
1234567891011121314151617181920212223using System;using UnityEngine;using System.Collections.Generic;public class MsgEventTest : ITest{ public void Execute() { HashSet<int> insHashSet = new(); Type type = typeof(MsgEvent); var fieldInfos = type.GetFields(); foreach (var fieldInfo in fie ...
输入模块管理
设计一个指令监听模块,监听并发布用户的输入指令或AI的指令,便于组合和拓展功能。
InputModule在Scripts——Module文件夹内新建Input文件夹,新建InputModule
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139using System;using System.Collections.Generic;using UnityEngine;public interface IInputModule& ...
Game场景层级管理
我们再次重构Game场景,引入层级来对Game场景中的对象进行管理。
修改SceneRoot预制体层级,添加MapMgr节点:
SceneRoot
Main Camera
MapMgr
map_0
map_1
将MapMgr拉取进Resources——Prefab——Game中。并把SceneRoot预制体中的MapMgr节点删掉,仅保留Main Camera。
拉取一个小飞机到场景,命名为Player,并将Prefab保存到Resources——Prefab——Game中。
在Pathes中添加这些Prefab的路径
12public const string PREFAB_MAP_MGR = PREFAB_GAME_FOLDER + "MapMgr";public const string PREFAB_PLAYER = PREFAB_GAME_FOLDER + "Player";
在Enums中添加GameLayer枚举,这里设置成负数,方便在后面指定各个层级的z轴大小
123456public enum GameLaye ...
无限Map背景
在Resources——Picture中新建Map文件夹,并将每个关卡的Map图片放在里面。每个Map图片都是上下无缝连接的。
在Game场景中新建SceneRoot空物体,并拿Main Camera和两张Map作为它的子物体,两张Map分别命名为map_0和map_1,并将两张Map上下无缝贴好,摄像机照向下面的Map。
我们想要Camera一直向Y轴正方向移动,而Camera的Postion和上面的Map重合时,下面的Map转到上面Map的上面,不断重复。
各种配置将SceneRoot拉取到Resources——Prefab——Game文件夹内。
在Consts中添加Map图片的名称前缀
1public const string MAP_PREFIX = "map_level_";
修改GameStateModel中的Level,修改为PlaneLevel
在GameModel中添加SelectedLevel属性,代表当前选择的关卡。
1public int SelectedLevel { get; set; }
修改LevelItemC ...
UI分层
目前我们的游戏暂停界面并不是弹窗的形式,而是覆盖掉了之前的GameUI,这是不合理的。
在这里我们引入UI分层的概念,定义好每个UI的层级关系,让每种UI更合理地显示在屏幕上。
UILayer枚举在Enums中定义三个UI层级
1234567public enum UILayer{ BASE_UI, MIDDLE_UI, TOP_UI, COUNT}
每个UI层级内的UI界面互相覆盖
不同UI层级的UI界面可以同时显示
这里只定义了三个层级,一般够用了。
UILayerMgr我们定义好三个层级,需要在游戏启动时根据三个层级创建UI父物体,然后新建的UI根据自己的层级自动挂载到对应的UI父物体上。
123456789101112131415161718192021222324252627282930313233343536373839404142434445using System.Collections.Generic;using UnityEngine;public class UILayerMgr : NormalSinglet ...
左右手模式
数据准备在Enums中添加左右手模式的枚举
12345public enum HandMode{ RIGHT, LEFT}
在DataKeys中添加存档文件中左右手模式的键值。
12//左右手模式public const string HAND_MODE = "HandMode";
在GameStateModel中添加此枚举变量,并在GameStateModel的构造函数中设定值。
12345public GameStateModel() { HandMode = (HandMode)DataMgr.Instance.Get<int>(DataKeys.HAND_MODE);}public HandMode HandMode { get; set; }
在MsgEvent中添加切换左右手的事件id
1public const int EVENT_CHANGE_HAND = 6;
添加新的工具类在Utility文件夹中新建GameUtil工具类
1234567891011 ...
护盾和炸弹UI部分逻辑
Shield、ShieldController、Bomb、BombController的创建略。
在GameUIView中添加挂载Shield和Bomb的逻辑
1234567protected override void InitChild(){ UIUtil.Get("Life").AddCo<Life>(); UIUtil.Get("Bomb").AddCo<Bomb>(); UIUtil.Get("Shield").AddCo<Shield>(); //...}
修改ExtendUtil和UIUtil在ExtendUtil中添加更加便捷的动态挂载脚本的transform拓展方法。方便Controller动态挂载脚本。
12345678public static T AddCo<T>(this Transform target) where T : Component{ return target.gameObje ...
游戏暂停
游戏暂停界面
暂停界面的Pathes路径、GamePauseView、GamePauseController的创建略
Empty4RaycastEmpty4Raycast脚本挂载在GamePauseView根节点上,它是一个不增加overdraw但是可以阻挡点击事件的脚本。使用这个脚本,可以让我们的背景完全透明但不像Image组件那样增加overdraw。注意,GamePauseView根节点必须还要挂载Canvas Renderer组件。
在Utility文件夹中新建Empty4Raycast脚本。
1234567891011121314using UnityEngine.UI;public class Empty4Raycast : MaskableGraphic{ public Empty4Raycast() { useLegacyMeshGeneration = false; } protected override void OnPopulateMesh(VertexHelper vh) { ...
消息系统
在Game场景中,每个UI的UpdateFun需要通过消息系统来更新。
首先先在Scripts——Module中新建Message文件夹
MessageSystem1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465using System.Collections.Generic;public interface IMessageSystem{ void AddListener(int key, IReceiver receiver); void RemoveListener(int key, IReceiver receiver); void DispatchMsg(int key, params object[] args); void AddListener(string key, IReceiver receiver); void RemoveList ...
生命值 UI界面
GameUI搭建
HP血条是通过动态增删LifeItem图片实现的
右下角为护盾和炸弹,需要添加特效,还需要添加左手右手模式。
在Prefab文件夹内,新建UI文件夹,将UI的Prefab全部转移进去,并修改Pathes里面的路径
Pathes中添加UIPrefab路径和创建GameUIController、GameUIView的部分略。注意要创建在Scripts——UI——GameUI文件夹内。
Const在Const中添加玩家最大生命值常量,以及LifeItem最大显示数量。
123//游戏中部分常量数据public const int LIFE_MAX = 100;public const int LIFE_ITEM_NUM = 10;
GameUIView只有根节点上的UI脚本才会使用“View”做结尾。
12345678[BindPrefab(Pathes.GAMEUI_VIEW,Consts.BIND_PREFAB_PRIORITY_VIEW)]public class GameUIView : ViewBase{ protected overr ...