diff options
| author | Weicao-CatilGrass <1992414357@qq.com> | 2026-05-30 19:35:16 +0800 |
|---|---|---|
| committer | Weicao-CatilGrass <1992414357@qq.com> | 2026-05-30 19:35:16 +0800 |
| commit | 7735b716401f630697d5b02910d50dbf8f3416af (patch) | |
| tree | 52d23e7e0434a569bbafdfca6ad196e3ef24af3f /Assets/Scripts | |
| parent | 4408cc53e044a9c649572991a764f46d247c67bf (diff) | |
正在编写动态场景加载
Diffstat (limited to 'Assets/Scripts')
| -rw-r--r-- | Assets/Scripts/ActiveGroup.cs | 52 | ||||
| -rw-r--r-- | Assets/Scripts/ActiveGroup.cs.meta | 11 | ||||
| -rw-r--r-- | Assets/Scripts/AnimatorHandler.cs | 3 | ||||
| -rw-r--r-- | Assets/Scripts/Boot.cs | 23 | ||||
| -rw-r--r-- | Assets/Scripts/Boot.cs.meta | 11 | ||||
| -rw-r--r-- | Assets/Scripts/FragmentManager.cs | 137 | ||||
| -rw-r--r-- | Assets/Scripts/FragmentManager.cs.meta | 11 | ||||
| -rw-r--r-- | Assets/Scripts/FragmentRequire.cs | 46 | ||||
| -rw-r--r-- | Assets/Scripts/FragmentRequire.cs.meta | 11 | ||||
| -rw-r--r-- | Assets/Scripts/PlayerPosition.cs | 30 | ||||
| -rw-r--r-- | Assets/Scripts/PlayerPosition.cs.meta | 11 | ||||
| -rw-r--r-- | Assets/Scripts/SoulCoreGameLoop/UI/AreaHint.cs | 26 | ||||
| -rw-r--r-- | Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs | 39 | ||||
| -rw-r--r-- | Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs.meta | 11 | ||||
| -rw-r--r-- | Assets/Scripts/SoulCoreGameLoop/UI/UIEventListener.cs | 43 |
15 files changed, 426 insertions, 39 deletions
diff --git a/Assets/Scripts/ActiveGroup.cs b/Assets/Scripts/ActiveGroup.cs new file mode 100644 index 0000000..c2e32d0 --- /dev/null +++ b/Assets/Scripts/ActiveGroup.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + +[ExecuteAlways] +public class ActiveGroup : MonoBehaviour +{ + public List<GameObject> members = new(); + + private void Awake() + { + foreach (var member in members) + member.SetActive(gameObject.activeSelf); + + MarkDirty(); + } + + private void OnEnable() + { + foreach (var member in members) + member.SetActive(true); + + MarkDirty(); + } + + private void OnDisable() + { + foreach (var member in members) + member.SetActive(false); + + MarkDirty(); + } + +#if UNITY_EDITOR + private void OnValidate() + { + if (!Application.isPlaying) + EditorUtility.SetDirty(this); + } + + private void MarkDirty() + { + if (!Application.isPlaying) + EditorUtility.SetDirty(this); + } +#else + // 非编辑器平台下,MarkDirty为空方法 + private void MarkDirty() { } +#endif +}
\ No newline at end of file diff --git a/Assets/Scripts/ActiveGroup.cs.meta b/Assets/Scripts/ActiveGroup.cs.meta new file mode 100644 index 0000000..4ba3787 --- /dev/null +++ b/Assets/Scripts/ActiveGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74b926f5f9539684bbdce17adbc0d976 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/AnimatorHandler.cs b/Assets/Scripts/AnimatorHandler.cs index 665a1ca..16f0f67 100644 --- a/Assets/Scripts/AnimatorHandler.cs +++ b/Assets/Scripts/AnimatorHandler.cs @@ -154,9 +154,6 @@ namespace DS // 获取当前帧的根运动位移向量 var rootMotion = GetRootMotion(); - // 输出调试日志,用于查看根运动数据 - Debug.Log(rootMotion); - // 将根运动数据传递给 PlayerLocomotion 组件 // PlayerLocomotion 会将这些位移应用到角色控制器上 playerLocomotion.rootMotion = rootMotion; diff --git a/Assets/Scripts/Boot.cs b/Assets/Scripts/Boot.cs new file mode 100644 index 0000000..ddefd0b --- /dev/null +++ b/Assets/Scripts/Boot.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; +#if UNITY_EDITOR +using UnityEditor; +#endif + +public class SceneLoader : MonoBehaviour +{ + [SerializeField] private List<SceneAsset> scenes; + + private void Awake() + { + foreach (var sceneAsset in scenes) + { + string sceneName = sceneAsset.name; + if (!SceneManager.GetSceneByName(sceneName).isLoaded) + { + SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); + } + } + } +}
\ No newline at end of file diff --git a/Assets/Scripts/Boot.cs.meta b/Assets/Scripts/Boot.cs.meta new file mode 100644 index 0000000..00e0ea0 --- /dev/null +++ b/Assets/Scripts/Boot.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4d77beacb22bba47962777552841ef3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/FragmentManager.cs b/Assets/Scripts/FragmentManager.cs new file mode 100644 index 0000000..3bac110 --- /dev/null +++ b/Assets/Scripts/FragmentManager.cs @@ -0,0 +1,137 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +public class FragmentManager : MonoBehaviour +{ + private static readonly HashSet<string> LoadedSceneNames = new(); + + /// <summary> + /// 刷新场景需要列表(基于场景名称) + /// </summary> + /// <param name="requiredSceneNames">需要的场景名称列表(需与 Build Settings 中的名称一致,不带 .unity 扩展名)</param> + public static void UpdateSceneRequirements(List<string> requiredSceneNames) + { + var toUnload = new List<string>(); + var toLoad = new List<string>(); + + // 需要卸载的:当前已加载但不在 requiredSceneNames 中 + foreach (var loadedName in LoadedSceneNames) + { + if (!requiredSceneNames.Contains(loadedName)) + toUnload.Add(loadedName); + } + + // 需要加载的:requiredSceneNames 中尚未加载的 + foreach (var reqName in requiredSceneNames) + { + if (!LoadedSceneNames.Contains(reqName)) + toLoad.Add(reqName); + } + + UnloadScenes(toUnload); + LoadScenes(toLoad); + } + + /// <summary> + /// 重置所有场景(先卸载全部,再重新加载) + /// </summary> + public static void ReloadAllScenes() + { + var scenesToReload = new List<string>(LoadedSceneNames); + + // 先卸载所有 + foreach (var sceneName in scenesToReload) + { + var asyncOp = SceneManager.UnloadSceneAsync(sceneName); + if (asyncOp != null) + { + asyncOp.completed += _ => + { + if (LoadedSceneNames.Contains(sceneName)) + LoadedSceneNames.Remove(sceneName); + }; + } + else + { + // 同步卸载后备(已过时,仅用于兼容) + if (SceneManager.UnloadScene(sceneName)) + LoadedSceneNames.Remove(sceneName); + } + } + + // 重新加载(注意:卸载异步,立即加载可能导致短暂重叠,但通常可接受) + foreach (var sceneName in scenesToReload) + { + var asyncOp = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); + if (asyncOp != null) + { + asyncOp.completed += _ => + { + var scene = SceneManager.GetSceneByName(sceneName); + if (scene.isLoaded && !LoadedSceneNames.Contains(sceneName)) + LoadedSceneNames.Add(sceneName); + }; + } + else + { + // 同步加载后备 + SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); + var scene = SceneManager.GetSceneByName(sceneName); + if (scene.isLoaded && !LoadedSceneNames.Contains(sceneName)) + LoadedSceneNames.Add(sceneName); + } + } + } + + /// <summary> + /// 异步卸载场景列表,完成后从 LoadedSceneNames 中移除 + /// </summary> + private static void UnloadScenes(List<string> sceneNames) + { + foreach (var sceneName in sceneNames) + { + var asyncOp = SceneManager.UnloadSceneAsync(sceneName); + if (asyncOp != null) + { + asyncOp.completed += _ => + { + if (LoadedSceneNames.Contains(sceneName)) + LoadedSceneNames.Remove(sceneName); + }; + } + else + { + if (SceneManager.UnloadScene(sceneName)) + LoadedSceneNames.Remove(sceneName); + } + } + } + + /// <summary> + /// 异步加载场景列表,完成后加入 LoadedSceneNames + /// </summary> + private static void LoadScenes(List<string> sceneNames) + { + foreach (var sceneName in sceneNames) + { + var asyncOp = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); + if (asyncOp != null) + { + asyncOp.completed += _ => + { + var scene = SceneManager.GetSceneByName(sceneName); + if (scene.isLoaded && !LoadedSceneNames.Contains(sceneName)) + LoadedSceneNames.Add(sceneName); + }; + } + else + { + SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); + var scene = SceneManager.GetSceneByName(sceneName); + if (scene.isLoaded && !LoadedSceneNames.Contains(sceneName)) + LoadedSceneNames.Add(sceneName); + } + } + } +}
\ No newline at end of file diff --git a/Assets/Scripts/FragmentManager.cs.meta b/Assets/Scripts/FragmentManager.cs.meta new file mode 100644 index 0000000..7427464 --- /dev/null +++ b/Assets/Scripts/FragmentManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ed3c0bca3fd03a42bd614ec3abc535d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/FragmentRequire.cs b/Assets/Scripts/FragmentRequire.cs new file mode 100644 index 0000000..71ce602 --- /dev/null +++ b/Assets/Scripts/FragmentRequire.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityEngine.SceneManagement; + +[RequireComponent(typeof(BoxCollider))] +[ExecuteAlways] +public class FragmentRequire : MonoBehaviour +{ + public List<SceneAsset> requiredScenes = new(); + + private BoxCollider _boxCollider; + + private void Awake() + { + _boxCollider = GetComponent<BoxCollider>(); + _boxCollider.isTrigger = true; + } + + private void OnTriggerEnter(Collider other) + { + var sceneName = new List<string>(); + foreach (SceneAsset sceneAsset in requiredScenes) + sceneName.Add(sceneAsset.name); + FragmentManager.UpdateSceneRequirements(sceneName); + } + + private void Update() + { + _boxCollider.size = Vector3.one; + } + + private void OnDrawGizmos() + { + if (_boxCollider == null) return; + + var cs = _boxCollider.size; + var ts = Vector3.one; + var size = new Vector3(cs.x * ts.x, cs.y * ts.y, cs.z * ts.z); + + Gizmos.color = new Color(1f, 0.18f, 0.29f, 0.5f); + Gizmos.matrix = transform.localToWorldMatrix; + Gizmos.DrawCube(_boxCollider.center, size); + } +} diff --git a/Assets/Scripts/FragmentRequire.cs.meta b/Assets/Scripts/FragmentRequire.cs.meta new file mode 100644 index 0000000..20db4a6 --- /dev/null +++ b/Assets/Scripts/FragmentRequire.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b72db117845309468398fb2b199c144 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/PlayerPosition.cs b/Assets/Scripts/PlayerPosition.cs new file mode 100644 index 0000000..9b839f8 --- /dev/null +++ b/Assets/Scripts/PlayerPosition.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections; +using DS; +using UnityEngine; + +public class PlayerPosition : MonoBehaviour +{ + private PlayerLocomotion _playerLocomotion; + + private void Awake() + { + StartCoroutine(FindPlayer()); + } + + private void Update() + { + if (_playerLocomotion != null) + transform.position = _playerLocomotion.transform.position; + } + + IEnumerator FindPlayer() + { + while (true) + { + yield return new WaitUntil(() => _playerLocomotion == null); + _playerLocomotion = GetComponent<PlayerLocomotion>(); + yield return new WaitForSeconds(5f); + } + } +} diff --git a/Assets/Scripts/PlayerPosition.cs.meta b/Assets/Scripts/PlayerPosition.cs.meta new file mode 100644 index 0000000..cbe7659 --- /dev/null +++ b/Assets/Scripts/PlayerPosition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8035635bcbd329a49b7b0fe4d301f6e5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SoulCoreGameLoop/UI/AreaHint.cs b/Assets/Scripts/SoulCoreGameLoop/UI/AreaHint.cs index ab03647..6b676fe 100644 --- a/Assets/Scripts/SoulCoreGameLoop/UI/AreaHint.cs +++ b/Assets/Scripts/SoulCoreGameLoop/UI/AreaHint.cs @@ -1,31 +1,31 @@ using System; -using TMPro; -using UnityEditor; using UnityEngine; +using TMPro; namespace SoulCoreGameLoop.UI { [RequireComponent(typeof(Animator))] public class AreaHint : MonoBehaviour, IUIEventSender<AreaHintMessage> { - private const String TriggerPlay = "Play"; + private static readonly int TriggerPlay = Animator.StringToHash("Play"); public TMP_Text areaName; private Animator _animator; - [InitializeOnLoadMethod] - public static void RegisterListener () - => UIEventListener.JoinListener<AreaHintMessage>(); - - public void OnReceive(AreaHintMessage evt) + private void Awake() { - areaName.text = evt.AreaName; - _animator.Play(TriggerPlay); + _animator = GetComponent<Animator>(); + UIEventListener.Register(this); } + + private void OnDestroy() + => UIEventListener.Unregister<AreaHintMessage>(); + - private void Start() + public void OnReceive(AreaHintMessage evt) { - _animator = GetComponent<Animator>(); + areaName.text = evt.AreaName; + _animator.SetTrigger(TriggerPlay); } } @@ -38,4 +38,4 @@ namespace SoulCoreGameLoop.UI AreaName = areaName; } } -} +}
\ No newline at end of file diff --git a/Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs b/Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs new file mode 100644 index 0000000..efc5e5f --- /dev/null +++ b/Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +namespace SoulCoreGameLoop.UI +{ + [RequireComponent(typeof(BoxCollider))] + public class AreaHintGenerator : MonoBehaviour + { + [Header("名字")] + public new string name = "土豆祭祀场"; + + private BoxCollider _collider; + + private void Awake() + { + _collider = GetComponent<BoxCollider>(); + _collider.isTrigger = true; + } + + private void OnTriggerEnter(Collider other) + { + Debug.Log("AreaHintGenerator OnTriggerEnter"); + // 向监听器发送消息 + UIEventListener.Send(new AreaHintMessage(name)); + } + + private void OnDrawGizmosSelected() + { + if (_collider == null) return; + + var cs = _collider.size; + var ts = transform.lossyScale; + var size = new Vector3(cs.x * ts.x, cs.y * ts.y, cs.z * ts.z); + + Gizmos.color = new Color(1f, 1f, 1f, 0.5f); + Gizmos.matrix = transform.localToWorldMatrix; + Gizmos.DrawCube(_collider.center, size); + } + } +} diff --git a/Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs.meta b/Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs.meta new file mode 100644 index 0000000..1282763 --- /dev/null +++ b/Assets/Scripts/SoulCoreGameLoop/UI/AreaHintGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 33b85f0adc67b1a43b0e1033f466d85e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SoulCoreGameLoop/UI/UIEventListener.cs b/Assets/Scripts/SoulCoreGameLoop/UI/UIEventListener.cs index 2d33a9b..0b17b6f 100644 --- a/Assets/Scripts/SoulCoreGameLoop/UI/UIEventListener.cs +++ b/Assets/Scripts/SoulCoreGameLoop/UI/UIEventListener.cs @@ -1,52 +1,49 @@ using System; using System.Collections.Generic; -using Object = System.Object; namespace SoulCoreGameLoop.UI { /// <summary> - /// UI 事件监听器 + /// UI 事件总线(消息类型 → 处理器) /// </summary> public static class UIEventListener { - private static readonly Dictionary<TypeCode, Object> TypeSets = new (); + private static readonly Dictionary<Type, object> Handlers = new(); /// <summary> - /// 向 UI 事件监听器添加发送器实例 + /// 注册某个消息类型的处理器(同一类型只能有一个处理器) /// </summary> - /// <typeparam name="T"> 发送器绑定类型 </typeparam> - public static void JoinListener<T>() where T : new() + public static void Register<T>(IUIEventSender<T> handler) { - var typeCode = Type.GetTypeCode(typeof(T)); - TypeSets.Add(typeCode, new T()); + Handlers[typeof(T)] = handler; } /// <summary> - /// 向 UI 事件监听器发送消息 + /// 移除某个消息类型的处理器 + /// </summary> + public static void Unregister<T>() + { + Handlers.Remove(typeof(T)); + } + + /// <summary> + /// 发送消息 /// </summary> - /// <param name="message"> 发送器 </param> - /// <typeparam name="T"> 消息类型 </typeparam> public static void Send<T>(T message) { - var typeCode = Type.GetTypeCode(typeof(T)); - if (TypeSets.TryGetValue(typeCode, out var set)) + Type type = typeof(T); + if (Handlers.TryGetValue(type, out object handlerObj)) { - var sender = (IUIEventSender<T>) set; - sender.OnReceive(message); + ((IUIEventSender<T>)handlerObj).OnReceive(message); } } } /// <summary> - /// UI 事件发送器 + /// 消息处理器接口 /// </summary> - /// <typeparam name="TEvent"></typeparam> public interface IUIEventSender<in TEvent> { - /// <summary> - /// 当接收到 UI 事件时的处理 - /// </summary> - /// <param name="evt"></param> - public void OnReceive(TEvent evt); + void OnReceive(TEvent evt); } -} +}
\ No newline at end of file |
