文章地址:https://www.cnblogs.com/liangxiegame/p/Unity-you-xi-kuang-jia-da-jian-qi-jian-shao-jia-ba.html
App类的职责:
1.接收生命周期事件
2.作为游戏的入口
3.一些框架级别组件的初始化。
好吧看看这个职责,我是完全不能体会为什么会有一个类去专门做这些事情。作者本文讲了一下第二个职责,我勉强看了很多遍整理出来他的思想。
问题情景是这样,经常要测很多东西,需要进游戏内才能测。比如我做AI,我要测赛车在赛道的跑动情况,在测试场景中赛车的数据和比赛中是完全不一样的。所以测试的时候经常就写一个功能,打Log,进入游戏---创房间----等AI。重复很多次这种行为,是很浪费时间没错。
问题就在于下一个模块要依赖于前一个模块的逻辑和数据,第二可能就是模块太深了,我要比赛就必须从登陆到建房间开始游戏。那么第一个问题的解决方案就是写一个接口,可以直接在模块的入口就做好资源数据的加载和初始化,第二就是在模块的入口写一个接口,可以直接跳转到这个界面。
阶段划分:
综上所述,为了以上解决问题而写的代码,其实需要在出包或者正式发布的时候失效。所以就有了阶段的划分:
1.开发阶段
2.出包/真机阶段
3.发布阶段,就是上线了
public enum AppMode
{
Developing,
QA,
Release
}
好,情景和解决方案都大概明白了,开始解析代码。
/// <summary>
/// 全局唯一继承于MonoBehaviour的单例类,保证其他公共模块都以App的生命周期为准
/// </summary>
public class App : QMonoSingleton<App>
{
public AppMode mode = AppMode.Developing;
private App() {}
void Awake()
{
// 确保不被销毁
DontDestroyOnLoad(gameObject);
mInstance = this;
Application.targetFrameRate = 60;
}
void Start()
{
CoroutineMgr.Instance ().StartCoroutine (ApplicationDidFinishLaunching());
}
/// <summary>
/// 进入游戏
/// </summary>
IEnumerator ApplicationDidFinishLaunching()
{
// 配置文件加载 类似PlayerPrefs
QSetting.Load();
// 日志输出
QLog.Instance ();
yield return GameManager.Instance ().Init ();
// 进入测试逻辑
if(App.Instance().mode == AppMode.Developing)
{
// 测试资源加载
ResMgr.Instance ().LoadRes ("TestRes",delegate(string
resName, Object resObj)
{
if(null != resObj)
{
GameObject.Instantiate(resObj);
}
// 进入目标界面等等
});
yield return null;
// 进入正常游戏逻辑
} else
{
yield return GameManager.Instance ().Launch ();
}
yield return null;
}
按照上面的写法在生命周期里面更新AppMode,就可以保证这部分用于开发期间测试的逻辑不会影响到正常游戏里了,也不用等上线时麻烦地去清理这些代码。
之后还有一个问题:
这个if(App.Instance().mode == AppMode.Developing)为true之后的逻辑,肯定是不能这么写的。这里需要兼容不同的模块,答案是用多态。其实这里用依赖倒置原则来想,就应该抽象出去。
public
interface ITestEntry
{
/// <summary>
/// 这里实现写针对不同模块入口该有的逻辑
/// </summary>
IEnumerator Launch();
}
/// <summary>
/// AR模块测试入口
/// </summary>
public
class ARSceneTestEntry :MonoBehaviour,ITestEntry {
public IEnumerator Launch()
{
Debug.LogWarning ("进入AR场景开始");
yield return GameObject.Find ("ARScene").GetComponent<ARScene> ().Launch ();
yield return null;
}
}
App类中阶段区分的代码要改成这样:
// 进入测试逻辑
if(App.Instance().mode == AppMode.Developing)
{
yield return GetComponent<ITestEntry> ().Launch ();
}
else // 进入正常游戏逻辑
{
yield return GameManager.Instance ().Launch ();
}
当然,这里的代码都是原作者写的测试代码,真实的项目中这些逻辑写在哪里就根据情况来定了,但是思想确实是这么回事。