前言
在Unity程序设计过程中,我们处理的第一个对象是Application Instance。
它的主要职责是启动流程管理、卸载流程管理,次要职责是管理在内部的子系统生命周期。其他职责,提供或桥接应用程序的配置信息、及其他第三方接口。
它通常以单例的形式存在在场景中,即使在切换场景时,也不会被删除。
设计需求
- 可以自定义异步启动流程、或卸载流程
- App 自动完成子系统的初始化和卸载工作
- 子系统是可轻松扩展的
- 通过App Instance可以轻松访问到子系统实例
UML结构
代码示例
//> XApplication.Utils.cs
//> Create by UniMark
namespace XF
{
public interface IApplication
{
void Startup();
void Initialize();
void Deinitialize();
void Shutdown();
}
public interface IApplicationSubSystem
{
int InitializeSequence { get; }
void Initialize(XApplication application);
void Deinitialize();
}
}
//> XApplication.cs
//> Create by UniMark
using System;
using System.Collections.Generic;
using UnityEngine;
namespace XF
{
public sealed class XApplication : MonoBehaviour
{
private IApplication Application;
private IApplicationSubSystem[] ApplicationSubSystems = new IApplicationSubSystem[0];
private Dictionary<Type, IApplicationSubSystem> QuickReferenceTable;
private void Awake ()
{
Debug.Log($"启动 [XApplication] 实例 ({gameObject.name})");
if ( ( Application = GetComponent<IApplication>() ) == null )
{
throw new Exception("你需要实现IApplication的接口");
}
ApplicationSubSystems = GetAllApplicationSubSystemWithSequence();
QuickReferenceTable = GetQuickReferenceTableWithAppSubSystem(ApplicationSubSystems);
Application.Startup();
}
private void Start ()
{
if ( ApplicationSubSystems.Length > 0 )
{
Debug.Log("实例化应用内联系统 ...");
for ( int index = 0; index < ApplicationSubSystems.Length; index++ )
{
var subSystem = ApplicationSubSystems[index];
var time = Time.time;
subSystem.Initialize(this);
Debug.Log($"释放: {subSystem.GetType().Name} 耗时 {( Time.time - time ).ToString("{0.000}")}s");
}
}
if ( Application != null )
{
Debug.Log("实例化应用 ...");
Application?.Initialize();
}
}
private void OnDestroy ()
{
if ( Application != null )
{
Debug.Log("释放应用 ...");
Application?.Deinitialize();
}
if ( ApplicationSubSystems.Length > 0 )
{
Debug.Log("释放应用内联系统 ...");
for ( int index = ApplicationSubSystems.Length - 1; index >= 0; index-- )
{
var subSystem = ApplicationSubSystems[index];
var time = Time.time;
subSystem.Deinitialize();
Debug.Log($"释放: {subSystem.GetType().Name} 耗时 {(Time.time - time).ToString("{0.000}")}s");
}
}
Debug.Log($"关闭 [XApplication] 实例 ({gameObject.name})");
Application.Shutdown();
Application = null;
ApplicationSubSystems = null;
QuickReferenceTable = null;
}
private IApplicationSubSystem[] GetAllApplicationSubSystemWithSequence ()
{
var list = new List<IApplicationSubSystem>();
GetComponentsInChildren(true, list);
list.Sort(( a, b ) => a.InitializeSequence.CompareTo(b.InitializeSequence));
return list.ToArray();
}
private Dictionary<Type, IApplicationSubSystem> GetQuickReferenceTableWithAppSubSystem ( IApplicationSubSystem[] systems )
{
Dictionary<Type, IApplicationSubSystem> result = new Dictionary<Type, IApplicationSubSystem>();
foreach ( var system in systems )
{
if ( false == result.TryAdd(system.GetType(), system) )
{
throw new Exception($"包含相同类型的子系统 {system.GetType().Name}");
}
}
return result;
}
#region API
public T GetSubSystem<T> () where T : MonoBehaviour, IApplicationSubSystem
{
if ( QuickReferenceTable.TryGetValue(typeof(T), out var system) )
{
return system as T;
}
throw new Exception($"不存在的子系统 {typeof(T).Name}");
}
#endregion
}
}
//> XGame.cs
//> Create by UniMark
using System;
using UnityEngine;
using XF;
public abstract class XGame<T> : MonoBehaviour, IApplication
where T : XGame<T>
{
public static T Instance
{
get; private set;
}
public XApplication Owner
{
get; private set;
}
//> 定义你自己的系统在这里
public TestSubSystem TestSystem { get; private set; }
void IApplication.Startup ()
{
if ( Instance != null )
{
throw new Exception($"[{gameObject.name}]{this.GetType().Name}类存在多实例异常!");
}
Instance = this as T;
GameObject.DontDestroyOnLoad(gameObject);
Owner = GetComponent<XApplication>();
//> 初始化你的系统在这里
TestSystem = Owner.GetSubSystem<TestSubSystem>();
}
void IApplication.Shutdown ()
{
Instance = null;
Owner = null;
//> 释放你的系统在这里
TestSystem = null;
}
void IApplication.Initialize () => StartGame();
void IApplication.Deinitialize () => QuitGame();
protected abstract void StartGame ();
protected abstract void QuitGame ();
}
//> GameIns.cs
//> Create by UniMark
using UnityEngine;
using XF;
public class GameIns : XGame<GameIns>
{
#region 生命周期
protected override async void StartGame ()
{
//> 加载配置文件
//> await 配置文件加载完毕
//> 做个测试
var testSystem = Owner.GetSubSystem<TestSubSystem> ();
Debug.Log(testSystem.GetMessage());
//> 进入第一个场景
}
protected override void QuitGame ()
{
//> 在这里卸载业务载入的资源和数据
}
#endregion
}
//> TestSubSystem.cs
//> Create by UniMark
using UnityEngine;
namespace XF
{
#region 非正式代码
public class TestSubSystem : MonoBehaviour, IApplicationSubSystem
{
[SerializeField]
private int InitializeSequence;
int IApplicationSubSystem.InitializeSequence => InitializeSequence;
private XApplication Owner;
void IApplicationSubSystem.Initialize ( XApplication application )
{
Owner = application;
}
void IApplicationSubSystem.Deinitialize ()
{
Owner = null;
}
public string GetMessage ()
{
return "Hello Here!";
}
}
#endregion
}
代码组织结构
-| Scripts
--| Core
---| SubSystems
---- TestSubSystem.cs
--- XApplication.cs
--- XApplication.Utils.cs
--- XGame.cs
-- GameIns.cs