diff --git a/Assets/GameScripts/HotFix/GameLogic/UI/Common/UIExtension.cs b/Assets/GameScripts/HotFix/GameLogic/UI/Common/UIExtension.cs index 18065b6b..d5cd9960 100644 --- a/Assets/GameScripts/HotFix/GameLogic/UI/Common/UIExtension.cs +++ b/Assets/GameScripts/HotFix/GameLogic/UI/Common/UIExtension.cs @@ -4,15 +4,6 @@ using UnityEngine; using UnityEngine.UI; using TEngine; -public enum EUIGroup -{ - Root, - UI, - Dialog, - Tips, - System -} - public static class UIExtension { #region SetActive diff --git a/Assets/TEngine/Runtime/GameFramework/GameFrameworkEntry.cs b/Assets/TEngine/Runtime/GameFramework/GameFrameworkEntry.cs index 7833c06a..ddad7a37 100644 --- a/Assets/TEngine/Runtime/GameFramework/GameFrameworkEntry.cs +++ b/Assets/TEngine/Runtime/GameFramework/GameFrameworkEntry.cs @@ -47,22 +47,18 @@ namespace TEngine /// 如果要获取的游戏框架模块不存在,则自动创建该游戏框架模块。 public static T GetModule() where T : class { - Type interfaceType = typeof(T); - if (!interfaceType.IsInterface) + Type module = typeof(T); + + if (module.FullName != null && !module.FullName.StartsWith("TEngine.", StringComparison.Ordinal)) { - throw new GameFrameworkException(Utility.Text.Format("You must get module by interface, but '{0}' is not.", interfaceType.FullName)); + throw new GameFrameworkException(Utility.Text.Format("You must get a Game Framework module, but '{0}' is not.", module.FullName)); } - if (!interfaceType.FullName.StartsWith("TEngine.", StringComparison.Ordinal)) - { - throw new GameFrameworkException(Utility.Text.Format("You must get a Game Framework module, but '{0}' is not.", interfaceType.FullName)); - } - - string moduleName = Utility.Text.Format("{0}.{1}", interfaceType.Namespace, interfaceType.Name.Substring(1)); + string moduleName = Utility.Text.Format("{0}.{1}", module.Namespace, module.Name.Substring(1)); Type moduleType = Type.GetType(moduleName); if (moduleType == null) { - moduleName = Utility.Text.Format("{0}.{1}", interfaceType.Namespace, interfaceType.Name); + moduleName = Utility.Text.Format("{0}.{1}", module.Namespace, module.Name); moduleType = Type.GetType(moduleName); if (moduleType == null) { diff --git a/Assets/TEngine/Runtime/GameFramework/Timer.meta b/Assets/TEngine/Runtime/GameFramework/Timer.meta new file mode 100644 index 00000000..82a8c33e --- /dev/null +++ b/Assets/TEngine/Runtime/GameFramework/Timer.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 555d657d6bb444a983750fb61876af89 +timeCreated: 1681822247 \ No newline at end of file diff --git a/Assets/TEngine/Runtime/GameFramework/Timer/Timer.meta b/Assets/TEngine/Runtime/GameFramework/Timer/Timer.meta new file mode 100644 index 00000000..1ec86396 --- /dev/null +++ b/Assets/TEngine/Runtime/GameFramework/Timer/Timer.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9d644fbcf0a6413da6f4d0c54724266a +timeCreated: 1681822257 \ No newline at end of file diff --git a/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerManager.cs b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerManager.cs new file mode 100644 index 00000000..083c7318 --- /dev/null +++ b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerManager.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections.Generic; + +namespace TEngine +{ + public delegate void TimerHandler(object[] args); + + internal class TimerManager : GameFrameworkModule + { + [Serializable] + public class Timer + { + public int timerId = 0; + public float curTime = 0; + public float time = 0; + public TimerHandler Handler; + public bool isLoop = false; + public bool isNeedRemove = false; + public bool isRunning = false; + public bool isUnscaled = false; //是否使用非缩放的时间 + public object[] Args = null; //回调参数 + } + + private int _curTimerId = 0; + private readonly List _timerList = new List(); + private readonly List _unscaledTimerList = new List(); + private readonly List _cacheRemoveTimers = new List(); + private readonly List _cacheRemoveUnscaledTimers = new List(); + + /// + /// 添加计时器 + /// + /// + /// + /// + /// + /// + /// + public int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args) + { + Timer timer = new Timer + { + timerId = ++_curTimerId, + curTime = time, + time = time, + Handler = callback, + isLoop = isLoop, + isUnscaled = isUnscaled, + Args = args, + isNeedRemove = false, + isRunning = true + }; + + InsertTimer(timer); + return timer.timerId; + } + + private void InsertTimer(Timer timer) + { + bool isInsert = false; + if (timer.isUnscaled) + { + for (int i = 0, len = _unscaledTimerList.Count; i < len; i++) + { + if (_unscaledTimerList[i].curTime > timer.curTime) + { + _unscaledTimerList.Insert(i, timer); + isInsert = true; + break; + } + } + + if (!isInsert) + { + _unscaledTimerList.Add(timer); + } + } + else + { + for (int i = 0, len = _timerList.Count; i < len; i++) + { + if (_timerList[i].curTime > timer.curTime) + { + _timerList.Insert(i, timer); + isInsert = true; + break; + } + } + + if (!isInsert) + { + _timerList.Add(timer); + } + } + } + + /// + /// 暂停计时 + /// + public void Stop(int timerId) + { + Timer timer = GetTimer(timerId); + if (timer != null) timer.isRunning = false; + } + + /// + /// 恢复计时 + /// + public void Resume(int timerId) + { + Timer timer = GetTimer(timerId); + if (timer != null) timer.isRunning = true; + } + + /// + /// 计时器是否在运行中 + /// + public bool IsRunning(int timerId) + { + Timer timer = GetTimer(timerId); + return timer is { isRunning: true }; + } + + /// + /// 获得计时器剩余时间 + /// + public float GetLeftTime(int timerId) + { + Timer timer = GetTimer(timerId); + if (timer == null) return 0; + return timer.curTime; + } + + /// + /// 重置计时器,恢复到开始状态 + /// + public void Restart(int timerId) + { + Timer timer = GetTimer(timerId); + if (timer != null) + { + timer.curTime = timer.time; + timer.isRunning = true; + } + } + + /// + /// 重置计时器 + /// + public void Reset(int timerId, TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false) + { + Timer timer = GetTimer(timerId); + if (timer != null) + { + timer.curTime = time; + timer.time = time; + timer.Handler = callback; + timer.isLoop = isLoop; + timer.isNeedRemove = false; + if (timer.isUnscaled != isUnscaled) + { + RemoveTimerImmediate(timerId); + + timer.isUnscaled = isUnscaled; + InsertTimer(timer); + } + } + } + + /// + /// 重置计时器 + /// + public void Reset(int timerId, float time, bool isLoop, bool isUnscaled) + { + Timer timer = GetTimer(timerId); + if (timer != null) + { + timer.curTime = time; + timer.time = time; + timer.isLoop = isLoop; + timer.isNeedRemove = false; + if (timer.isUnscaled != isUnscaled) + { + RemoveTimerImmediate(timerId); + + timer.isUnscaled = isUnscaled; + InsertTimer(timer); + } + } + } + + /// + /// 立即移除 + /// + /// + private void RemoveTimerImmediate(int timerId) + { + for (int i = 0, len = _timerList.Count; i < len; i++) + { + if (_timerList[i].timerId == timerId) + { + _timerList.RemoveAt(i); + return; + } + } + + for (int i = 0, len = _unscaledTimerList.Count; i < len; i++) + { + if (_unscaledTimerList[i].timerId == timerId) + { + _unscaledTimerList.RemoveAt(i); + return; + } + } + } + + /// + /// 移除计时器 + /// + /// + public void RemoveTimer(int timerId) + { + for (int i = 0, len = _timerList.Count; i < len; i++) + { + if (_timerList[i].timerId == timerId) + { + _timerList[i].isNeedRemove = true; + return; + } + } + + for (int i = 0, len = _unscaledTimerList.Count; i < len; i++) + { + if (_unscaledTimerList[i].timerId == timerId) + { + _unscaledTimerList[i].isNeedRemove = true; + return; + } + } + } + + /// + /// 移除所有计时器 + /// + public void RemoveAllTimer() + { + _timerList.Clear(); + _unscaledTimerList.Clear(); + } + + /// + /// 根据TimerId获取计时器 + /// + /// + /// + private Timer GetTimer(int timerId) + { + for (int i = 0, len = _timerList.Count; i < len; i++) + { + if (_timerList[i].timerId == timerId) + { + return _timerList[i]; + } + } + + for (int i = 0, len = _unscaledTimerList.Count; i < len; i++) + { + if (_unscaledTimerList[i].timerId == timerId) + { + return _unscaledTimerList[i]; + } + } + + return null; + } + + private void LoopCallInBadFrame() + { + bool isLoopCall = false; + for (int i = 0, len = _timerList.Count; i < len; i++) + { + Timer timer = _timerList[i]; + if (timer.isLoop && timer.curTime <= 0) + { + if (timer.Handler != null) + { + timer.Handler(timer.Args); + } + + timer.curTime += timer.time; + if (timer.curTime <= 0) + { + isLoopCall = true; + } + } + } + + if (isLoopCall) + { + LoopCallInBadFrame(); + } + } + + private void LoopCallUnscaledInBadFrame() + { + bool isLoopCall = false; + for (int i = 0, len = _unscaledTimerList.Count; i < len; i++) + { + Timer timer = _unscaledTimerList[i]; + if (timer.isLoop && timer.curTime <= 0) + { + if (timer.Handler != null) + { + timer.Handler(timer.Args); + } + + timer.curTime += timer.time; + if (timer.curTime <= 0) + { + isLoopCall = true; + } + } + } + + if (isLoopCall) + { + LoopCallUnscaledInBadFrame(); + } + } + + private void UpdateTimer(float elapseSeconds) + { + bool isLoopCall = false; + for (int i = 0, len = _timerList.Count; i < len; i++) + { + Timer timer = _timerList[i]; + if (timer.isNeedRemove) + { + _cacheRemoveTimers.Add(i); + continue; + } + + if (!timer.isRunning) continue; + timer.curTime -= elapseSeconds; + if (timer.curTime <= 0) + { + if (timer.Handler != null) + { + timer.Handler(timer.Args); + } + + if (timer.isLoop) + { + timer.curTime += timer.time; + if (timer.curTime <= 0) + { + isLoopCall = true; + } + } + else + { + _cacheRemoveTimers.Add(i); + } + } + } + + for (int i = _cacheRemoveTimers.Count - 1; i >= 0; i--) + { + _timerList.RemoveAt(_cacheRemoveTimers[i]); + _cacheRemoveTimers.RemoveAt(i); + } + + if (isLoopCall) + { + LoopCallInBadFrame(); + } + } + + + private void UpdateUnscaledTimer(float realElapseSeconds) + { + bool isLoopCall = false; + for (int i = 0, len = _unscaledTimerList.Count; i < len; i++) + { + Timer timer = _unscaledTimerList[i]; + if (timer.isNeedRemove) + { + _cacheRemoveUnscaledTimers.Add(i); + continue; + } + + if (!timer.isRunning) continue; + timer.curTime -= realElapseSeconds; + if (timer.curTime <= 0) + { + if (timer.Handler != null) + { + timer.Handler(timer.Args); + } + + if (timer.isLoop) + { + timer.curTime += timer.time; + if (timer.curTime <= 0) + { + isLoopCall = true; + } + } + else + { + _cacheRemoveUnscaledTimers.Add(i); + } + } + } + + for (int i = _cacheRemoveUnscaledTimers.Count - 1; i >= 0; i--) + { + _unscaledTimerList.RemoveAt(_cacheRemoveUnscaledTimers[i]); + _cacheRemoveUnscaledTimers.RemoveAt(i); + } + + if (isLoopCall) + { + LoopCallUnscaledInBadFrame(); + } + } + + private readonly List _ticker = new List(); + + public System.Timers.Timer AddSystemTimer(Action callBack) + { + int interval = 1000; + var timerTick = new System.Timers.Timer(interval); + timerTick.AutoReset = true; + timerTick.Enabled = true; + timerTick.Elapsed += new System.Timers.ElapsedEventHandler(callBack); + + _ticker.Add(timerTick); + + return timerTick; + } + + private void DestroySystemTimer() + { + foreach (var ticker in _ticker) + { + if (ticker != null) + { + ticker.Stop(); + } + } + } + + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + UpdateTimer(elapseSeconds); + UpdateUnscaledTimer(realElapseSeconds); + } + + internal override void Shutdown() + { + DestroySystemTimer(); + } + } +} \ No newline at end of file diff --git a/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerManager.cs.meta b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerManager.cs.meta new file mode 100644 index 00000000..7fd82771 --- /dev/null +++ b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 928cb27baf9022142915e745abe0bb95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerModule.cs b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerModule.cs new file mode 100644 index 00000000..fa27dcc4 --- /dev/null +++ b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerModule.cs @@ -0,0 +1,115 @@ +using UnityEngine; + +namespace TEngine +{ + /// + /// 计时器模块。 + /// + [DisallowMultipleComponent] + public sealed partial class TimerModule : GameFrameworkModuleBase + { + private TimerManager _timerManager; + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + _timerManager = GameFrameworkEntry.GetModule(); + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + } + } + + /// + /// 添加计时器 + /// + /// + /// + /// + /// + /// + /// + public int AddTimer(TimerHandler callback, float time, bool isLoop = false, bool isUnscaled = false, params object[] args) + { + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + throw new GameFrameworkException("TimerMgr is invalid."); + } + + return _timerManager.AddTimer(callback, time, isLoop, isUnscaled, args); + } + + /// + /// 暂停计时 + /// + public void Stop(int timerId) + { + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + throw new GameFrameworkException("TimerMgr is invalid."); + } + _timerManager.Stop(timerId); + } + + /// + /// 移除计时器 + /// + /// + public void RemoveTimer(int timerId) + { + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + throw new GameFrameworkException("TimerMgr is invalid."); + } + _timerManager.RemoveTimer(timerId); + } + + /// + /// 恢复计时 + /// + public void Resume(int timerId) + { + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + throw new GameFrameworkException("TimerMgr is invalid."); + } + _timerManager.Resume(timerId); + } + + /// + /// 计时器是否在运行中 + /// + public bool IsRunning(int timerId) + { + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + throw new GameFrameworkException("TimerMgr is invalid."); + } + + return _timerManager.IsRunning(timerId); + } + + /// + /// 移除所有计时器 + /// + public void RemoveAllTimer() + { + if (_timerManager == null) + { + Log.Fatal("TimerMgr is invalid."); + throw new GameFrameworkException("TimerMgr is invalid."); + } + + _timerManager.RemoveAllTimer(); + } + } +} \ No newline at end of file diff --git a/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerModule.cs.meta b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerModule.cs.meta new file mode 100644 index 00000000..994c3bb4 --- /dev/null +++ b/Assets/TEngine/Runtime/GameFramework/Timer/Timer/TimerModule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 281867d7790648b4aa5342077ba3e5e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TEngine/Runtime/GameModule.cs b/Assets/TEngine/Runtime/GameModule.cs index ea8e591b..c2e2fa88 100644 --- a/Assets/TEngine/Runtime/GameModule.cs +++ b/Assets/TEngine/Runtime/GameModule.cs @@ -53,6 +53,11 @@ public class GameModule:MonoBehaviour /// 获取音频模块。 /// public static AudioModule Audio { get; private set; } + + /// + /// 计时器模块。 + /// + public static TimerModule Timer { get; private set; } #endregion @@ -70,6 +75,7 @@ public class GameModule:MonoBehaviour Setting = Get(); UI = Get(); Audio = Get(); + Timer = Get(); } private static void InitCustomModules() diff --git a/Packages/manifest.json b/Packages/manifest.json index c0d4ec58..26999f53 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -7,7 +7,6 @@ "com.unity.2d.spriteshape": "5.3.0", "com.unity.2d.tilemap": "1.0.0", "com.unity.collab-proxy": "1.15.15", - "com.unity.device-simulator": "3.1.0-preview", "com.unity.ide.rider": "2.0.7", "com.unity.ide.visualstudio": "2.0.14", "com.unity.ide.vscode": "1.2.5", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 78b8be9a..33e2922b 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -81,13 +81,6 @@ }, "url": "https://packages.unity.cn" }, - "com.unity.device-simulator": { - "version": "3.1.0-preview", - "depth": 0, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.cn" - }, "com.unity.ext.nunit": { "version": "1.0.6", "depth": 1, diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset index 14cc8fcc..1691ae21 100644 --- a/ProjectSettings/PackageManagerSettings.asset +++ b/ProjectSettings/PackageManagerSettings.asset @@ -12,7 +12,7 @@ MonoBehaviour: m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} m_Name: m_EditorClassIdentifier: - m_EnablePreviewPackages: 1 + m_EnablePreviewPackages: 0 m_EnablePackageDependencies: 0 m_AdvancedSettingsExpanded: 1 m_ScopedRegistriesSettingsExpanded: 1