Compare commits

..

No commits in common. "e7a4150495c8971b197074135c5f5cd5d1be4e02" and "c4c9a22fc42bc8ef9052040cd162ce865c588464" have entirely different histories.

38 changed files with 263 additions and 242 deletions

View File

@ -7,87 +7,67 @@ namespace AlicizaX
private static ServiceWorld _world;
public static bool HasWorld => _world != null;
internal static ServiceWorld EnsureWorld(int appScopeOrder = ServiceDomainOrder.App)
public static bool HasScene => _world != null && _world.HasScene;
public static bool HasGameplay => _world != null && _world.HasGameplay;
public static ServiceWorld World
{
get
{
if (_world == null)
throw new InvalidOperationException("ServiceWorld has not been created yet.");
return _world;
}
}
public static ServiceScope App => World.App;
public static ServiceScope Scene => World.Scene;
public static ServiceScope Gameplay => World.Gameplay;
public static ServiceWorld EnsureWorld(int appScopeOrder = ServiceDomainOrder.App)
{
if (_world == null)
_world = new ServiceWorld(appScopeOrder);
return _world;
}
internal static ServiceWorld RequireWorld()
public static ServiceScope EnsureScene(int order = ServiceDomainOrder.Scene)
=> World.EnsureScene(order);
public static bool TryGetScene(out ServiceScope scope)
{
if (_world == null)
throw new InvalidOperationException("ServiceWorld has not been created yet.");
return _world;
if (_world == null) { scope = null; return false; }
return _world.TryGetScene(out scope);
}
public static T RegisterApp<T>(T service, params Type[] extraContracts) where T : class, IService
=> RequireWorld().App.Register(service, extraContracts);
public static ServiceScope ResetScene(int order = ServiceDomainOrder.Scene)
=> World.ResetScene(order);
public static bool TryGetApp<T>(out T service) where T : class, IService
public static bool DestroyScene()
=> _world != null && _world.DestroyScene();
public static ServiceScope EnsureGameplay(int order = ServiceDomainOrder.Gameplay)
=> World.EnsureGameplay(order);
public static bool TryGetGameplay(out ServiceScope scope)
{
if (_world == null)
{
service = null;
return false;
}
return _world.App.TryGet(out service);
if (_world == null) { scope = null; return false; }
return _world.TryGetGameplay(out scope);
}
public static T RequireApp<T>() where T : class, IService
=> RequireWorld().App.Require<T>();
public static bool DestroyGameplay()
=> _world != null && _world.DestroyGameplay();
public static bool TryGet<T>(out T service) where T : class, IService
{
if (_world == null)
{
service = null;
return false;
}
if (_world == null) { service = null; return false; }
return _world.TryGet(out service);
}
public static T Require<T>() where T : class, IService
=> RequireWorld().Require<T>();
internal static ServiceScope EnsureScene(int order = ServiceDomainOrder.Scene)
=> RequireWorld().EnsureScene(order);
internal static bool TryGetScene(out ServiceScope scope)
{
if (_world == null)
{
scope = null;
return false;
}
return _world.TryGetScene(out scope);
}
internal static ServiceScope ResetScene(int order = ServiceDomainOrder.Scene)
=> RequireWorld().ResetScene(order);
internal static bool DestroyScene()
=> _world != null && _world.DestroyScene();
internal static ServiceScope EnsureGameplay(int order = ServiceDomainOrder.Gameplay)
=> RequireWorld().EnsureGameplay(order);
internal static bool TryGetGameplay(out ServiceScope scope)
{
if (_world == null)
{
scope = null;
return false;
}
return _world.TryGetGameplay(out scope);
}
internal static bool DestroyGameplay()
=> _world != null && _world.DestroyGameplay();
=> World.Require<T>();
public static void Shutdown()
{

View File

@ -2,5 +2,7 @@ namespace AlicizaX
{
public interface IService
{
void Initialize(ServiceContext context);
void Destroy();
}
}

View File

@ -1,11 +0,0 @@
using System;
namespace AlicizaX
{
public interface IServiceRegistry
{
T Register<T>(T service, params Type[] extraContracts) where T : class, IService;
bool TryGet<T>(out T service) where T : class, IService;
T Require<T>() where T : class, IService;
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d190bfd76bea7644b922ec06f1be6b26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,18 +1,16 @@
namespace AlicizaX
{
internal interface IServiceLifecycle
public abstract class ServiceBase : IService
{
void Initialize(ServiceContext context);
void Destroy();
}
public ServiceContext Context { get; private set; }
public abstract class ServiceBase : IService, IServiceLifecycle
{
protected ServiceContext Context { get; private set; }
public bool IsInitialized { get; private set; }
protected bool IsInitialized { get; private set; }
protected ServiceWorld World => Context.World;
void IServiceLifecycle.Initialize(ServiceContext context)
protected ServiceScope Scope => Context.Scope;
void IService.Initialize(ServiceContext context)
{
if (IsInitialized)
throw new System.InvalidOperationException($"{GetType().FullName} is already initialized.");
@ -22,7 +20,7 @@ namespace AlicizaX
OnInitialize();
}
void IServiceLifecycle.Destroy()
void IService.Destroy()
{
if (!IsInitialized) return;

View File

@ -2,16 +2,27 @@ namespace AlicizaX
{
public readonly struct ServiceContext
{
internal ServiceContext(ServiceWorld world, ServiceScope scope)
public ServiceContext(ServiceWorld world, ServiceScope scope)
{
World = world;
Scope = scope;
}
internal ServiceWorld World { get; }
public ServiceWorld World { get; }
internal ServiceScope Scope { get; }
public ServiceScope Scope { get; }
public ServiceScope App => World.App;
public ServiceScope AppScope => App;
public bool HasScene => World.HasScene;
public bool HasGameplay => World.HasGameplay;
public ServiceScope Scene => World.Scene;
public ServiceScope Gameplay => World.Gameplay;
public T Require<T>() where T : class, IService
=> World.Require<T>(Scope);
@ -19,28 +30,28 @@ namespace AlicizaX
public bool TryGet<T>(out T service) where T : class, IService
=> World.TryGet(Scope, out service);
internal ServiceScope EnsureScene(int order = ServiceDomainOrder.Scene)
public ServiceScope EnsureScene(int order = ServiceDomainOrder.Scene)
=> World.EnsureScene(order);
internal bool TryGetScene(out ServiceScope scope)
public bool TryGetScene(out ServiceScope scope)
=> World.TryGetScene(out scope);
internal ServiceScope ResetScene(int order = ServiceDomainOrder.Scene)
public ServiceScope ResetScene(int order = ServiceDomainOrder.Scene)
=> World.ResetScene(order);
internal ServiceScope EnsureGameplay(int order = ServiceDomainOrder.Gameplay)
public ServiceScope EnsureGameplay(int order = ServiceDomainOrder.Gameplay)
=> World.EnsureGameplay(order);
internal bool TryGetGameplay(out ServiceScope scope)
public bool TryGetGameplay(out ServiceScope scope)
=> World.TryGetGameplay(out scope);
public T RequireApp<T>() where T : class, IService
=> World.App.Require<T>();
=> App.Require<T>();
public T RequireScene<T>() where T : class, IService
=> World.Scene.Require<T>();
=> Scene.Require<T>();
public T RequireGameplay<T>() where T : class, IService
=> World.Gameplay.Require<T>();
=> Gameplay.Require<T>();
}
}

View File

@ -8,13 +8,11 @@ namespace AlicizaX
private static readonly HashSet<Type> ExcludedContracts = new HashSet<Type>
{
typeof(IService),
typeof(IMonoService),
typeof(IServiceTickable),
typeof(IServiceLateTickable),
typeof(IServiceFixedTickable),
typeof(IServiceGizmoDrawable),
typeof(IServiceOrder),
typeof(IServiceLifecycle),
};
// Cache for the common no-extraContracts path — contracts per concrete type never change.

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace AlicizaX
{
internal sealed class ServiceScope : IDisposable, IServiceRegistry
public sealed class ServiceScope : IDisposable
{
private readonly Dictionary<Type, IService> _servicesByContract = new Dictionary<Type, IService>();
private readonly Dictionary<IService, List<Type>> _contractsByService = new Dictionary<IService, List<Type>>(ReferenceComparer<IService>.Instance);
@ -31,13 +31,13 @@ namespace AlicizaX
Order = order;
}
internal ServiceWorld World { get; }
public ServiceWorld World { get; }
public string Name { get; }
internal int Order { get; }
public int Order { get; }
internal bool IsDisposed { get; private set; }
public bool IsDisposed { get; private set; }
public T Register<T>(T service, params Type[] extraContracts)
where T : class, IService
@ -47,9 +47,6 @@ namespace AlicizaX
if (service == null)
throw new ArgumentNullException(nameof(service));
if (service is not IServiceLifecycle lifecycle)
throw new InvalidOperationException($"Service {service.GetType().FullName} must implement {nameof(IServiceLifecycle)}.");
ValidateService(service);
if (_contractsByService.ContainsKey(service))
@ -73,7 +70,7 @@ namespace AlicizaX
try
{
lifecycle.Initialize(new ServiceContext(World, this));
service.Initialize(new ServiceContext(World, this));
AddToLifecycleLists(service);
}
catch
@ -97,12 +94,9 @@ namespace AlicizaX
if (service == null || !_contractsByService.ContainsKey(service))
return false;
if (service is not IServiceLifecycle lifecycle)
throw new InvalidOperationException($"Service {service.GetType().FullName} must implement {nameof(IServiceLifecycle)}.");
RemoveFromLifecycleLists(service);
RemoveBindings(service);
lifecycle.Destroy();
service.Destroy();
return true;
}
@ -161,11 +155,9 @@ namespace AlicizaX
{
var service = snapshot[i];
if (!_contractsByService.ContainsKey(service)) continue;
if (service is not IServiceLifecycle lifecycle)
throw new InvalidOperationException($"Service {service.GetType().FullName} must implement {nameof(IServiceLifecycle)}.");
RemoveFromLifecycleLists(service);
RemoveContractBindings(service); // skip _registrationOrder.Remove — we clear below
lifecycle.Destroy();
service.Destroy();
}
_registrationOrder.Clear();

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace AlicizaX
{
internal sealed class ServiceWorld : IDisposable
public sealed class ServiceWorld : IDisposable
{
private readonly List<ServiceScope> _scopes = new List<ServiceScope>();
private readonly Dictionary<Type, ServiceScope> _scopesByType = new Dictionary<Type, ServiceScope>();
@ -13,18 +13,20 @@ namespace AlicizaX
private ServiceScope _sceneScope;
private ServiceScope _gameplayScope;
internal ServiceWorld(int appScopeOrder = ServiceDomainOrder.App)
public ServiceWorld(int appScopeOrder = ServiceDomainOrder.App)
{
App = CreateScopeInternal(typeof(AppScope), nameof(App), appScopeOrder);
App = CreateScopeInternal(typeof(AppScope), nameof(AppScope), appScopeOrder);
}
internal ServiceScope App { get; }
public ServiceScope App { get; }
internal bool HasScene => _sceneScope != null && !_sceneScope.IsDisposed;
public ServiceScope AppScope => App;
internal bool HasGameplay => _gameplayScope != null && !_gameplayScope.IsDisposed;
public bool HasScene => _sceneScope != null && !_sceneScope.IsDisposed;
internal ServiceScope Scene
public bool HasGameplay => _gameplayScope != null && !_gameplayScope.IsDisposed;
public ServiceScope Scene
{
get
{
@ -34,7 +36,7 @@ namespace AlicizaX
}
}
internal ServiceScope Gameplay
public ServiceScope Gameplay
{
get
{
@ -44,24 +46,24 @@ namespace AlicizaX
}
}
internal ServiceScope EnsureScene(int order = ServiceDomainOrder.Scene)
public ServiceScope EnsureScene(int order = ServiceDomainOrder.Scene)
=> _sceneScope is { IsDisposed: false }
? _sceneScope
: _sceneScope = CreateScopeInternal(typeof(SceneScope), nameof(SceneScope), order);
internal bool TryGetScene(out ServiceScope scope)
public bool TryGetScene(out ServiceScope scope)
{
scope = HasScene ? _sceneScope : null;
return scope != null;
}
internal ServiceScope ResetScene(int order = ServiceDomainOrder.Scene)
public ServiceScope ResetScene(int order = ServiceDomainOrder.Scene)
{
DestroyScene();
return EnsureScene(order);
}
internal bool DestroyScene()
public bool DestroyScene()
{
if (!HasScene)
return false;
@ -71,18 +73,18 @@ namespace AlicizaX
return DestroyScope(scope, typeof(SceneScope));
}
internal ServiceScope EnsureGameplay(int order = ServiceDomainOrder.Gameplay)
public ServiceScope EnsureGameplay(int order = ServiceDomainOrder.Gameplay)
=> _gameplayScope is { IsDisposed: false }
? _gameplayScope
: _gameplayScope = CreateScopeInternal(typeof(GameplayScope), nameof(GameplayScope), order);
internal bool TryGetGameplay(out ServiceScope scope)
public bool TryGetGameplay(out ServiceScope scope)
{
scope = HasGameplay ? _gameplayScope : null;
return scope != null;
}
internal bool DestroyGameplay()
public bool DestroyGameplay()
{
if (!HasGameplay)
return false;
@ -92,10 +94,10 @@ namespace AlicizaX
return DestroyScope(scope, typeof(GameplayScope));
}
internal bool TryGet<T>(out T service) where T : class, IService
public bool TryGet<T>(out T service) where T : class, IService
=> TryGet(null, out service);
internal bool TryGet<T>(ServiceScope preferredScope, out T service) where T : class, IService
public bool TryGet<T>(ServiceScope preferredScope, out T service) where T : class, IService
{
if (preferredScope != null && !preferredScope.IsDisposed && preferredScope.TryGet(out service))
return true;
@ -112,33 +114,33 @@ namespace AlicizaX
return false;
}
internal T Require<T>() where T : class, IService => Require<T>(null);
public T Require<T>() where T : class, IService => Require<T>(null);
internal T Require<T>(ServiceScope preferredScope) where T : class, IService
public T Require<T>(ServiceScope preferredScope) where T : class, IService
{
if (TryGet(preferredScope, out T service)) return service;
throw new InvalidOperationException($"Service {typeof(T).FullName} was not found in any active scope.");
}
internal void Tick(float deltaTime)
public void Tick(float deltaTime)
{
var snapshot = GetScopeSnapshot();
for (var i = 0; i < snapshot.Length; i++) snapshot[i].Tick(deltaTime);
}
internal void LateTick(float deltaTime)
public void LateTick(float deltaTime)
{
var snapshot = GetScopeSnapshot();
for (var i = 0; i < snapshot.Length; i++) snapshot[i].LateTick(deltaTime);
}
internal void FixedTick(float fixedDeltaTime)
public void FixedTick(float fixedDeltaTime)
{
var snapshot = GetScopeSnapshot();
for (var i = 0; i < snapshot.Length; i++) snapshot[i].FixedTick(fixedDeltaTime);
}
internal void DrawGizmos()
public void DrawGizmos()
{
var snapshot = GetScopeSnapshot();
for (var i = 0; i < snapshot.Length; i++) snapshot[i].DrawGizmos();

View File

@ -37,22 +37,22 @@ namespace AlicizaX
protected virtual void Update()
{
if (AppServices.HasWorld) AppServices.RequireWorld().Tick(Time.deltaTime);
if (AppServices.HasWorld) AppServices.World.Tick(Time.deltaTime);
}
protected virtual void LateUpdate()
{
if (AppServices.HasWorld) AppServices.RequireWorld().LateTick(Time.deltaTime);
if (AppServices.HasWorld) AppServices.World.LateTick(Time.deltaTime);
}
protected virtual void FixedUpdate()
{
if (AppServices.HasWorld) AppServices.RequireWorld().FixedTick(Time.fixedDeltaTime);
if (AppServices.HasWorld) AppServices.World.FixedTick(Time.fixedDeltaTime);
}
protected virtual void OnDrawGizmos()
{
if (AppServices.HasWorld) AppServices.RequireWorld().DrawGizmos();
if (AppServices.HasWorld) AppServices.World.DrawGizmos();
}
protected virtual async void OnDestroy()
@ -68,6 +68,6 @@ namespace AlicizaX
}
protected virtual void RegisterAppServices(IServiceRegistry appServices) { }
protected virtual void RegisterAppServices(ServiceScope appScope) { }
}
}

View File

@ -2,13 +2,17 @@ using UnityEngine;
namespace AlicizaX
{
public abstract class MonoServiceBehaviour : MonoBehaviour, IMonoService, IServiceLifecycle
public abstract class MonoServiceBehaviour : MonoBehaviour, IMonoService
{
protected ServiceContext Context { get; private set; }
public ServiceContext Context { get; private set; }
protected bool IsInitialized { get; private set; }
public bool IsInitialized { get; private set; }
void IServiceLifecycle.Initialize(ServiceContext context)
protected ServiceWorld World => Context.World;
protected ServiceScope Scope => Context.Scope;
void IService.Initialize(ServiceContext context)
{
if (IsInitialized)
throw new System.InvalidOperationException($"{GetType().FullName} is already initialized.");
@ -18,7 +22,7 @@ namespace AlicizaX
OnInitialize();
}
void IServiceLifecycle.Destroy()
void IService.Destroy()
{
if (!IsInitialized) return;
@ -70,7 +74,7 @@ namespace AlicizaX
private static ServiceScope ResolveOrCreateScope()
{
if (typeof(TScope) == typeof(AppScope))
return AppServices.RequireWorld().App;
return AppServices.App;
if (typeof(TScope) == typeof(SceneScope))
return AppServices.EnsureScene();
@ -85,7 +89,7 @@ namespace AlicizaX
{
if (typeof(TScope) == typeof(AppScope))
{
scope = AppServices.RequireWorld().App;
scope = AppServices.App;
return true;
}

View File

@ -42,7 +42,7 @@ namespace AlicizaX.ObjectPool
/// <summary>
/// 对象池管理器。
/// </summary>
public interface IObjectPoolService : IService
public interface IObjectPoolService : IService, IServiceTickable
{
int Count { get; }

View File

@ -4,14 +4,14 @@ using UnityEngine;
namespace AlicizaX
{
/// <summary>
/// 对象池组件。
/// 对象池组件。
/// </summary>
public sealed class ObjectPoolComponent : MonoBehaviour
{
private IObjectPoolService _mObjectPoolService = null;
/// <summary>
/// 获取对象池数量。
/// 获取对象池数量。
/// </summary>
public int Count
{
@ -20,7 +20,7 @@ namespace AlicizaX
private void Awake()
{
_mObjectPoolService = AppServices.RegisterApp(new ObjectPoolService());
_mObjectPoolService = AppServices.App.Register(new ObjectPoolService());
}
private void OnDestroy()
@ -29,10 +29,10 @@ namespace AlicizaX
}
/// <summary>
/// 获取所有对象池。
/// 获取所有对象池。
/// </summary>
/// <param name="sort">是否根据对象池的优先级排序。</param>
/// <returns>所有对象池。</returns>
/// <param name="sort">是否根据对象池的优先级排序。</param>
/// <returns>所有对象池。</returns>
public ObjectPoolBase[] GetAllObjectPools(bool sort)
{
return _mObjectPoolService.GetAllObjectPools(sort);

View File

@ -9,7 +9,7 @@ namespace AlicizaX.ObjectPool
/// 对象池管理器。
/// </summary>
[UnityEngine.Scripting.Preserve]
internal sealed partial class ObjectPoolService : ServiceBase, IObjectPoolService, IServiceTickable
internal sealed partial class ObjectPoolService : ServiceBase, IObjectPoolService
{
private const int DefaultCapacity = int.MaxValue;
private const float DefaultExpireTime = float.MaxValue;

View File

@ -77,7 +77,7 @@ namespace AlicizaX
catch (UnityWebRequestException e)
{
HandleRequestError(request, url);
return e.Message;
return string.Empty;
}
}

View File

@ -81,9 +81,9 @@ namespace AlicizaX
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
return;
#endif
Application.Quit();
}
#if UNITY_IOS
@ -98,7 +98,9 @@ namespace AlicizaX
{
#if UNITY_EDITOR
Application.OpenURL(url);
#elif UNITY_IOS
return;
#endif
#if UNITY_IOS
open_url(url);
#else
Application.OpenURL(url);

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
@ -286,7 +286,7 @@ namespace AlicizaX
return;
}
_loopService = AppServices.RegisterApp(new UtilityLoopService());
_loopService = AppServices.App.Register(new UtilityLoopService());
}
private static UtilityLoopService EnsureLoopService()

View File

@ -5,9 +5,9 @@ using UnityEngine.Audio;
namespace AlicizaX.Audio.Runtime
{
/// <summary>
/// 音效管理,为游戏提供统一的音效播放接口。
/// 音效管理,为游戏提供统一的音效播放接口。
/// </summary>
/// <remarks>场景3D音效挂到场景物件、技能3D音效挂到技能特效上并在AudioSource的Output上设置对应分类的AudioMixerGroup</remarks>
/// <remarks>场景3D音效挂到场景物件、技能3D音效挂到技能特效上并在AudioSource的Output上设置对应分类的AudioMixerGroup</remarks>
[DisallowMultipleComponent]
[AddComponentMenu("Game Framework/Audio")]
public sealed class AudioComponent : MonoBehaviour
@ -22,11 +22,11 @@ namespace AlicizaX.Audio.Runtime
private void Awake()
{
_audioService = AppServices.RegisterApp(new AudioService());
_audioService = AppServices.App.Register(new AudioService());
}
/// <summary>
/// 初始化音频模块。
/// 初始化音频模块。
/// </summary>
void Start()
{

View File

@ -12,7 +12,7 @@ using AudioType = AlicizaX.Audio.Runtime.AudioType;
namespace AlicizaX.Audio.Runtime
{
internal class AudioService : ServiceBase, IAudioService, IServiceTickable
internal class AudioService : ServiceBase, IAudioService
{
public const string MUSIC_VOLUME_NAME = "MusicVolume";
public const string UI_SOUND_VOLUME_NAME = "UISoundVolume";

View File

@ -6,7 +6,7 @@ using YooAsset;
namespace AlicizaX.Audio.Runtime
{
public interface IAudioService : IService
public interface IAudioService:IService, IServiceTickable
{
/// <summary>
/// 总音量控制。

View File

@ -6,7 +6,7 @@ using Object = UnityEngine.Object;
namespace AlicizaX.Debugger.Runtime
{
/// <summary>
/// 璋冭瘯鍣ㄧ粍浠躲€?
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞嗚<EFBFBD>?
/// </summary>
[DisallowMultipleComponent]
[AddComponentMenu("Game Framework/Debugger")]
@ -28,17 +28,17 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 榛樿璋冭瘯鍣ㄦ紓娴澶у皬銆?
/// 暺䁅恕靚<EFBFBD><EFBFBD><EFBFBD><EFBFBD>瘚格<EFBFBD>憭批<EFBFBD><EFBFBD>?
/// </summary>
internal static readonly Rect DefaultIconRect = new Rect(10f, 10f, 60f, 60f);
/// <summary>
/// 榛樿璋冭瘯鍣ㄧ獥鍙eぇ灏忋€?
/// 暺䁅恕靚<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>之撠譌<EFBFBD>?
/// </summary>
internal static readonly Rect DefaultWindowRect = new Rect(10f, 10f, 640f, 480f);
/// <summary>
/// 榛樿璋冭瘯鍣ㄧ獥鍙g缉鏀炬瘮渚嬨€?
/// 暺䁅恕靚<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>靘卝<EFBFBD>?
/// </summary>
internal static readonly float DefaultWindowScale = 1f;
@ -95,7 +95,7 @@ namespace AlicizaX.Debugger.Runtime
private FpsCounter m_FpsCounter = null;
/// <summary>
/// 鑾峰彇鎴栬缃皟璇曞櫒绐楀彛鏄惁婵€娲汇€?
/// <EFBFBD><EFBFBD><EFBFBD>𤥁挽蝵株<EFBFBD>霂訫膥蝒堒藁<EFBFBD>臬炏瞈<EFBFBD>瘣颯<EFBFBD>?
/// </summary>
public bool ActiveWindow
{
@ -108,7 +108,7 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 鑾峰彇鎴栬缃槸鍚︽樉绀哄畬鏁磋皟璇曞櫒鐣岄潰銆?
/// <EFBFBD><EFBFBD><EFBFBD>𤥁挽蝵格糓<EFBFBD>行遬蝷箏<EFBFBD><EFBFBD><EFBFBD>霂訫膥<EFBFBD>屸𢒰<EFBFBD>?
/// </summary>
public bool ShowFullWindow
{
@ -117,7 +117,7 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 鑾峰彇鎴栬缃皟璇曞櫒婕傛诞妗嗗ぇ灏忋€?
/// <EFBFBD><EFBFBD><EFBFBD>𤥁挽蝵株<EFBFBD>霂訫膥瞍<EFBFBD>筑獢<EFBFBD>之撠譌<EFBFBD>?
/// </summary>
public Rect IconRect
{
@ -126,7 +126,7 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 鑾峰彇鎴栬缃皟璇曞櫒绐楀彛澶у皬銆?
/// <EFBFBD><EFBFBD><EFBFBD>𤥁挽蝵株<EFBFBD>霂訫膥蝒堒藁憭批<EFBFBD><EFBFBD>?
/// </summary>
public Rect WindowRect
{
@ -135,7 +135,7 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 鑾峰彇鎴栬缃皟璇曞櫒绐楀彛缂╂斁姣斾緥銆?
/// <EFBFBD><EFBFBD><EFBFBD>𤥁挽蝵株<EFBFBD>霂訫膥蝒堒藁蝻拇𦆮瘥𥪯<EFBFBD><EFBFBD>?
/// </summary>
public float WindowScale
{
@ -144,12 +144,12 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 娓告垙妗嗘灦缁勪欢鍒濆鍖栥€?
/// 皜豢<EFBFBD><EFBFBD>沲蝏<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
/// </summary>
private void Awake()
{
_instance = this;
_mDebuggerService = AppServices.RegisterApp(new DebuggerService());
_mDebuggerService = AppServices.App.Register(new DebuggerService());
if (_mDebuggerService == null)
{
Log.Error("Debugger manager is invalid.");
@ -256,48 +256,48 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 娉ㄥ唽璋冭瘯鍣ㄧ獥鍙c€?
/// 瘜典<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
/// </summary>
/// <param name="path">璋冭瘯鍣ㄧ獥鍙h矾寰勩€?/param>
/// <param name="debuggerWindow">瑕佹敞鍐岀殑璋冭瘯鍣ㄧ獥鍙c€?/param>
/// <param name="args">鍒濆鍖栬皟璇曞櫒绐楀彛鍙傛暟銆?/param>
/// <param name="path"><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>楝敺<EFBFBD><EFBFBD>?/param>
/// <param name="debuggerWindow"><EFBFBD><EFBFBD>𣬚<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/param>
/// <param name="args"><EFBFBD><EFBFBD><EFBFBD>𤥁<EFBFBD>霂訫膥蝒堒藁<EFBFBD><EFBFBD><EFBFBD>?/param>
public void RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow, params object[] args)
{
_mDebuggerService.RegisterDebuggerWindow(path, debuggerWindow, args);
}
/// <summary>
/// 瑙i櫎娉ㄥ唽璋冭瘯鍣ㄧ獥鍙c€?
/// <EFBFBD>膄瘜典<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
/// </summary>
/// <param name="path">璋冭瘯鍣ㄧ獥鍙h矾寰勩€?/param>
/// <returns>鏄惁瑙i櫎娉ㄥ唽璋冭瘯鍣ㄧ獥鍙f垚鍔熴€?/returns>
/// <param name="path"><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>楝敺<EFBFBD><EFBFBD>?/param>
/// <returns><EFBFBD>臬炏閫<EFBFBD>膄瘜典<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/returns>
public bool UnregisterDebuggerWindow(string path)
{
return _mDebuggerService.UnregisterDebuggerWindow(path);
}
/// <summary>
/// 鑾峰彇璋冭瘯鍣ㄧ獥鍙c€?
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
/// </summary>
/// <param name="path">璋冭瘯鍣ㄧ獥鍙h矾寰勩€?/param>
/// <returns>瑕佽幏鍙栫殑璋冭瘯鍣ㄧ獥鍙c€?/returns>
/// <param name="path"><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>楝敺<EFBFBD><EFBFBD>?/param>
/// <returns><EFBFBD><EFBFBD>𣇉<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/returns>
public IDebuggerWindow GetDebuggerWindow(string path)
{
return _mDebuggerService.GetDebuggerWindow(path);
}
/// <summary>
/// 閫変腑璋冭瘯鍣ㄧ獥鍙c€?
/// <EFBFBD>劐葉靚<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
/// </summary>
/// <param name="path">璋冭瘯鍣ㄧ獥鍙h矾寰勩€?/param>
/// <returns>鏄惁鎴愬姛閫変腑璋冭瘯鍣ㄧ獥鍙c€?/returns>
/// <param name="path"><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>楝敺<EFBFBD><EFBFBD>?/param>
/// <returns><EFBFBD>臬炏<EFBFBD>𣂼<EFBFBD><EFBFBD>劐葉靚<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/returns>
public bool SelectDebuggerWindow(string path)
{
return _mDebuggerService.SelectDebuggerWindow(path);
}
/// <summary>
/// 杩樺師璋冭瘯鍣ㄧ獥鍙e竷灞€銆?
/// 餈睃<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
/// </summary>
public void ResetLayout()
{
@ -307,19 +307,19 @@ namespace AlicizaX.Debugger.Runtime
}
/// <summary>
/// 鑾峰彇璁板綍鐨勬墍鏈夋棩蹇椼€?
/// <EFBFBD><EFBFBD>霈啣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㗇𠯫敹𨰜<EFBFBD>?
/// </summary>
/// <param name="results">瑕佽幏鍙栫殑鏃ュ織銆?/param>
/// <param name="results"><EFBFBD><EFBFBD>𣇉<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/param>
public void GetRecentLogs(List<LogNode> results)
{
m_ConsoleWindow.GetRecentLogs(results);
}
/// <summary>
/// 鑾峰彇璁板綍鐨勬渶杩戞棩蹇椼€?
/// <EFBFBD><EFBFBD>霈啣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>餈烐𠯫敹𨰜<EFBFBD>?
/// </summary>
/// <param name="results">瑕佽幏鍙栫殑鏃ュ織銆?/param>
/// <param name="count">瑕佽幏鍙栨渶杩戞棩蹇楃殑鏁伴噺銆?/param>
/// <param name="results"><EFBFBD><EFBFBD>𣇉<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/param>
/// <param name="count"><EFBFBD><EFBFBD>𡝗<EFBFBD>餈烐𠯫敹㛖<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?/param>
public void GetRecentLogs(List<LogNode> results, int count)
{
m_ConsoleWindow.GetRecentLogs(results, count);

View File

@ -7,7 +7,7 @@ namespace AlicizaX.Debugger.Runtime
/// 调试器管理器。
/// </summary>
[UnityEngine.Scripting.Preserve]
internal sealed partial class DebuggerService : ServiceBase, IDebuggerService, IServiceTickable
internal sealed partial class DebuggerService : ServiceBase, IDebuggerService
{
private readonly DebuggerWindowGroup m_DebuggerWindowRoot;
private bool m_ActiveWindow;

View File

@ -6,7 +6,7 @@ using AlicizaX;
namespace AlicizaX.Debugger.Runtime
{
/// <summary>调试器管理器接口。</summary>
public interface IDebuggerService : IService
public interface IDebuggerService:IService, IServiceTickable
{
/// <summary>获取或设置调试器窗口是否激活。</summary>
bool ActiveWindow { get; set; }

View File

@ -23,7 +23,7 @@ public static partial class GameApp
{
if (_audio == null)
{
_audio = AppServices.RequireApp<IAudioService>();
_audio = AppServices.App.Require<IAudioService>();
}
return _audio;
@ -42,7 +42,7 @@ public static partial class GameApp
{
if (_localization == null)
{
_localization = AppServices.RequireApp<ILocalizationService>();
_localization = AppServices.App.Require<ILocalizationService>();
}
return _localization;
@ -60,7 +60,7 @@ public static partial class GameApp
{
if (_objectPool == null)
{
_objectPool = AppServices.RequireApp<IObjectPoolService>();
_objectPool = AppServices.App.Require<IObjectPoolService>();
}
return _objectPool;
@ -79,7 +79,7 @@ public static partial class GameApp
{
if (_procedure == null)
{
_procedure = AppServices.RequireApp<IProcedureService>();
_procedure = AppServices.App.Require<IProcedureService>();
}
return _procedure;
@ -98,7 +98,7 @@ public static partial class GameApp
{
if (_resource == null)
{
_resource = AppServices.RequireApp<IResourceService>();
_resource = AppServices.App.Require<IResourceService>();
}
return _resource;
@ -116,7 +116,7 @@ public static partial class GameApp
{
if (_scene == null)
{
_scene = AppServices.RequireApp<ISceneService>();
_scene = AppServices.App.Require<ISceneService>();
}
return _scene;
@ -134,7 +134,7 @@ public static partial class GameApp
{
if (_timer == null)
{
_timer = AppServices.RequireApp<ITimerService>();
_timer = AppServices.App.Require<ITimerService>();
}
return _timer;
@ -153,7 +153,7 @@ public static partial class GameApp
{
if (_ui == null)
{
_ui = AppServices.RequireApp<IUIService>();
_ui = AppServices.App.Require<IUIService>();
}
return _ui;

View File

@ -53,9 +53,9 @@ namespace AlicizaX.Localization.Runtime
private void Start()
{
if (!AppServices.TryGetApp<ILocalizationService>(out _mLocalizationService))
if (!AppServices.App.TryGet<ILocalizationService>(out _mLocalizationService))
{
_mLocalizationService = AppServices.RegisterApp(new LocalizationService());
_mLocalizationService = AppServices.App.Register(new LocalizationService());
}
if (_mLocalizationService == null)

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace AlicizaX
{
public interface IProcedureService : IService
public interface IProcedureService : IService, IServiceTickable
{
Type CurrentProcedureType { get; }
void InitializeProcedure(IEnumerable<IProcedure> availableProcedures, Type defaultProcedureType);

View File

@ -8,7 +8,7 @@ namespace AlicizaX
{
private void Awake()
{
AppServices.RegisterApp(new ProcedureService());
AppServices.App.Register(new ProcedureService());
}
}
}

View File

@ -4,7 +4,7 @@ using UnityEngine;
namespace AlicizaX
{
internal class ProcedureService : ServiceBase, IProcedureService, IServiceTickable
internal class ProcedureService : ServiceBase, IProcedureService
{
private readonly Dictionary<Type, IProcedure> _procedures = new Dictionary<Type, IProcedure>();
private IProcedure _currentProcedure;

View File

@ -6,6 +6,9 @@ using YooAsset;
namespace AlicizaX.Resource.Runtime
{
/// <summary>
/// 资源组件<E7BB84>?
/// </summary>
[DisallowMultipleComponent]
public class ResourceComponent : MonoBehaviour
{
@ -37,14 +40,26 @@ namespace AlicizaX.Resource.Runtime
[SerializeField] private string decryptionServices = "";
/// <summary>
/// 自动释放资源引用计数<E8AEA1>?的资源包
/// </summary>
[SerializeField] public bool autoUnloadBundleWhenUnused = false;
[SerializeField] private EPlayMode _playMode = EPlayMode.EditorSimulateMode;
/// <summary>
/// 当前最新的包裹版本<E78988>?
/// </summary>
public string PackageVersion { set; get; }
/// <summary>
/// 资源包名称<E5908D>?
/// </summary>
[SerializeField] private string packageName = "DefaultPackage";
/// <summary>
/// 资源包名称<E5908D>?
/// </summary>
public string PackageName
{
get => packageName;
@ -52,11 +67,16 @@ namespace AlicizaX.Resource.Runtime
}
/// <summary>
/// 设置异步系统参数,每帧执行消耗的最大时间切片(单位:毫秒)
/// </summary>
[SerializeField] public long milliseconds = 30;
public int downloadingMaxNum = 10;
/// <summary>
/// 获取或设置同时最大下载数目<E695B0>?
/// </summary>
public int DownloadingMaxNum
{
get => downloadingMaxNum;
@ -71,31 +91,46 @@ namespace AlicizaX.Resource.Runtime
set => failedTryAgain = value;
}
/// <summary>
/// 获取当前资源适用的游戏版本号<E69CAC>?
/// </summary>
public string ApplicableGameVersion => _resourceService.ApplicableGameVersion;
/// <summary>
/// 获取当前内部资源版本号<E69CAC>?
/// </summary>
public int InternalResourceVersion => _resourceService.InternalResourceVersion;
/// <summary>
/// 获取或设置无用资源释放的最小间隔时间以秒为单位<E58D95>?
/// </summary>
public float MinUnloadUnusedAssetsInterval
{
get => minUnloadUnusedAssetsInterval;
set => minUnloadUnusedAssetsInterval = value;
}
/// <summary>
/// 获取或设置无用资源释放的最大间隔时间以秒为单位<E58D95>?
/// </summary>
public float MaxUnloadUnusedAssetsInterval
{
get => maxUnloadUnusedAssetsInterval;
set => maxUnloadUnusedAssetsInterval = value;
}
/// <summary>
/// 使用系统释放无用资源策略<E7AD96>?
/// </summary>
public bool UseSystemUnloadUnusedAssets
{
get => useSystemUnloadUnusedAssets;
set => useSystemUnloadUnusedAssets = value;
}
/// <summary>
/// 获取无用资源释放的等待时长以秒为单位<E58D95>?
/// </summary>
public float LastUnloadUnusedAssetsOperationElapseSeconds => _lastUnloadUnusedAssetsOperationElapseSeconds;
[SerializeField] private float assetAutoReleaseInterval = 60f;
@ -106,28 +141,36 @@ namespace AlicizaX.Resource.Runtime
[SerializeField] private int assetPriority = 0;
/// <summary>
/// 获取或设置资源对象池自动释放可释放对象的间隔秒数<E7A792>?
/// </summary>
public float AssetAutoReleaseInterval
{
get => _resourceService.AssetAutoReleaseInterval;
set => _resourceService.AssetAutoReleaseInterval = assetAutoReleaseInterval = value;
}
/// <summary>
/// 获取或设置资源对象池的容量<E5AEB9>?
/// </summary>
public int AssetCapacity
{
get => _resourceService.AssetCapacity;
set => _resourceService.AssetCapacity = assetCapacity = value;
}
/// <summary>
/// 获取或设置资源对象池对象过期秒数<E7A792>?
/// </summary>
public float AssetExpireTime
{
get => _resourceService.AssetExpireTime;
set => _resourceService.AssetExpireTime = assetExpireTime = value;
}
/// <summary>
/// 获取或设置资源对象池的优先级<E58588>?
/// </summary>
public int AssetPriority
{
get => _resourceService.AssetPriority;
@ -148,7 +191,7 @@ namespace AlicizaX.Resource.Runtime
private void Awake()
{
_resourceService = AppServices.RegisterApp(new ResourceService());
_resourceService = AppServices.App.Register(new ResourceService());
Application.lowMemory += OnLowMemory;
}
@ -173,7 +216,7 @@ namespace AlicizaX.Resource.Runtime
_resourceService.AssetExpireTime = assetExpireTime;
_resourceService.AssetPriority = assetPriority;
_resourceService.SetForceUnloadUnusedAssetsAction(ForceUnloadUnusedAssets);
Log.Info($"ResourceModule Run Mode {_playMode}");
Log.Info($"ResourceModule Run Mode{_playMode}");
}
private void OnApplicationQuit()
@ -181,8 +224,12 @@ namespace AlicizaX.Resource.Runtime
Application.lowMemory -= OnLowMemory;
}
#region
#region
/// <summary>
/// 强制执行释放未被使用的资源<E8B584>?
/// </summary>
/// <param name="performGCCollect">是否使用垃圾回收<E59B9E>?/param>
public void ForceUnloadUnusedAssets(bool performGCCollect)
{
_forceUnloadUnusedAssets = true;

View File

@ -37,6 +37,12 @@ namespace AlicizaX.Resource.Runtime
/// </summary>
public long Milliseconds { get; set; } = 30;
public int Priority
{
get => 2;
}
private string _applicableGameVersion;
private int _internalResourceVersion;

View File

@ -9,9 +9,9 @@ namespace AlicizaX.Scene.Runtime
{
private void Awake()
{
if (!AppServices.TryGetApp<ISceneService>(out _))
if (!AppServices.App.TryGet<ISceneService>(out _))
{
AppServices.RegisterApp(new SceneService());
AppServices.App.Register(new SceneService());
}
AppServices.EnsureScene();

View File

@ -3,7 +3,7 @@ using System;
namespace AlicizaX
{
[UnityEngine.Scripting.Preserve]
public interface ITimerService : IService
public interface ITimerService : IService, IServiceTickable
{
int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args);
int AddTimer(TimerHandlerNoArgs callback, float time, bool isLoop = false, bool isUnscaled = false);

View File

@ -10,7 +10,7 @@ namespace AlicizaX.Timer.Runtime
{
private void Awake()
{
AppServices.RegisterApp(new TimerService());
AppServices.App.Register(new TimerService());
}
}
}

View File

@ -77,7 +77,7 @@ namespace AlicizaX
[UnityEngine.Scripting.Preserve]
[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
internal sealed class TimerService : ServiceBase, ITimerService, IServiceTickable
internal sealed class TimerService : ServiceBase, ITimerService
{
private const float TimeWheelSlotInterval = 0.001f;

View File

@ -87,7 +87,6 @@ namespace AlicizaX.UI.Runtime
try
{
Type baseType = uiType;
#pragma warning disable CS8632
Type? holderType = null;
var genericArgs = baseType.GetGenericArguments();

View File

@ -9,7 +9,7 @@ namespace AlicizaX.UI.Runtime
/// UI 模块接口:负责 UI 的创建、显示、关闭与查询。
/// 支持异步与同步(预加载)两种打开方式。
/// </summary>
public interface IUIService : IService
public interface IUIService : IService, IServiceTickable
{
/// <summary>
/// 初始化 UI 模块。

View File

@ -7,8 +7,10 @@ using UnityEngine;
namespace AlicizaX.UI.Runtime
{
internal sealed partial class UIService : ServiceBase, IUIService, IServiceTickable
internal sealed partial class UIService : ServiceBase, IUIService
{
public int Priority { get; }
private ITimerService _timerService;
protected override void OnInitialize()

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
@ -29,7 +29,7 @@ namespace AlicizaX.UI.Runtime
private void Awake()
{
_uiService = AppServices.RegisterApp(new UIService());
_uiService = AppServices.App.Register(new UIService());
if (uiRoot == null)
{
throw new GameFrameworkException("UIRoot Prefab is invalid.");