diff --git a/unity/Assets/Scenes/Gameplay 1.unity b/unity/Assets/Scenes/Gameplay 1.unity
index 88d8a32..d0117da 100644
--- a/unity/Assets/Scenes/Gameplay 1.unity
+++ b/unity/Assets/Scenes/Gameplay 1.unity
@@ -5399,7 +5399,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 0}
+ m_AnchoredPosition: {x: 0, y: -146}
m_SizeDelta: {x: 160, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &393911460
@@ -6968,7 +6968,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
- m_AnchoredPosition: {x: 0, y: 144.90002}
+ m_AnchoredPosition: {x: 0, y: 1}
m_SizeDelta: {x: 160, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &465138251
@@ -13706,7 +13706,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 0
+ m_IsActive: 1
--- !u!114 &779887011
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -19990,7 +19990,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 0
+ m_IsActive: 1
--- !u!114 &1191631700
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -26470,7 +26470,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
- m_AnchoredPosition: {x: 0, y: -129}
+ m_AnchoredPosition: {x: 0, y: 141}
m_SizeDelta: {x: 160, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1640494086
diff --git a/unity/Assets/Scenes/Gameplay.unity b/unity/Assets/Scenes/Gameplay.unity
index 4bdd338..e9bfdf3 100644
--- a/unity/Assets/Scenes/Gameplay.unity
+++ b/unity/Assets/Scenes/Gameplay.unity
@@ -282,7 +282,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 0
+ m_IsActive: 1
--- !u!224 &18993442
RectTransform:
m_ObjectHideFlags: 0
@@ -8942,7 +8942,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 0
+ m_IsActive: 1
--- !u!224 &607799031
RectTransform:
m_ObjectHideFlags: 0
@@ -11460,6 +11460,7 @@ GameObject:
m_Component:
- component: {fileID: 709661871}
- component: {fileID: 709661870}
+ - component: {fileID: 709661872}
m_Layer: 0
m_HasEditorInfo: 1
m_Name: BGM
@@ -11497,6 +11498,18 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &709661872
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 709661869}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: adcab449847dabf458cae202b969cf63, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!1 &714514298
GameObject:
m_ObjectHideFlags: 0
diff --git a/unity/Assets/Scenes/MainMenu.unity b/unity/Assets/Scenes/MainMenu.unity
index a20c5f6..06312d4 100644
--- a/unity/Assets/Scenes/MainMenu.unity
+++ b/unity/Assets/Scenes/MainMenu.unity
@@ -763,10 +763,56 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
transitionImage: {fileID: 1022684516}
- fadeTime: 1
+ fadeTime: 1.5
mainMenuScene: MainMenu
gameplayScene: Gameplay
scoringScene: Scoring
+--- !u!1 &646400227
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 7
+ m_Component:
+ - component: {fileID: 646400229}
+ - component: {fileID: 646400228}
+ m_Layer: 0
+ m_HasEditorInfo: 1
+ m_Name: ScoreManager
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &646400228
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 646400227}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 3e98896ae36c7a54ba83c4e9eb532752, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ defaultPlayerName: Player
+--- !u!4 &646400229
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 646400227}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &700186399
GameObject:
m_ObjectHideFlags: 0
@@ -1076,7 +1122,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
- m_IsActive: 1
+ m_IsActive: 0
--- !u!224 &1022684515
RectTransform:
m_ObjectHideFlags: 0
@@ -1103,14 +1149,14 @@ MonoBehaviour:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1022684514}
- m_Enabled: 0
+ m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
- m_RaycastTarget: 0
+ m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
@@ -1449,6 +1495,7 @@ GameObject:
- component: {fileID: 1717100627}
- component: {fileID: 1717100626}
- component: {fileID: 1717100625}
+ - component: {fileID: 1717100628}
m_Layer: 0
m_HasEditorInfo: 1
m_Name: EventSystem
@@ -1507,6 +1554,18 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1717100628
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1717100624}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 123025e1710a13c46bf4c72b4a69c62d, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!1 &1717955646
GameObject:
m_ObjectHideFlags: 0
@@ -2014,6 +2073,7 @@ SceneRoots:
- {fileID: 1065091766}
- {fileID: 423191007}
- {fileID: 1340997607}
+ - {fileID: 646400229}
- {fileID: 574406656}
- {fileID: 700186401}
- {fileID: 1717100627}
diff --git a/unity/Assets/UI/PersistentEventSystem.cs b/unity/Assets/UI/PersistentEventSystem.cs
new file mode 100644
index 0000000..8365adc
--- /dev/null
+++ b/unity/Assets/UI/PersistentEventSystem.cs
@@ -0,0 +1,32 @@
+using UnityEngine;
+using UnityEngine.EventSystems;
+
+namespace GameFramework
+{
+ ///
+ /// 挂到 MainMenu 场景的 EventSystem 上(或和它同一个空物体上),
+ /// 让 EventSystem 通过 DontDestroyOnLoad 跨场景存活。
+ /// 这样 Gameplay、Scoring 等场景的按钮都能正常响应点击。
+ ///
+ /// 如果场景里没有 EventSystem,也可以挂到任意空物体上,
+ /// 脚本会自动创建一个。
+ ///
+ public class PersistentEventSystem : MonoBehaviour
+ {
+ void Awake()
+ {
+ // 如果场景里没有 EventSystem,自动创建
+ if (FindObjectOfType() == null)
+ {
+ var go = new GameObject("EventSystem");
+ go.AddComponent();
+ go.AddComponent();
+ }
+
+ // 让 EventSystem 跨场景存活
+ var eventSystem = FindObjectOfType();
+ if (eventSystem != null)
+ DontDestroyOnLoad(eventSystem.gameObject);
+ }
+ }
+}
diff --git a/unity/Assets/UI/PersistentEventSystem.cs.meta b/unity/Assets/UI/PersistentEventSystem.cs.meta
new file mode 100644
index 0000000..2a10c30
--- /dev/null
+++ b/unity/Assets/UI/PersistentEventSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: DngctSioBnphPjHzVSJy8JJFUED7SJpCvstbMN5AHriyvx/FqtTNVmE=
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/unity/Assets/UI/SceneLoader.cs b/unity/Assets/UI/SceneLoader.cs
index fa86655..8d685ec 100644
--- a/unity/Assets/UI/SceneLoader.cs
+++ b/unity/Assets/UI/SceneLoader.cs
@@ -11,7 +11,7 @@ namespace GameFramework
///
/// 搭建:把 SceneLoader 挂到一个空物体上(放第一个场景 MainMenu 里),
/// 它会 DontDestroyOnLoad。transitionImage 是它子物体 Canvas 上的 Image(全屏黑),
- /// Canvas 设为 Screen Space - Overlay、sortingOrder 设很高(如 1000)。
+ /// Canvas 设为 Screen Space - Overlay、sortingOrder 设很高(如 9999)。
///
public class SceneLoader : PersistentSingleton
{
@@ -25,18 +25,28 @@ namespace GameFramework
[SerializeField] private string scoringScene = "Scoring";
private Color color;
+ private bool isLoading = false;
public void LoadGameplayScene() => Load(gameplayScene);
public void LoadMainMenuScene() => Load(mainMenuScene);
public void LoadScoringScene() => Load(scoringScene);
public void Load(string sceneName)
{
+ if (isLoading) return;
+ isLoading = true;
StopAllCoroutines();
StartCoroutine(LoadingCoroutine(sceneName));
}
private IEnumerator LoadingCoroutine(string sceneName)
{
+ if (transitionImage == null)
+ {
+ Debug.LogWarning("[SceneLoader] transitionImage 未赋值! " +
+ "请在 SceneLoader 子物体上创建 Canvas (Overlay, SortOrder=9999) + 全屏黑色 Image," +
+ "拖到 SceneLoader 的 transitionImage 字段。");
+ }
+
var loadingOperation = SceneManager.LoadSceneAsync(sceneName);
loadingOperation.allowSceneActivation = false;
@@ -46,20 +56,32 @@ namespace GameFramework
color = transitionImage.color;
color.a = 0f;
- // 淡入到黑
+ // 淡入到黑(LoadSceneAsync 在后台并行加载)
while (color.a < 1f)
{
color.a = Mathf.Clamp01(color.a + Time.unscaledDeltaTime / fadeTime);
transitionImage.color = color;
yield return null;
}
+ color.a = 1f;
+ transitionImage.color = color;
+
+ // 淡入完成后,确保场景已加载就绪(大多数情况下已经加载好了)
+ yield return new WaitUntil(() => loadingOperation.progress >= 0.9f);
+ }
+ else
+ {
+ // 没有过渡图,直接等加载
+ yield return new WaitUntil(() => loadingOperation.progress >= 0.9f);
}
- // 等异步加载到 90%
- yield return new WaitUntil(() => loadingOperation.progress >= 0.9f);
-
loadingOperation.allowSceneActivation = true;
+ // 等待场景切换完全完成(旧场景卸载 + 新场景渲染就绪)
+ // 没有这一步会在场景交接时闪一帧旧场景的内容
+ yield return null;
+ yield return null;
+
if (transitionImage != null)
{
// 淡出到透明
diff --git a/unity/Assets/UI/ScorePickup.cs b/unity/Assets/UI/ScorePickup.cs
index 370dbba..e6b05f0 100644
--- a/unity/Assets/UI/ScorePickup.cs
+++ b/unity/Assets/UI/ScorePickup.cs
@@ -18,11 +18,13 @@ namespace GameFramework
Collider pickupCollider;
MeshRenderer meshRenderer;
+ SpriteRenderer spriteRenderer;
void Awake()
{
pickupCollider = GetComponent();
meshRenderer = GetComponentInChildren();
+ spriteRenderer = GetComponentInChildren();
// 确保有触发器
if (pickupCollider != null)
pickupCollider.isTrigger = true;
@@ -30,11 +32,16 @@ namespace GameFramework
void OnTriggerEnter(Collider other)
{
+ Debug.Log($"[ScorePickup] 触发碰撞: {other.gameObject.name}, Tag={other.tag}");
if (!other.CompareTag("Player")) return;
+ Debug.Log($"[ScorePickup] 玩家碰撞! ScoreManager={(ScoreManager.Instance != null ? "存在" : "NULL")}");
+
// 加分
if (ScoreManager.Instance != null)
ScoreManager.Instance.AddScore(scoreValue);
+ else
+ Debug.LogWarning("[ScorePickup] ScoreManager 未挂载! 请在 MainMenu 场景的空 GameObject 上挂载 ScoreManager 组件。");
// 音效
if (AudioManager.Instance != null && pickUpSFX != null)
@@ -58,6 +65,8 @@ namespace GameFramework
pickupCollider.enabled = visible;
if (meshRenderer != null)
meshRenderer.enabled = visible;
+ if (spriteRenderer != null)
+ spriteRenderer.enabled = visible;
}
void Respawn()
diff --git a/unity/UserSettings/EditorUserSettings.asset b/unity/UserSettings/EditorUserSettings.asset
index 23f9b05..7d46cd5 100644
--- a/unity/UserSettings/EditorUserSettings.asset
+++ b/unity/UserSettings/EditorUserSettings.asset
@@ -21,15 +21,18 @@ EditorUserSettings:
value: 5055070050010c5a0e5d0d27497a0e441016412c2f7d206178714f61b3b8326b
flags: 0
RecentlyUsedSceneGuid-5:
- value: 5a5757560101590a5d0c0e24427b5d44434e4c7a7b7a23677f2b4565b7b5353a
- flags: 0
- RecentlyUsedSceneGuid-6:
value: 0552060207540d5e0c0c5b2743770a4415164f2c782c7563747f4f31e0b5306f
flags: 0
+ RecentlyUsedSceneGuid-6:
+ value: 5a5757560101590a5d0c0e24427b5d44434e4c7a7b7a23677f2b4565b7b5353a
+ flags: 0
RecentlyUsedSceneGuid-7:
- value: 5a55515156575a0b0f56592346260f444f16197c7e7f24697d2a4a32b1b0353e
+ value: 5300055151055f5a5e0c0f27477708444515192b287124367c791f30b3b9616d
flags: 0
RecentlyUsedSceneGuid-8:
+ value: 5a55515156575a0b0f56592346260f444f16197c7e7f24697d2a4a32b1b0353e
+ flags: 0
+ RecentlyUsedSceneGuid-9:
value: 0209025f575750595c57092149765d444e4e49727e7c7068757b1c65b6e36c3b
flags: 0
UnityEditor.ShaderGraph.Blackboard: