diff --git a/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset b/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset
index 8887b885b..a2ed8c500 100644
--- a/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset
+++ b/Assets/AddressableAssetsData/AssetGroups/Default Local Group.asset
@@ -59,6 +59,13 @@ MonoBehaviour:
- PTCBZS
- ZSYX
FlaggedDuringContentUpdateRestriction: 0
+ - m_GUID: 55ff41d3491d69048aed1f871fee2253
+ m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Button.ogg
+ m_ReadOnly: 0
+ m_SerializedLabels:
+ - Audio
+ - Default
+ FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 623f39d408d373f498bfa9c7ef4f4dd1
m_Address: Assets/MyGame/aa/Game/ZhanShen/Game/display_14080_0_DaTing.prefab
m_ReadOnly: 0
diff --git a/Assets/AddressableAssetsData/AssetGroups/Fish_XJMH.asset b/Assets/AddressableAssetsData/AssetGroups/Fish_XJMH.asset
index 8bffc0fe9..f48d4e581 100644
--- a/Assets/AddressableAssetsData/AssetGroups/Fish_XJMH.asset
+++ b/Assets/AddressableAssetsData/AssetGroups/Fish_XJMH.asset
@@ -673,13 +673,6 @@ MonoBehaviour:
- Audio
- XJMH
FlaggedDuringContentUpdateRestriction: 0
- - m_GUID: 55ff41d3491d69048aed1f871fee2253
- m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Button.ogg
- m_ReadOnly: 0
- m_SerializedLabels:
- - Audio
- - XJMH
- FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 571b94c02f405bf44846bb65a9063c17
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Settle_Hole.ogg
m_ReadOnly: 0
diff --git a/Assets/Art/FengLei/Boss/6002/6002.prefab b/Assets/Art/FengLei/Boss/6002/6002.prefab
index aec3d26ab..ed4b1002d 100644
--- a/Assets/Art/FengLei/Boss/6002/6002.prefab
+++ b/Assets/Art/FengLei/Boss/6002/6002.prefab
@@ -2318,7 +2318,7 @@ GameObject:
m_Component:
- component: {fileID: 7597091867940339197}
- component: {fileID: 4536030933686261914}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_5
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -20518,7 +20518,7 @@ GameObject:
m_Component:
- component: {fileID: 5098281124427048100}
- component: {fileID: 6279646298209540641}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_3
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -20738,7 +20738,7 @@ GameObject:
m_Component:
- component: {fileID: 7945055334132002757}
- component: {fileID: 2353989672940325644}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_1
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -45945,7 +45945,7 @@ GameObject:
m_Component:
- component: {fileID: 4926610848449747640}
- component: {fileID: 9188114047427420724}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -71375,7 +71375,7 @@ GameObject:
m_Component:
- component: {fileID: 7662152191139975403}
- component: {fileID: 6830302151371473141}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_4
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -83492,7 +83492,7 @@ GameObject:
m_Component:
- component: {fileID: 7809844692213518709}
- component: {fileID: 4505455546857565809}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_2
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -111886,7 +111886,7 @@ GameObject:
m_Component:
- component: {fileID: 8754853922715629038}
- component: {fileID: 2561839350788404781}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_7
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -126916,7 +126916,7 @@ Camera:
m_Depth: 0
m_CullingMask:
serializedVersion: 2
- m_Bits: 16777280
+ m_Bits: 16778240
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
@@ -127006,6 +127006,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
subCamera: {fileID: 0}
+ isFishCamera: 0
--- !u!1 &8350492631816748217
GameObject:
m_ObjectHideFlags: 0
@@ -134175,7 +134176,7 @@ GameObject:
m_Component:
- component: {fileID: 8033707387404974704}
- component: {fileID: 7811082189917875340}
- m_Layer: 6
+ m_Layer: 10
m_Name: 6002_6
m_TagString: Untagged
m_Icon: {fileID: 0}
diff --git a/Assets/Framework/Tool/UITool/UIBase.cs b/Assets/Framework/Tool/UITool/UIBase.cs
index eb15e6206..21e85d2b6 100644
--- a/Assets/Framework/Tool/UITool/UIBase.cs
+++ b/Assets/Framework/Tool/UITool/UIBase.cs
@@ -1,13 +1,19 @@
-
+using System.Collections;
using UnityEngine;
///
-/// UI 基类:统一生命周期、显示/隐藏、入场出场动画钩子
+/// UI 基类:统一生命周期、显示/隐藏、入场出场动画钩子、按钮点击音效
///
public abstract class UIBase : MonoBehaviour
{
public UIPanel PanelType { get; private set; }
+ /// 面板内按钮点击音效 ID(tbaudio 表;60009=PW_Button)。0=不播
+ public int buttonClickAudioID = 60009;
+
+ /// 面板显示期间的点击音效兜底扫描协程
+ private Coroutine _clickSoundWatch;
+
// 初始化,由 UIManager 赋值
public void Init(UIPanel type)
{
@@ -24,7 +30,10 @@ public abstract class UIBase : MonoBehaviour
{
gameObject.SetActive(true);
transform.SetAsLastSibling(); // 每次激活都放到最上层
+ RefreshButtonClickSounds(); // ⭐ 先给面板内已有的按钮补齐点击音效
OnShow(args);
+ RefreshButtonClickSounds(); // ⭐ OnShow 中同步创建的按钮(如列表项)再补一遍
+ StartClickSoundWatch();
}
public virtual void Hide()
@@ -32,4 +41,32 @@ public abstract class UIBase : MonoBehaviour
OnHide();
gameObject.SetActive(false);
}
+
+ /// 给面板下所有 Button/Toggle 补齐点击音效(可重复调用,已挂 UIClickSound 的会跳过)
+ public void RefreshButtonClickSounds()
+ {
+ UIClickSound.AttachToAll(gameObject, buttonClickAudioID);
+ }
+
+ ///
+ /// 面板显示期间每 0.3 秒兜底扫描一次:列表项等运行时动态创建的按钮也能自动带上点击音效
+ /// (已挂 UIClickSound 的会跳过,扫描开销很小)。面板隐藏后循环自动退出。
+ ///
+ private void StartClickSoundWatch()
+ {
+ if (_clickSoundWatch != null)
+ StopCoroutine(_clickSoundWatch);
+ _clickSoundWatch = StartCoroutine(ClickSoundWatchRoutine());
+ }
+
+ private IEnumerator ClickSoundWatchRoutine()
+ {
+ var wait = new WaitForSecondsRealtime(0.3f);
+ while (gameObject.activeInHierarchy)
+ {
+ yield return wait;
+ RefreshButtonClickSounds();
+ }
+ _clickSoundWatch = null;
+ }
}
\ No newline at end of file
diff --git a/Assets/Framework/Tool/UITool/UIClickSound.cs b/Assets/Framework/Tool/UITool/UIClickSound.cs
new file mode 100644
index 000000000..7074c8d8e
--- /dev/null
+++ b/Assets/Framework/Tool/UITool/UIClickSound.cs
@@ -0,0 +1,56 @@
+using UnityEngine;
+using UnityEngine.EventSystems;
+using UnityEngine.UI;
+
+///
+/// 点击音效组件:挂在 Button/Toggle 上,玩家点击时播放 tbaudio 表中的按钮音效(默认 60009 = PW_Button)。
+/// ⭐ 由 UIBase 在面板显示时自动为所有子按钮补齐,无需手动挂载;列表项等运行时动态创建的按钮由面板兜底扫描补上。
+/// 监听指针点击而不是 onClick/onValueChanged:代码里 isOn = true / SetIsOnWithoutNotify 等程序化改动不会误发音效,
+/// 只在玩家真的点按时播放,同时与 Button/Toggle 自身的可交互规则保持一致。
+///
+[DisallowMultipleComponent]
+public class UIClickSound : MonoBehaviour, IPointerClickHandler
+{
+ /// 点击音效 ID(tbaudio 表;60009=PW_Button)。0=不播
+ public int clickAudioID = 60009;
+
+ public void OnPointerClick(PointerEventData eventData)
+ {
+ Play();
+ }
+
+ /// 播放点击音效
+ public void Play()
+ {
+ if (clickAudioID <= 0) return;
+
+ // 与 Button/Toggle 自身规则一致:不可交互的不发声
+ var selectable = GetComponent();
+ if (selectable != null && !selectable.interactable) return;
+
+ if (AudioManager.Instance == null) return;
+
+ // 音效尚未加载(如启动早期默认音频未就绪)时静默跳过,避免连点刷错误日志
+ if (AudioResourcesData.audioClipDic == null || !AudioResourcesData.audioClipDic.ContainsKey(clickAudioID))
+ return;
+
+ AudioManager.Instance.PlayerFX(clickAudioID);
+ }
+
+ /// 为 root 下所有 Button/Toggle 补齐点击音效(已有 UIClickSound 的跳过,可重复调用)
+ public static void AttachToAll(GameObject root, int audioID = 60009)
+ {
+ if (root == null || audioID <= 0) return;
+ foreach (var button in root.GetComponentsInChildren