From bbced819dc73c2ff9a2d66edc8e6b882e5ec49c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com>
Date: Mon, 27 Apr 2026 19:43:38 +0800
Subject: [PATCH] =?UTF-8?q?[Opt]=E8=BD=BB=E9=87=8F=E5=8C=96Procudure?=
=?UTF-8?q?=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Runtime/GameApp.cs | 21 +-
Runtime/Procedure/IProcedureService.cs | 27 --
Runtime/Procedure/IProcedureService.cs.meta | 3 -
Runtime/Procedure/ProcedureBase.cs | 59 +--
Runtime/Procedure/ProcedureBuilder.cs | 418 +++++++++++++++++++
Runtime/Procedure/ProcedureBuilder.cs.meta | 3 +
Runtime/Procedure/ProcedureComponent.cs | 15 -
Runtime/Procedure/ProcedureComponent.cs.meta | 3 -
Runtime/Procedure/ProcedureService.cs | 102 -----
Runtime/Procedure/ProcedureService.cs.meta | 3 -
10 files changed, 437 insertions(+), 217 deletions(-)
delete mode 100644 Runtime/Procedure/IProcedureService.cs
delete mode 100644 Runtime/Procedure/IProcedureService.cs.meta
create mode 100644 Runtime/Procedure/ProcedureBuilder.cs
create mode 100644 Runtime/Procedure/ProcedureBuilder.cs.meta
delete mode 100644 Runtime/Procedure/ProcedureComponent.cs
delete mode 100644 Runtime/Procedure/ProcedureComponent.cs.meta
delete mode 100644 Runtime/Procedure/ProcedureService.cs
delete mode 100644 Runtime/Procedure/ProcedureService.cs.meta
diff --git a/Runtime/GameApp.cs b/Runtime/GameApp.cs
index 854c88d..12b9c04 100644
--- a/Runtime/GameApp.cs
+++ b/Runtime/GameApp.cs
@@ -69,26 +69,7 @@ public static partial class GameApp
}
private static IObjectPoolService _objectPool;
-
-
- ///
- /// 获取有限状态机组件。
- ///
- public static IProcedureService Procedure
- {
- get
- {
- if (_procedure == null)
- {
- _procedure = AppServices.RequireApp();
- }
-
- return _procedure;
- }
- }
-
- private static IProcedureService _procedure;
-
+
///
/// 获取Asset组件。
diff --git a/Runtime/Procedure/IProcedureService.cs b/Runtime/Procedure/IProcedureService.cs
deleted file mode 100644
index 893273a..0000000
--- a/Runtime/Procedure/IProcedureService.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace AlicizaX
-{
- public interface IProcedureService : IService
- {
- Type CurrentProcedureType { get; }
- void InitializeProcedure(IEnumerable availableProcedures, Type defaultProcedureType);
- void ClearAllProcedures();
- bool ContainsProcedure(Type procedureType);
- bool TrySwitchProcedure(Type procedureType);
- }
-
- public static class ProcedureServiceExtensions
- {
- public static bool SwitchProcedure(this IProcedureService procedureService) where T : IProcedure
- {
- return procedureService.TrySwitchProcedure(typeof(T));
- }
-
- public static bool SwitchProcedure(this IProcedureService procedureService, Type procedureType)
- {
- return procedureService.TrySwitchProcedure(procedureType);
- }
- }
-}
diff --git a/Runtime/Procedure/IProcedureService.cs.meta b/Runtime/Procedure/IProcedureService.cs.meta
deleted file mode 100644
index 4585a5c..0000000
--- a/Runtime/Procedure/IProcedureService.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 18d5ca3d17384612b2d2023084b6a97b
-timeCreated: 1763451617
\ No newline at end of file
diff --git a/Runtime/Procedure/ProcedureBase.cs b/Runtime/Procedure/ProcedureBase.cs
index 8d3609e..57e5a6e 100644
--- a/Runtime/Procedure/ProcedureBase.cs
+++ b/Runtime/Procedure/ProcedureBase.cs
@@ -1,72 +1,43 @@
namespace AlicizaX
{
- public interface IProcedure
- {
- IProcedureService ProcedureService { get; set; }
- void Init();
- void Enter();
- void Leave();
- void Update();
- void Destroy();
- }
+ // public interface IProcedure
+ // {
+ // void Init();
+ // void Enter();
+ // void Leave();
+ // void Update();
+ // void Destroy();
+ // }
///
/// 流程基类 - 使用模板方法模式定义流程生命周期
///
- public abstract class ProcedureBase : IProcedure
+ public abstract class ProcedureBase
{
- public IProcedureService ProcedureService { get; set; }
-
- void IProcedure.Init()
- {
- OnInit();
- }
-
- void IProcedure.Enter()
- {
- OnEnter();
- }
-
- void IProcedure.Leave()
- {
- OnLeave();
- }
-
- void IProcedure.Update()
- {
- OnUpdate();
- }
-
- void IProcedure.Destroy()
- {
- OnDestroy();
- }
-
-
- protected virtual void OnInit()
+ protected internal virtual void OnInit()
{
}
- protected virtual void OnEnter()
+ protected internal virtual void OnEnter()
{
}
- protected virtual void OnLeave()
+ protected internal virtual void OnLeave()
{
}
- protected virtual void OnUpdate()
+ protected internal virtual void OnUpdate()
{
}
- protected virtual void OnDestroy()
+ protected internal virtual void OnDestroy()
{
}
protected internal void SwitchProcedure() where T : ProcedureBase
{
- ProcedureService.SwitchProcedure();
+ ProcedureBuilder.SwitchProcedure();
}
}
}
diff --git a/Runtime/Procedure/ProcedureBuilder.cs b/Runtime/Procedure/ProcedureBuilder.cs
new file mode 100644
index 0000000..ac6bb38
--- /dev/null
+++ b/Runtime/Procedure/ProcedureBuilder.cs
@@ -0,0 +1,418 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AlicizaX
+{
+ public static class ProcedureBuilder
+ {
+ private const string ProcedureRunnerName = "[ProcedureRunner]";
+
+ private static ProcedureRunner _runner;
+
+ public static Type CurrentProcedureType => _runner != null ? _runner.CurrentProcedureType : null;
+
+ public static bool IsRunning => _runner != null;
+
+ public static void InitializeProcedure(IEnumerable availableProcedures, Type defaultProcedureType)
+ {
+ DestroyProcedure();
+
+ var gameObject = new GameObject(ProcedureRunnerName);
+ UnityEngine.Object.DontDestroyOnLoad(gameObject);
+
+ _runner = gameObject.AddComponent();
+ _runner.InitializeProcedure(availableProcedures, defaultProcedureType);
+ }
+
+ public static void InitializeProcedure(ProcedureBase[] availableProcedures, Type defaultProcedureType)
+ {
+ DestroyProcedure();
+
+ var gameObject = new GameObject(ProcedureRunnerName);
+ UnityEngine.Object.DontDestroyOnLoad(gameObject);
+
+ _runner = gameObject.AddComponent();
+ _runner.InitializeProcedure(availableProcedures, defaultProcedureType);
+ }
+
+ public static void InitializeProcedure(List availableProcedures, Type defaultProcedureType)
+ {
+ DestroyProcedure();
+
+ var gameObject = new GameObject(ProcedureRunnerName);
+ UnityEngine.Object.DontDestroyOnLoad(gameObject);
+
+ _runner = gameObject.AddComponent();
+ _runner.InitializeProcedure(availableProcedures, defaultProcedureType);
+ }
+
+ public static bool SwitchProcedure() where T : ProcedureBase
+ {
+ return _runner != null && _runner.TrySwitchProcedure(typeof(T));
+ }
+
+ public static bool SwitchProcedure(Type procedureType)
+ {
+ return _runner != null && _runner.TrySwitchProcedure(procedureType);
+ }
+
+ public static bool ContainsProcedure() where T : ProcedureBase
+ {
+ return _runner != null && _runner.ContainsProcedure(typeof(T));
+ }
+
+ public static bool ContainsProcedure(Type procedureType)
+ {
+ return _runner != null && _runner.ContainsProcedure(procedureType);
+ }
+
+ public static void DestroyProcedure()
+ {
+ if (_runner == null)
+ {
+ return;
+ }
+
+ var gameObject = _runner.gameObject;
+ _runner.Shutdown();
+ _runner = null;
+
+ if (gameObject != null)
+ {
+ UnityEngine.Object.Destroy(gameObject);
+ }
+ }
+
+ private sealed class ProcedureRunner : MonoBehaviour
+ {
+ private const int MaxLoadFactorNumerator = 7;
+ private const int MaxLoadFactorDenominator = 10;
+
+ private Type[] _types;
+ private ProcedureBase[] _procedures;
+ private int[] _orderedIndices;
+ private ProcedureBase[] _orderedProcedures;
+ private int _procedureCount;
+ private int _bucketCount;
+
+ private ProcedureBase _currentProcedure;
+ private ProcedureBase _defaultProcedure;
+ private bool _isDestroying;
+
+ public Type CurrentProcedureType => _currentProcedure != null ? _currentProcedure.GetType() : null;
+
+ public void InitializeProcedure(IEnumerable availableProcedures, Type defaultProcedureType)
+ {
+ ClearAllProcedures();
+
+ if (availableProcedures == null || defaultProcedureType == null)
+ {
+ return;
+ }
+
+ foreach (var procedure in availableProcedures)
+ {
+ AddProcedure(procedure);
+ }
+
+ if (TryGetProcedure(defaultProcedureType, out var defaultProcedure))
+ {
+ _defaultProcedure = defaultProcedure;
+ TrySwitchProcedure(defaultProcedureType);
+ }
+ }
+
+ public void InitializeProcedure(ProcedureBase[] availableProcedures, Type defaultProcedureType)
+ {
+ ClearAllProcedures();
+
+ if (availableProcedures == null || defaultProcedureType == null)
+ {
+ return;
+ }
+
+ EnsureCapacity(availableProcedures.Length);
+
+ for (var i = 0; i < availableProcedures.Length; i++)
+ {
+ AddProcedure(availableProcedures[i]);
+ }
+
+ if (TryGetProcedure(defaultProcedureType, out var defaultProcedure))
+ {
+ _defaultProcedure = defaultProcedure;
+ TrySwitchProcedure(defaultProcedureType);
+ }
+ }
+
+ public void InitializeProcedure(List availableProcedures, Type defaultProcedureType)
+ {
+ ClearAllProcedures();
+
+ if (availableProcedures == null || defaultProcedureType == null)
+ {
+ return;
+ }
+
+ EnsureCapacity(availableProcedures.Count);
+
+ for (var i = 0; i < availableProcedures.Count; i++)
+ {
+ AddProcedure(availableProcedures[i]);
+ }
+
+ if (TryGetProcedure(defaultProcedureType, out var defaultProcedure))
+ {
+ _defaultProcedure = defaultProcedure;
+ TrySwitchProcedure(defaultProcedureType);
+ }
+ }
+
+ public void ClearAllProcedures()
+ {
+ if (_currentProcedure != null)
+ {
+ _currentProcedure.OnLeave();
+ _currentProcedure = null;
+ }
+
+ for (var i = 0; i < _procedureCount; i++)
+ {
+ var procedure = _orderedProcedures[i];
+ if (procedure == null)
+ {
+ continue;
+ }
+
+ procedure.OnDestroy();
+ _orderedProcedures[i] = null;
+ }
+
+ if (_types != null)
+ {
+ for (var i = 0; i < _types.Length; i++)
+ {
+ _types[i] = null;
+ _procedures[i] = null;
+ }
+ }
+
+ _procedureCount = 0;
+ _bucketCount = 0;
+ _defaultProcedure = null;
+ }
+
+ public bool ContainsProcedure(Type procedureType)
+ {
+ return TryGetProcedure(procedureType, out _);
+ }
+
+ public bool TrySwitchProcedure(Type procedureType)
+ {
+ if (procedureType == null || _isDestroying)
+ {
+ return false;
+ }
+
+ if (!TryGetProcedure(procedureType, out var nextProcedure))
+ {
+ nextProcedure = _defaultProcedure;
+ }
+
+ if (nextProcedure == null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(_currentProcedure, nextProcedure))
+ {
+ return true;
+ }
+
+ var previousProcedure = _currentProcedure;
+ _currentProcedure = nextProcedure;
+ previousProcedure?.OnLeave();
+ nextProcedure.OnEnter();
+ return true;
+ }
+
+ public void Shutdown()
+ {
+ _isDestroying = true;
+ ClearAllProcedures();
+ }
+
+ private void AddProcedure(ProcedureBase procedure)
+ {
+ if (procedure == null)
+ {
+ return;
+ }
+
+ var type = procedure.GetType();
+ EnsureCapacity(_procedureCount + 1);
+
+ var index = FindIndex(type);
+
+ if (index >= 0)
+ {
+ var previousProcedure = _procedures[index];
+ if (previousProcedure != null)
+ {
+ if (ReferenceEquals(_currentProcedure, previousProcedure))
+ {
+ _currentProcedure = null;
+ }
+
+ if (ReferenceEquals(_defaultProcedure, previousProcedure))
+ {
+ _defaultProcedure = procedure;
+ }
+
+ previousProcedure.OnDestroy();
+ }
+
+ _procedures[index] = procedure;
+ _orderedProcedures[_orderedIndices[index]] = procedure;
+ procedure.OnInit();
+ return;
+ }
+
+ var insertIndex = FindInsertIndex(type);
+ _types[insertIndex] = type;
+ _procedures[insertIndex] = procedure;
+ _orderedIndices[insertIndex] = _procedureCount;
+ _orderedProcedures[_procedureCount] = procedure;
+ _procedureCount++;
+ _bucketCount++;
+ procedure.OnInit();
+ }
+
+ private bool TryGetProcedure(Type procedureType, out ProcedureBase procedure)
+ {
+ var index = FindIndex(procedureType);
+ if (index >= 0)
+ {
+ procedure = _procedures[index];
+ return true;
+ }
+
+ procedure = null;
+ return false;
+ }
+
+ private int FindIndex(Type procedureType)
+ {
+ if (procedureType == null || _types == null)
+ {
+ return -1;
+ }
+
+ var mask = _types.Length - 1;
+ var index = procedureType.GetHashCode() & mask;
+
+ for (var i = 0; i < _types.Length; i++)
+ {
+ var type = _types[index];
+ if (type == null)
+ {
+ return -1;
+ }
+
+ if (type == procedureType)
+ {
+ return index;
+ }
+
+ index = (index + 1) & mask;
+ }
+
+ return -1;
+ }
+
+ private int FindInsertIndex(Type procedureType)
+ {
+ var mask = _types.Length - 1;
+ var index = procedureType.GetHashCode() & mask;
+
+ while (_types[index] != null)
+ {
+ index = (index + 1) & mask;
+ }
+
+ return index;
+ }
+
+ private void EnsureCapacity(int targetCapacity)
+ {
+ if (_types != null && _orderedProcedures.Length >= targetCapacity && (_bucketCount + 1) * MaxLoadFactorDenominator < _types.Length * MaxLoadFactorNumerator)
+ {
+ return;
+ }
+
+ var newProcedureCapacity = _orderedProcedures == null ? 4 : _orderedProcedures.Length;
+ while (newProcedureCapacity < targetCapacity)
+ {
+ newProcedureCapacity <<= 1;
+ }
+
+ var newBucketCapacity = _types == null ? 8 : _types.Length;
+ while (targetCapacity * MaxLoadFactorDenominator >= newBucketCapacity * MaxLoadFactorNumerator)
+ {
+ newBucketCapacity <<= 1;
+ }
+
+ var newTypes = new Type[newBucketCapacity];
+ var newProcedures = new ProcedureBase[newBucketCapacity];
+ var newOrderedIndices = new int[newBucketCapacity];
+ var newOrderedProcedures = new ProcedureBase[newProcedureCapacity];
+
+ for (var i = 0; i < _procedureCount; i++)
+ {
+ var procedure = _orderedProcedures[i];
+ var type = procedure.GetType();
+ var insertIndex = FindInsertIndex(newTypes, type);
+ newTypes[insertIndex] = type;
+ newProcedures[insertIndex] = procedure;
+ newOrderedIndices[insertIndex] = i;
+ newOrderedProcedures[i] = procedure;
+ }
+
+ _types = newTypes;
+ _procedures = newProcedures;
+ _orderedIndices = newOrderedIndices;
+ _orderedProcedures = newOrderedProcedures;
+ _bucketCount = _procedureCount;
+ }
+
+ private static int FindInsertIndex(Type[] types, Type procedureType)
+ {
+ var mask = types.Length - 1;
+ var index = procedureType.GetHashCode() & mask;
+
+ while (types[index] != null)
+ {
+ index = (index + 1) & mask;
+ }
+
+ return index;
+ }
+
+ private void Update()
+ {
+ _currentProcedure?.OnUpdate();
+ }
+
+ private void OnDestroy()
+ {
+ if (_runner == this)
+ {
+ _runner = null;
+ }
+
+ Shutdown();
+ }
+ }
+ }
+}
diff --git a/Runtime/Procedure/ProcedureBuilder.cs.meta b/Runtime/Procedure/ProcedureBuilder.cs.meta
new file mode 100644
index 0000000..f581fc0
--- /dev/null
+++ b/Runtime/Procedure/ProcedureBuilder.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6c4b9af55d3c4f53a8d9e58a45d8a2b1
+timeCreated: 1777305600
diff --git a/Runtime/Procedure/ProcedureComponent.cs b/Runtime/Procedure/ProcedureComponent.cs
deleted file mode 100644
index c85efd7..0000000
--- a/Runtime/Procedure/ProcedureComponent.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using UnityEngine;
-
-namespace AlicizaX
-{
- [DisallowMultipleComponent]
- [AddComponentMenu("Game Framework/Procedure")]
- public sealed class ProcedureComponent : MonoBehaviour
- {
- private void Awake()
- {
- AppServices.RegisterApp(new ProcedureService());
- }
- }
-}
-
diff --git a/Runtime/Procedure/ProcedureComponent.cs.meta b/Runtime/Procedure/ProcedureComponent.cs.meta
deleted file mode 100644
index dce34ef..0000000
--- a/Runtime/Procedure/ProcedureComponent.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: c0a419f3af614cdda5267671f803dfdb
-timeCreated: 1763451994
\ No newline at end of file
diff --git a/Runtime/Procedure/ProcedureService.cs b/Runtime/Procedure/ProcedureService.cs
deleted file mode 100644
index 1cfae19..0000000
--- a/Runtime/Procedure/ProcedureService.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using System;
-using System.Collections.Generic;
-using UnityEngine;
-
-namespace AlicizaX
-{
- internal class ProcedureService : ServiceBase, IProcedureService, IServiceTickable
- {
- private readonly Dictionary _procedures = new Dictionary();
- private IProcedure _currentProcedure;
- private IProcedure _defaultProcedure;
-
- public Type CurrentProcedureType => _currentProcedure?.GetType();
-
- public void InitializeProcedure(IEnumerable availableProcedures, Type defaultProcedureType)
- {
- _procedures.Clear();
- foreach (var procedure in availableProcedures)
- {
- if (procedure == null)
- {
- continue;
- }
-
- var type = procedure.GetType();
- _procedures[type] = procedure;
- procedure.ProcedureService = this;
- procedure.Init();
- }
-
- if (_procedures.TryGetValue(defaultProcedureType, out var defaultProcedure))
- {
- _defaultProcedure = defaultProcedure;
- TrySwitchProcedure(defaultProcedureType);
- }
- else
- {
- Log.Info($"榛樿娴佺▼ {defaultProcedureType.Name} 鏈敞鍐?");
- }
- }
-
- public void ClearAllProcedures()
- {
- foreach (var procedure in _procedures.Values)
- {
- procedure.Destroy();
- }
-
- _procedures.Clear();
- _currentProcedure = null;
- _defaultProcedure = null;
- }
-
- public bool ContainsProcedure(Type procedureType)
- {
- return procedureType != null && _procedures.ContainsKey(procedureType);
- }
-
- public bool TrySwitchProcedure(Type procedureType)
- {
- if (procedureType == null)
- {
- return false;
- }
-
- if (!_procedures.TryGetValue(procedureType, out var nextProcedure))
- {
- if (_defaultProcedure == null)
- {
- return false;
- }
-
- Debug.LogWarning($"娴佺▼ {procedureType.Name} 涓嶅瓨鍦紝鍒囨崲鍒伴粯璁ゆ祦绋?");
- nextProcedure = _defaultProcedure;
- }
-
- if (ReferenceEquals(_currentProcedure, nextProcedure))
- {
- return true;
- }
-
- _currentProcedure?.Leave();
- nextProcedure.Enter();
- _currentProcedure = nextProcedure;
- return true;
- }
-
- protected override void OnInitialize()
- {
- }
-
- protected override void OnDestroyService()
- {
- ClearAllProcedures();
- }
-
- void IServiceTickable.Tick(float deltaTime)
- {
- _currentProcedure?.Update();
- }
- }
-}
diff --git a/Runtime/Procedure/ProcedureService.cs.meta b/Runtime/Procedure/ProcedureService.cs.meta
deleted file mode 100644
index 434e607..0000000
--- a/Runtime/Procedure/ProcedureService.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 4272c5c31b6b4a459f1da37a228cfd3f
-timeCreated: 1763450372
\ No newline at end of file