From 8ae4469c7269742caed79acc47e39348c22d0726 Mon Sep 17 00:00:00 2001 From: ksh999000 <740612340@qq.com> Date: Sat, 4 Jul 2026 18:35:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9F=B3=E6=95=88=20v0.1?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + unity/.qoder/skills/water-reflection/SKILL.md | 104 ++++++++++++++++++ .../2.5D Engine/Scripts/HealthSystem.cs | 4 + unity/Assets/2.5D Engine/Scripts/Player.cs | 5 + .../shaders/IndianOcean_DarknessOverlay.mat | 2 +- unity/Assets/Scenes/Gameplay.unity | 36 +++++- unity/Assets/Scenes/MainMenu.unity | 68 ++++++++++++ unity/Assets/Scenes/Test.unity | 22 +++- unity/Assets/UI/AudioManager.cs | 24 ++++ unity/Assets/UI/UIClickSoundHandler.cs | 46 ++++++++ unity/Assets/UI/UIClickSoundHandler.cs.meta | 11 ++ unity/Assets/audios/Resources.meta | 8 ++ unity/Assets/audios/Resources/SFX.meta | 8 ++ unity/Assets/audios/Resources/SFX/Bell.wav | Bin 0 -> 70604 bytes .../Assets/audios/Resources/SFX/Bell.wav.meta | 23 ++++ unity/Assets/audios/Resources/SFX/Dash.wav | Bin 0 -> 30912 bytes .../Assets/audios/Resources/SFX/Dash.wav.meta | 23 ++++ unity/Assets/audios/Resources/SFX/Hurt.wav | Bin 0 -> 26504 bytes .../Assets/audios/Resources/SFX/Hurt.wav.meta | 23 ++++ unity/Assets/audios/Resources/SFX/Lantern.wav | Bin 0 -> 44144 bytes .../audios/Resources/SFX/Lantern.wav.meta | 23 ++++ .../Assets/audios/Resources/SFX/UI_Click.wav | Bin 0 -> 7100 bytes .../audios/Resources/SFX/UI_Click.wav.meta | 23 ++++ unity/Assets/audios/SFX.meta | 8 ++ unity/Assets/audios/SFX/Bell.wav | Bin 0 -> 70604 bytes unity/Assets/audios/SFX/Bell.wav.meta | 23 ++++ unity/Assets/audios/SFX/Dash.wav | Bin 0 -> 30912 bytes unity/Assets/audios/SFX/Dash.wav.meta | 23 ++++ unity/Assets/audios/SFX/Hurt.wav | Bin 0 -> 26504 bytes unity/Assets/audios/SFX/Hurt.wav.meta | 23 ++++ unity/Assets/audios/SFX/Lantern.wav | Bin 0 -> 44144 bytes unity/Assets/audios/SFX/Lantern.wav.meta | 23 ++++ unity/Assets/audios/SFX/UI_Click.wav | Bin 0 -> 7100 bytes unity/Assets/audios/SFX/UI_Click.wav.meta | 23 ++++ unity/Assets/eco/EchoSystem.cs | 5 + unity/Assets/eco/SpiritLanternSystem.cs | 5 + unity/UserSettings/EditorUserSettings.asset | 8 +- 37 files changed, 588 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 unity/.qoder/skills/water-reflection/SKILL.md create mode 100644 unity/Assets/UI/UIClickSoundHandler.cs create mode 100644 unity/Assets/UI/UIClickSoundHandler.cs.meta create mode 100644 unity/Assets/audios/Resources.meta create mode 100644 unity/Assets/audios/Resources/SFX.meta create mode 100644 unity/Assets/audios/Resources/SFX/Bell.wav create mode 100644 unity/Assets/audios/Resources/SFX/Bell.wav.meta create mode 100644 unity/Assets/audios/Resources/SFX/Dash.wav create mode 100644 unity/Assets/audios/Resources/SFX/Dash.wav.meta create mode 100644 unity/Assets/audios/Resources/SFX/Hurt.wav create mode 100644 unity/Assets/audios/Resources/SFX/Hurt.wav.meta create mode 100644 unity/Assets/audios/Resources/SFX/Lantern.wav create mode 100644 unity/Assets/audios/Resources/SFX/Lantern.wav.meta create mode 100644 unity/Assets/audios/Resources/SFX/UI_Click.wav create mode 100644 unity/Assets/audios/Resources/SFX/UI_Click.wav.meta create mode 100644 unity/Assets/audios/SFX.meta create mode 100644 unity/Assets/audios/SFX/Bell.wav create mode 100644 unity/Assets/audios/SFX/Bell.wav.meta create mode 100644 unity/Assets/audios/SFX/Dash.wav create mode 100644 unity/Assets/audios/SFX/Dash.wav.meta create mode 100644 unity/Assets/audios/SFX/Hurt.wav create mode 100644 unity/Assets/audios/SFX/Hurt.wav.meta create mode 100644 unity/Assets/audios/SFX/Lantern.wav create mode 100644 unity/Assets/audios/SFX/Lantern.wav.meta create mode 100644 unity/Assets/audios/SFX/UI_Click.wav create mode 100644 unity/Assets/audios/SFX/UI_Click.wav.meta diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e56e04 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/unity/.qoder/skills/water-reflection/SKILL.md b/unity/.qoder/skills/water-reflection/SKILL.md new file mode 100644 index 0000000..30049b3 --- /dev/null +++ b/unity/.qoder/skills/water-reflection/SKILL.md @@ -0,0 +1,104 @@ +--- +name: water-reflection +description: 为 Unity 项目中的 UI Image 或 Sprite 应用水面倒影效果。创建或复用 WaterReflection shader(IndianOcean/WaterReflection),创建材质并应用到目标物体。支持水面线位置、波浪振幅、扰动强度、倒影变暗、淡出长度、水面线亮度等参数配置。当用户提到水面倒影、水面反射、倒影效果、water reflection 时使用。 +--- + +# 水面倒影效果 (Water Reflection) + +为 UI Image 或 SpriteRenderer 添加水面倒影效果:原图上半部分保持不变,下半部分显示垂直翻转的扰动倒影,水面分界线带波浪起伏和亮线。 + +## 资源路径 + +| 资源 | 路径 | +|------|------| +| Shader | `Assets/Light/shaders/WaterReflection.shader` | +| 材质 | `Assets/Materials/WaterReflection.mat` | +| Shader 名称 | `IndianOcean/WaterReflection` | + +## 使用流程 + +### 1. 确保 Shader 存在 + +检查 `Assets/Light/shaders/WaterReflection.shader` 是否存在。若不存在,从下方 [Shader 源码](#shader-源码) 创建。 + +### 2. 创建或复用材质 + +使用 MCP `assets-material-create` 工具: + +``` +shaderName: "IndianOcean/WaterReflection" +assetPath: "Assets/Materials/WaterReflection.mat" +``` + +若材质已存在则跳过。 + +### 3. 应用到目标物体 + +通过 MCP `script-execute` 执行以下脚本(替换 `TARGET_NAME` 为目标物体名): + +```csharp +using UnityEngine; +using UnityEditor; +using UnityEngine.UI; + +public class Script +{ + public static void Main() + { + var target = GameObject.Find("TARGET_NAME"); + var mat = AssetDatabase.LoadAssetAtPath("Assets/Materials/WaterReflection.mat"); + + // UI Image + var img = target.GetComponent(); + if (img != null) { img.material = mat; return; } + + // SpriteRenderer + var sr = target.GetComponent(); + if (sr != null) { sr.material = mat; return; } + + // Any Renderer + var r = target.GetComponent(); + if (r != null) { r.material = mat; return; } + } +} +``` + +### 4. 刷新资源 + +调用 MCP `assets-refresh` 确保 Unity 编译 shader。 + +## 可调参数 + +| 参数 | 说明 | 默认值 | 范围 | +|------|------|--------|------| +| `_Waterline` | 水面线位置(UV.y) | 0.7 | 0.05 ~ 0.95 | +| `_WaveAmplitude` | 水面线波浪振幅 | 0.012 | 0 ~ 0.05 | +| `_WaveFreq` | 水面线波浪频率 | 4.0 | 1 ~ 15 | +| `_WaveSpeed` | 水面线波浪速度 | 1.0 | 0 ~ 5 | +| `_DistortStrength` | 倒影水平扰动强度 | 0.015 | 0 ~ 0.08 | +| `_DistortSpeed` | 扰动动画速度 | 1.5 | 0 ~ 5 | +| `_DistortFreq` | 扰动波纹频率 | 8.0 | 1 ~ 20 | +| `_ReflDarken` | 倒影变暗系数 | 0.5 | 0 ~ 1 | +| `_ReflFadeLen` | 倒影向下淡出长度 | 0.25 | 0 ~ 0.5 | +| `_LineBrightness` | 水面线亮度 | 1.5 | 0 ~ 3 | +| `_LineThickness` | 水面线粗细 | 0.004 | 0 ~ 0.02 | + +通过 MCP `gameobject-component-modify` 或 `object-modify` 修改材质参数。 + +## Shader 源码 + +若需重建 shader,完整源码见 [WaterReflection.shader](../../../Assets/Light/shaders/WaterReflection.shader)。 + +核心原理: +- 以 `_Waterline` 为轴,多层正弦+noise 叠加产生波浪形分界线 +- 倒影区 UV 垂直翻转:`reflUV.y = 2 * waterline - uv.y` +- 水平扰动由多层 noise 叠加模拟随机水面波纹 +- 倒影从上往下逐渐淡出(alpha 衰减) +- 水面分界线处叠加蓝白色亮线 + +## 注意事项 + +- 项目使用 **URP** 渲染管线,shader 已包含 `"RenderPipeline" = "UniversalPipeline"` tag +- UI Image 通过 `Image.material` 设置,不是 `Renderer.material` +- 修改 shader 文件后需调用 `assets-refresh` 触发重新编译 +- 波浪效果是动态的(依赖 `_Time.y`),在 Play 模式下最明显 diff --git a/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs b/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs index ce6c797..b146c47 100644 --- a/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs +++ b/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs @@ -39,6 +39,10 @@ namespace IndianOceanAssets.Engine2_5D if (isPlayer && onPlayerDamaged != null) onPlayerDamaged.Invoke(); + // 播放受伤音效 + if (isPlayer && AudioManager.Instance != null) + AudioManager.Instance.PlaySFXFromResources("SFX/Hurt", 0.7f); + // If dead if (health <= 0) { diff --git a/unity/Assets/2.5D Engine/Scripts/Player.cs b/unity/Assets/2.5D Engine/Scripts/Player.cs index ef1c1ca..17e7418 100644 --- a/unity/Assets/2.5D Engine/Scripts/Player.cs +++ b/unity/Assets/2.5D Engine/Scripts/Player.cs @@ -1,5 +1,6 @@ using UnityEngine; using System.Collections; +using GameFramework; namespace IndianOceanAssets.Engine2_5D { @@ -89,6 +90,10 @@ namespace IndianOceanAssets.Engine2_5D isRolling = true; lastRollTime = Time.time; + // 播放冲刺音效 + if (AudioManager.Instance != null) + AudioManager.Instance.PlaySFXFromResources("SFX/Dash", 0.8f); + float timer = 0.2f; Vector3 rollDir = new Vector3(inputDirection.x, 0f, inputDirection.y).normalized; diff --git a/unity/Assets/Light/shaders/IndianOcean_DarknessOverlay.mat b/unity/Assets/Light/shaders/IndianOcean_DarknessOverlay.mat index 2abee3a..d415915 100644 --- a/unity/Assets/Light/shaders/IndianOcean_DarknessOverlay.mat +++ b/unity/Assets/Light/shaders/IndianOcean_DarknessOverlay.mat @@ -30,7 +30,7 @@ Material: - _EchoIntensity: 0 - _EchoRadius: 39.41617 - _EchoWidth: 2.5 - - _LightSoftness: 1 + - _LightSoftness: 0.5 - _MinBrightness: 0 m_Colors: - _DarknessColor: {r: 0.01, g: 0.01, b: 0.02, a: 1} diff --git a/unity/Assets/Scenes/Gameplay.unity b/unity/Assets/Scenes/Gameplay.unity index ad787b5..26b87c6 100644 --- a/unity/Assets/Scenes/Gameplay.unity +++ b/unity/Assets/Scenes/Gameplay.unity @@ -2017,6 +2017,7 @@ GameObject: - component: {fileID: 160213093} - component: {fileID: 160213092} - component: {fileID: 160213091} + - component: {fileID: 160213096} m_Layer: 0 m_HasEditorInfo: 1 m_Name: HUD_Canvas @@ -2138,6 +2139,22 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0, y: 0} +--- !u!114 &160213096 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 160213090} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!4 &166849993 stripped Transform: m_CorrespondingSourceObject: {fileID: 435539791518907074, guid: 559314d2eb0483149908bafda142bcd7, type: 3} @@ -8835,6 +8852,7 @@ GameObject: - component: {fileID: 607799032} - component: {fileID: 607799034} - component: {fileID: 607799033} + - component: {fileID: 607799035} m_Layer: 5 m_HasEditorInfo: 1 m_Name: PauseMenuCanvas @@ -8926,6 +8944,22 @@ MonoBehaviour: m_DefaultSpriteDPI: 96 m_DynamicPixelsPerUnit: 1 m_PresetInfoIsWorld: 0 +--- !u!114 &607799035 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 607799030} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!1 &609157175 GameObject: m_ObjectHideFlags: 0 @@ -30447,7 +30481,7 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1966623129} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} m_Name: diff --git a/unity/Assets/Scenes/MainMenu.unity b/unity/Assets/Scenes/MainMenu.unity index 0b5a315..da05eb5 100644 --- a/unity/Assets/Scenes/MainMenu.unity +++ b/unity/Assets/Scenes/MainMenu.unity @@ -1341,6 +1341,7 @@ GameObject: - component: {fileID: 897692929} - component: {fileID: 897692928} - component: {fileID: 897692927} + - component: {fileID: 897692930} m_Layer: 0 m_HasEditorInfo: 1 m_Name: Canvas @@ -1433,6 +1434,22 @@ Canvas: m_SortingLayerID: 0 m_SortingOrder: 1000 m_TargetDisplay: 0 +--- !u!114 &897692930 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 897692925} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!1 &951237302 GameObject: m_ObjectHideFlags: 0 @@ -1882,6 +1899,7 @@ GameObject: - component: {fileID: 1036666437} - component: {fileID: 1036666436} - component: {fileID: 1036666435} + - component: {fileID: 1036666440} m_Layer: 0 m_HasEditorInfo: 1 m_Name: MainMenu_Canvas @@ -1997,6 +2015,22 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0, y: 0} +--- !u!114 &1036666440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1036666434} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!1 &1036827524 GameObject: m_ObjectHideFlags: 0 @@ -2208,6 +2242,7 @@ GameObject: - component: {fileID: 1065091764} - component: {fileID: 1065091763} - component: {fileID: 1065091767} + - component: {fileID: 1065091768} m_Layer: 5 m_HasEditorInfo: 1 m_Name: UI @@ -2321,6 +2356,22 @@ MonoBehaviour: settingsBackButton: {fileID: 774721830} creditsPanel: {fileID: 0} creditsCloseButton: {fileID: 0} +--- !u!114 &1065091768 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1065091762} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!1 &1106266784 GameObject: m_ObjectHideFlags: 0 @@ -3722,6 +3773,7 @@ GameObject: - component: {fileID: 1852443090} - component: {fileID: 1852443089} - component: {fileID: 1852443088} + - component: {fileID: 1852443093} m_Layer: 0 m_HasEditorInfo: 1 m_Name: HUD_Canvas @@ -3836,6 +3888,22 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0, y: 0} +--- !u!114 &1852443093 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1852443087} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!1 &1867658318 GameObject: m_ObjectHideFlags: 0 diff --git a/unity/Assets/Scenes/Test.unity b/unity/Assets/Scenes/Test.unity index afb0c70..62384bf 100644 --- a/unity/Assets/Scenes/Test.unity +++ b/unity/Assets/Scenes/Test.unity @@ -164,7 +164,7 @@ MonoBehaviour: minBrightness: 0 darknessColor: {r: 0.01, g: 0.01, b: 0.02, a: 1} lightSoftness: 0.5 - followCamera: 1 + followTarget: {fileID: 0} maskPlane: {fileID: 338266643} maskOffset: {x: 0, y: 0, z: 0} planeSize: 300 @@ -1730,6 +1730,7 @@ MonoBehaviour: m_EditorClassIdentifier: target: {fileID: 441783843} offset: {x: 0, y: 6.25, z: -7.5} + followSmoothness: 20 --- !u!4 &331731258 stripped Transform: m_CorrespondingSourceObject: {fileID: 3758831290525234046, guid: c8ebec87794f9e541b3416e11049afa7, type: 3} @@ -2322,6 +2323,7 @@ GameObject: - component: {fileID: 413844532} - component: {fileID: 413844531} - component: {fileID: 413844535} + - component: {fileID: 413844536} m_Layer: 5 m_HasEditorInfo: 1 m_Name: Canvas @@ -2428,6 +2430,22 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: healthFill: {fileID: 255691866} +--- !u!114 &413844536 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 413844530} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4acb13cd074243844ae5d9645289796d, type: 3} + m_Name: + m_EditorClassIdentifier: + selectSFXPath: SFX/UI_Click + clickSFXPath: SFX/UI_Click + selectVolume: 0.5 + clickVolume: 0.6 --- !u!1001 &416141938 PrefabInstance: m_ObjectHideFlags: 0 @@ -5494,6 +5512,7 @@ MonoBehaviour: radius: 2 intensity: 1 registerOnStart: 1 + offset: {x: 0, y: 0, z: 0} followTarget: {fileID: 0} enableFlicker: 0 flickerSpeed: 5 @@ -7775,6 +7794,7 @@ MonoBehaviour: radius: 1 intensity: 1 registerOnStart: 1 + offset: {x: 0, y: 0, z: 0} followTarget: {fileID: 0} enableFlicker: 1 flickerSpeed: 5 diff --git a/unity/Assets/UI/AudioManager.cs b/unity/Assets/UI/AudioManager.cs index 6cd1f59..9731c52 100644 --- a/unity/Assets/UI/AudioManager.cs +++ b/unity/Assets/UI/AudioManager.cs @@ -113,6 +113,30 @@ namespace GameFramework PlaySFX(data); } + /// + /// 直接通过 AudioClip 播放音效。 + /// + public void PlaySFX(AudioClip clip, float volume = 1f) + { + if (clip == null) return; + sfxPlayer.PlayOneShot(clip, volume); + } + + /// + /// 通过 Resources 路径加载并播放音效。 + /// 路径相对于 Assets/audios/Resources/,例如 "SFX/Bell" + /// + public void PlaySFXFromResources(string resourcePath, float volume = 1f) + { + var clip = Resources.Load(resourcePath); + if (clip == null) + { + Debug.LogWarning($"[AudioManager] SFX not found: {resourcePath}"); + return; + } + PlaySFX(clip, volume); + } + public void SetSFXVolume(float volume) { sfxVolume = Mathf.Clamp01(volume); diff --git a/unity/Assets/UI/UIClickSoundHandler.cs b/unity/Assets/UI/UIClickSoundHandler.cs new file mode 100644 index 0000000..4510e82 --- /dev/null +++ b/unity/Assets/UI/UIClickSoundHandler.cs @@ -0,0 +1,46 @@ +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.EventSystems; + +namespace GameFramework +{ + /// + /// 全局 UI 按钮音效处理器。 + /// 挂到 Canvas 上,自动监听所有按钮的点击/悬停事件并播放音效。 + /// 无需在每个按钮上单独添加组件。 + /// + public class UIClickSoundHandler : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler + { + [Header("音效资源路径(相对于 Resources 文件夹)")] + [SerializeField] private string selectSFXPath = "SFX/UI_Click"; + [SerializeField] private string clickSFXPath = "SFX/UI_Click"; + + [Header("音量")] + [SerializeField] private float selectVolume = 0.5f; + [SerializeField] private float clickVolume = 0.6f; + + private void PlaySFX(string path, float volume) + { + if (AudioManager.Instance != null) + AudioManager.Instance.PlaySFXFromResources(path, volume); + } + + public void OnPointerEnter(PointerEventData eventData) + { + // 只对按钮播放悬停音效 + if (eventData.pointerEnter != null && eventData.pointerEnter.GetComponent