1
This commit is contained in:
@@ -15,7 +15,7 @@ MonoBehaviour:
|
||||
m_DefaultGroup: a263e71fce79f2f4cb5b5f1fa6b7291a
|
||||
m_currentHash:
|
||||
serializedVersion: 2
|
||||
Hash: e88239bd385df7eeb8432db63ac72d7d
|
||||
Hash: 3b2ddf0423273ab9d68b887ff1cc1809
|
||||
m_OptimizeCatalogSize: 0
|
||||
m_BuildRemoteCatalog: 0
|
||||
m_BundleLocalCatalog: 0
|
||||
|
||||
@@ -51,6 +51,13 @@ MonoBehaviour:
|
||||
- PTCBZS
|
||||
- ZSYX
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 4ccd2be5159a8434689185dad378dd01
|
||||
m_Address: Assets/Art/FengLei/Audio/FLZY_bgm_default.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 55692611ed57c594fa0d7ecba7dcf704
|
||||
m_Address: Assets/MyGame/aa/Game/ZhanShen/Game/display_wargod_14901_0_dev.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -70,6 +77,41 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 8e07162e07c25974cae59b29d808aaf2
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_BgFree.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 964dfa5d6b6f9b947983721026622299
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Shoot.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- PTCBZS
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 98b1baf987b5c8942baa65ac95c04a15
|
||||
m_Address: Assets/Audios/HHWK/HHWK_ziyouxiBGM.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: a5531410c3acf2a45990658c82c7db06
|
||||
m_Address: Assets/Art/FengLei/Audio/FLZY_bgm_20.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b9f66d4b543101b4a8f6529f7e1c3fc8
|
||||
m_Address: Assets/Audios/HHWK/HHWK_youxiBGM2.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c0665105ad467074a9d951a074b6c71b
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Boss/XingJiXunHang/PW_Enemy_4000.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -77,6 +119,20 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c37a24b1b9382e04c86ecae674a7e071
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Bg.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ec58d755545af58489ae35ed82c1e07d
|
||||
m_Address: Assets/Audios/HHWK/HHWK_youxiBGM.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: fd77a1da22db21441ab0b116128a5e3a
|
||||
m_Address: Assets/MyGame/aa/Game/ZhanShen/Game/display_wargod_in_14053_0_dev.prefab
|
||||
m_ReadOnly: 0
|
||||
|
||||
@@ -206,13 +206,6 @@ MonoBehaviour:
|
||||
- FLZY
|
||||
- FishPrefab
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 4ccd2be5159a8434689185dad378dd01
|
||||
m_Address: Assets/Art/FengLei/Audio/FLZY_bgm_default.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 4f07750ceee651741ba0228ffd45e954
|
||||
m_Address: Assets/Art/FengLei/bundles/by_fish_base/bundles/prefab/fishbase@/12.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -528,13 +521,6 @@ MonoBehaviour:
|
||||
- FLZY
|
||||
- FishPrefab
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: a5531410c3acf2a45990658c82c7db06
|
||||
m_Address: Assets/Art/FengLei/Audio/FLZY_bgm_20.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: a718714f431d35247b001c93ad1683b9
|
||||
m_Address: Assets/Art/TuJianFishTexture/1595.png
|
||||
m_ReadOnly: 0
|
||||
|
||||
@@ -1200,13 +1200,6 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- HHWK
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 98b1baf987b5c8942baa65ac95c04a15
|
||||
m_Address: Assets/Audios/HHWK/HHWK_ziyouxiBGM.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 9a71ec700d97e9442be4e7ca1ec88b88
|
||||
m_Address: Assets/Art/HHWK/TuJianTexture/fish_1022 Variant.png
|
||||
m_ReadOnly: 0
|
||||
@@ -1501,13 +1494,6 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- HHWK
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b9f66d4b543101b4a8f6529f7e1c3fc8
|
||||
m_Address: Assets/Audios/HHWK/HHWK_youxiBGM2.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: bbddd2883bdfd1644ba49d4261a73d27
|
||||
m_Address: Assets/game_download/games/game177/prefab/fish/Game177_yilong_sj_2.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -1963,13 +1949,6 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- HHWK
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ec58d755545af58489ae35ed82c1e07d
|
||||
m_Address: Assets/Audios/HHWK/HHWK_youxiBGM.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ec8b574c01d5d354db2c62b9737d7c49
|
||||
m_Address: Assets/Art/HHWK/TuJianTexture/Fish_2009 Variant.png
|
||||
m_ReadOnly: 0
|
||||
|
||||
@@ -178,6 +178,12 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 1abfe2b699a5f764c896951d8bc859ad
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_1.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 1c991808cacc37a4884f95a3bd88a29c
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_FlyCoin.ogg
|
||||
m_ReadOnly: 0
|
||||
@@ -423,6 +429,12 @@ MonoBehaviour:
|
||||
- TuJian
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 3b6ce020d078b524ab9f8ea29d7fe431
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_zd.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 3c361fb6838b59a40b183bc1dbf9ae2a
|
||||
m_Address: Assets/Art/XJMH/pw/pw_prefab/game/enemy/XJMHEnemy/PW_Enemy_2.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -801,6 +813,12 @@ MonoBehaviour:
|
||||
- Audio
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 689bc9268484c3c4fab1743b9c99ee9e
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_2.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 68e9db06ce8a52043bce8e20dd84fb7e
|
||||
m_Address: Assets/Art/XJMH/pw/pw_prefab/game/enemy/XJMHEnemy/PW_Enemy_9.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -983,13 +1001,6 @@ MonoBehaviour:
|
||||
- Audio
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 8e07162e07c25974cae59b29d808aaf2
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_BgFree.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 8e9f22d048bac0a41a86b7a8f89efb0f
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Boss/XiaoChouPuKe/PW_Enemy_113.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -1032,11 +1043,10 @@ MonoBehaviour:
|
||||
- TuJian
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 964dfa5d6b6f9b947983721026622299
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Shoot.ogg
|
||||
- m_GUID: 9bf752fc3d63b374998b79d5b9e169a0
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_3.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 9cd48272e3e176b4b86b3ce703cfa03b
|
||||
@@ -1128,6 +1138,12 @@ MonoBehaviour:
|
||||
- TuJian
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: adf779a3413c62744b56021a0ad5c93d
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_ss.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: aea38e560a41ff44ba0a68d3b3194052
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_TextDragon.ogg
|
||||
m_ReadOnly: 0
|
||||
@@ -1156,6 +1172,12 @@ MonoBehaviour:
|
||||
- Audio
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b40ddb35d439d4546ab220424de7e930
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_sd.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b494aa76324a7c84ba8d1b26c9b3d231
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/handbook/PW_Enemy_32.png
|
||||
m_ReadOnly: 0
|
||||
@@ -1247,13 +1269,6 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c37a24b1b9382e04c86ecae674a7e071
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Bg.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- Audio
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c37fb4f7c76b1154a9d20ad974a14010
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/handbook/PW_Enemy_104.png
|
||||
m_ReadOnly: 0
|
||||
@@ -1525,6 +1540,12 @@ MonoBehaviour:
|
||||
- FishPrefab
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: e54c60eb5da5278478389292015f8e8a
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_4.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: e590af03990a88a4c842c66df7dde040
|
||||
m_Address: Assets/MyGame/aa/Game/XJMH/Sound/PW_Prop_GammaStorm_Attack.ogg
|
||||
m_ReadOnly: 0
|
||||
@@ -1733,48 +1754,6 @@ MonoBehaviour:
|
||||
- Audio
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b40ddb35d439d4546ab220424de7e930
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_sd.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 3b6ce020d078b524ab9f8ea29d7fe431
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_zd.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: adf779a3413c62744b56021a0ad5c93d
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/common/zd_jn_ss.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 1abfe2b699a5f764c896951d8bc859ad
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_1.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 689bc9268484c3c4fab1743b9c99ee9e
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_2.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 9bf752fc3d63b374998b79d5b9e169a0
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_3.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: e54c60eb5da5278478389292015f8e8a
|
||||
m_Address: Assets/Art/XJMH/pw/pw_sprite/freemodel/PW_FreeItem_4.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels:
|
||||
- XJMH
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
m_ReadOnly: 0
|
||||
m_Settings: {fileID: 11400000, guid: 3d7ea06370502a34e82011fabf822b45, type: 2}
|
||||
m_SchemaSet:
|
||||
|
||||
Binary file not shown.
@@ -3855,6 +3855,7 @@ GameObject:
|
||||
- component: {fileID: 2075409202}
|
||||
- component: {fileID: 2075409203}
|
||||
- component: {fileID: 2075409204}
|
||||
- component: {fileID: 2075409205}
|
||||
m_Layer: 0
|
||||
m_Name: Manager
|
||||
m_TagString: Untagged
|
||||
@@ -3917,7 +3918,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
cam: {fileID: 1985717029}
|
||||
enableBot: 0
|
||||
enableBot: 1
|
||||
botConfig:
|
||||
enabled: 1
|
||||
aiState: active
|
||||
@@ -4342,6 +4343,18 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
audioMixer: {fileID: 24100000, guid: ca43f9a7549657a49a2978e97c7a621a, type: 2}
|
||||
--- !u!114 &2075409205
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2075409194}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: bd70cad3c45605a4f824c9eaf1eb081d, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1001 &3569938244496052059
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f650bd50b29116409d46a87a7828a35
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,513 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.Profiling;
|
||||
|
||||
/// <summary>
|
||||
/// Addressables / AssetBundle 已加载包实时监控悬浮窗(调试插件)。
|
||||
///
|
||||
/// 【用途】
|
||||
/// 实时查看当前进程里加载了哪些 AA 包(bundle)、数量与内存概况,
|
||||
/// 用于定位"进房加载资源时内存暴涨 / 被 iOS jetsam 杀掉"这类问题。
|
||||
/// 注意:本项目所有 Addressables 组都是 LZMA 压缩,包一旦被打开就会整体解压进内存
|
||||
/// (实测 fish_hhwk 解压 487MB、fish_flzy 436MB、fish_xjmh 219MB),
|
||||
/// 所以看到哪个大包出现时,概览里的内存数字会立刻抬升,可直接对上。
|
||||
///
|
||||
/// 【使用方式】
|
||||
/// 1. 编辑器 Play / Development Build:自动出现在左上角,无需任何操作;
|
||||
/// 2. 其他构建(如 Release 真机包):加 AA_MONITOR 宏,或把本组件手动挂到任意常驻物体上。
|
||||
///
|
||||
/// 【操作】
|
||||
/// - 左上角小标签:可拖动;轻点 = 展开 / 收起面板(编辑器下 F9 也可切换)
|
||||
/// - 面板:上一页 / 下一页翻页;"导出日志"把完整列表 + 内存打入 Player Log(真机看 Xcode / idevice 日志)
|
||||
/// - 每次有新包加载 / 卸载时自动打日志(logOnChange,默认开)
|
||||
///
|
||||
/// 【注意】
|
||||
/// 项目 Active Input Handling = Input System(New),IMGUI 收不到点击事件,
|
||||
/// 所以本窗口的交互(拖动 / 轻点 / 翻页)全部用新输入系统自行采样实现,不依赖 GUILayout 按钮;
|
||||
/// 也因此悬浮层上的点击无法从游戏输入里"吃掉",测试时的小误触属正常现象。
|
||||
/// </summary>
|
||||
public class AABundleMonitor : MonoBehaviour
|
||||
{
|
||||
#region 配置
|
||||
|
||||
/// <summary>新包加载 / 卸载时自动输出日志(真机排查用,建议保持开启)</summary>
|
||||
public static bool logOnChange = true;
|
||||
|
||||
/// <summary>刷新间隔(秒):0.5 秒扫一次已加载包列表,避免每帧开销</summary>
|
||||
private const float RefreshInterval = 0.5f;
|
||||
|
||||
/// <summary>新增包高亮保持时长(秒)</summary>
|
||||
private const float HighlightDuration = 5f;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 自动安装
|
||||
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD || AA_MONITOR
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
private static void AutoInstall()
|
||||
{
|
||||
if (FindFirstObjectByType<AABundleMonitor>() != null) return;
|
||||
var go = new GameObject("[AABundleMonitor]");
|
||||
DontDestroyOnLoad(go);
|
||||
go.AddComponent<AABundleMonitor>();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region 数据
|
||||
|
||||
/// <summary>单个已加载包的记录</summary>
|
||||
private sealed class BundleRecord
|
||||
{
|
||||
public string name; // 完整 bundle 名(导出日志用)
|
||||
public string shortName; // 截断后的显示名
|
||||
public float firstSeen; // 首次出现时间(realtimeSinceStartup)
|
||||
public bool streamedScene; // 是否是场景包
|
||||
public string tag; // 内容标识(扫描包内资源路径得出,如 XJMH/HHWK/FLZY/LOGIN)
|
||||
public int assetCount; // 包内资源数量(GetAllAssetNames 只读目录,不会加载资源)
|
||||
public List<string> samplePaths; // 样例资源路径(导出日志用,帮助辨认包内容)
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, BundleRecord> _records = new Dictionary<string, BundleRecord>();
|
||||
private readonly List<BundleRecord> _sorted = new List<BundleRecord>(); // 按加载时间倒序(最新在前)
|
||||
private readonly HashSet<string> _loadedNow = new HashSet<string>(); // 本次扫描到的包名
|
||||
private readonly List<string> _removed = new List<string>(); // 本次扫描发现已卸载的包名
|
||||
|
||||
private float _appStartTime;
|
||||
private float _nextRefreshTime;
|
||||
|
||||
// 悬浮标签(可拖动)
|
||||
private Vector2 _ballPos = new Vector2(16f, 16f);
|
||||
private Rect _ballRect;
|
||||
private bool _ballDragging;
|
||||
private Vector2 _ballDragOffset;
|
||||
private bool _ballMoved;
|
||||
|
||||
// 面板
|
||||
private bool _panelOpen = true;
|
||||
private int _page;
|
||||
private int _rowsPerPage = 12;
|
||||
|
||||
// 上一帧 OnGUI 画出的按钮区域(供自采样点击命中,IMGUI 事件在本项目不可用)
|
||||
private Rect _prevPageRect, _nextPageRect, _exportRect;
|
||||
|
||||
// 样式缓存
|
||||
private GUIStyle _styleTitle, _styleLine, _styleOld, _styleNew, _styleButton, _styleWrap;
|
||||
|
||||
// 编辑器 PlayMode Script 名称(仅编辑器下有效,反射读取,失败为空)
|
||||
private string _editorPlayModeName;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_appStartTime = Time.realtimeSinceStartup;
|
||||
if (Application.isEditor) _editorPlayModeName = ReadEditorPlayModeName();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
PollPointer();
|
||||
if (Time.unscaledTime >= _nextRefreshTime)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 扫描已加载包
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
_nextRefreshTime = Time.unscaledTime + RefreshInterval;
|
||||
|
||||
int addedCount = 0;
|
||||
_loadedNow.Clear();
|
||||
var bundles = AssetBundle.GetAllLoadedAssetBundles();
|
||||
if (bundles != null)
|
||||
{
|
||||
foreach (var b in bundles)
|
||||
{
|
||||
if (b == null) continue;
|
||||
string n = b.name;
|
||||
_loadedNow.Add(n);
|
||||
|
||||
if (!_records.ContainsKey(n))
|
||||
{
|
||||
string baseName = n.EndsWith(".bundle") ? n.Substring(0, n.Length - 7) : n;
|
||||
var rec = new BundleRecord
|
||||
{
|
||||
name = n,
|
||||
shortName = baseName.Length > 16 ? baseName.Substring(0, 16) + "…" : baseName,
|
||||
firstSeen = Time.realtimeSinceStartup,
|
||||
streamedScene = b.isStreamedSceneAssetBundle
|
||||
};
|
||||
|
||||
// ⭐ 扫描包内资源清单辨认内容(GetAllAssetNames 只读包目录、不会把资源加载进内存)
|
||||
try
|
||||
{
|
||||
var assets = b.GetAllAssetNames();
|
||||
if (assets != null && assets.Length > 0)
|
||||
{
|
||||
rec.assetCount = assets.Length;
|
||||
rec.tag = GuessTag(assets);
|
||||
rec.samplePaths = new List<string>();
|
||||
for (int i = 0; i < assets.Length && rec.samplePaths.Count < 4; i++)
|
||||
rec.samplePaths.Add(assets[i]);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
_records[n] = rec;
|
||||
addedCount++;
|
||||
if (logOnChange)
|
||||
Debug.Log(string.IsNullOrEmpty(rec.tag)
|
||||
? $"[AA包监控] + {n}({rec.assetCount} 项)"
|
||||
: $"[AA包监控] + {n}【{rec.tag}】({rec.assetCount} 项)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 已卸载的包:从记录中移除
|
||||
_removed.Clear();
|
||||
foreach (var kv in _records)
|
||||
if (!_loadedNow.Contains(kv.Key)) _removed.Add(kv.Key);
|
||||
foreach (var n in _removed)
|
||||
{
|
||||
_records.Remove(n);
|
||||
if (logOnChange)
|
||||
Debug.Log($"[AA包监控] - {n}");
|
||||
}
|
||||
|
||||
// 排序:最新加载的排最前(进房时新增的包会直接顶到列表上方)
|
||||
_sorted.Clear();
|
||||
_sorted.AddRange(_records.Values);
|
||||
_sorted.Sort((a, b) => b.firstSeen.CompareTo(a.firstSeen));
|
||||
|
||||
if (logOnChange && (addedCount > 0 || _removed.Count > 0))
|
||||
Debug.Log($"[AA包监控] 变动:+{addedCount} / -{_removed.Count},当前共 {_records.Count} 个包 | {MemSummary()}");
|
||||
}
|
||||
|
||||
private static string MemSummary()
|
||||
{
|
||||
long allocated = Profiler.GetTotalAllocatedMemoryLong();
|
||||
long reserved = Profiler.GetTotalReservedMemoryLong();
|
||||
long mono = Profiler.GetMonoUsedSizeLong();
|
||||
return $"内存: 已分配 {allocated / 1048576f:F1}MB / 预留 {reserved / 1048576f:F1}MB / Mono {mono / 1048576f:F1}MB";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据包内资源路径猜内容标识:优先识别玩法关键词(XJMH/HHWK/FLZY),
|
||||
/// 否则取出现最多的路径段(如 login/home/zhanshen 等),识别不出返回空。
|
||||
/// </summary>
|
||||
private static string GuessTag(string[] assets)
|
||||
{
|
||||
int sample = Mathf.Min(assets.Length, 400);
|
||||
int xjmh = 0, hhwk = 0, flzy = 0;
|
||||
var freq = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
for (int i = 0; i < sample; i++)
|
||||
{
|
||||
string a = assets[i].ToLowerInvariant();
|
||||
if (a.Contains("xjmh")) xjmh++;
|
||||
else if (a.Contains("hhwk")) hhwk++;
|
||||
else if (a.Contains("flzy") || a.Contains("fenglei")) flzy++;
|
||||
|
||||
var parts = a.Split('/');
|
||||
for (int k = 1; k < parts.Length && k <= 3; k++)
|
||||
{
|
||||
string seg = parts[k];
|
||||
if (seg.Length == 0 || seg.Length > 12) continue;
|
||||
if (seg == "assets" || seg == "mygame" || seg == "art" || seg == "game" || seg == "aa" || seg == "ui") continue;
|
||||
freq.TryGetValue(seg, out int c);
|
||||
freq[seg] = c + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int minHits = Mathf.Max(3, sample / 5);
|
||||
if (xjmh >= minHits && xjmh >= hhwk && xjmh >= flzy) return "XJMH";
|
||||
if (hhwk >= minHits && hhwk >= xjmh && hhwk >= flzy) return "HHWK";
|
||||
if (flzy >= minHits && flzy >= xjmh && flzy >= hhwk) return "FLZY";
|
||||
|
||||
string best = null;
|
||||
int bestCount = 0;
|
||||
foreach (var kv in freq)
|
||||
if (kv.Value > bestCount) { bestCount = kv.Value; best = kv.Key; }
|
||||
return bestCount >= minHits ? best.ToUpperInvariant() : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器里显示当前 Addressables Play Mode Script 状态:
|
||||
/// Use Asset Database / Simulate Groups 模式下资源直接走工程读取、不产生 bundle,
|
||||
/// 本窗口看不到包属正常;0 个包时附带"去哪看真实包"的操作指引。
|
||||
/// </summary>
|
||||
private string EditorStatusLine()
|
||||
{
|
||||
if (!Application.isEditor) return null;
|
||||
string mode = string.IsNullOrEmpty(_editorPlayModeName) ? "未知" : _editorPlayModeName;
|
||||
if (_records.Count == 0 && mode != "Use Existing Build")
|
||||
return $"编辑器 PlayMode:{mode} —— 此模式资源不走 bundle,0 个包属正常。" +
|
||||
"要看真实包:构建 Windows 内容后切 Use Existing Build,或用真机 Dev Build";
|
||||
return $"编辑器 PlayMode:{mode}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反射读取 Addressables 编辑器设置里的 PlayMode Script 索引
|
||||
/// (0=Use Asset Database 1=Simulate Groups 2=Use Existing Build 3=Default Build Script)。
|
||||
/// 用反射是为了不依赖 Unity.Addressables.Editor 程序集,运行时/真机编译不受影响。
|
||||
/// </summary>
|
||||
private static string ReadEditorPlayModeName()
|
||||
{
|
||||
try
|
||||
{
|
||||
var t = Type.GetType("UnityEditor.AddressableAssets.Settings.ProjectConfigData, Unity.Addressables.Editor");
|
||||
var prop = t?.GetProperty("ActivePlayModeIndex", BindingFlags.Public | BindingFlags.Static);
|
||||
if (prop != null)
|
||||
{
|
||||
int idx = (int)prop.GetValue(null);
|
||||
switch (idx)
|
||||
{
|
||||
case 0: return "Use Asset Database";
|
||||
case 1: return "Simulate Groups";
|
||||
case 2: return "Use Existing Build";
|
||||
case 3: return "Default Build Script";
|
||||
}
|
||||
return $"index={idx}";
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return "未知";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 输入(新输入系统自采样:拖动标签 / 轻点切换 / 翻页 / 导出)
|
||||
|
||||
private void PollPointer()
|
||||
{
|
||||
// 键盘便捷开关(编辑器 / 带键盘设备;真机为 null 自动跳过)
|
||||
var kb = Keyboard.current;
|
||||
if (kb != null && kb.f9Key.wasPressedThisFrame)
|
||||
_panelOpen = !_panelOpen;
|
||||
|
||||
Vector2 screenPos;
|
||||
bool isPressed, wasPressed, wasReleased;
|
||||
|
||||
var ts = Touchscreen.current;
|
||||
var m = Mouse.current;
|
||||
|
||||
bool touchActive = ts != null &&
|
||||
(ts.primaryTouch.press.isPressed || ts.primaryTouch.press.wasPressedThisFrame || ts.primaryTouch.press.wasReleasedThisFrame);
|
||||
|
||||
if (touchActive)
|
||||
{
|
||||
screenPos = ts.primaryTouch.position.ReadValue();
|
||||
isPressed = ts.primaryTouch.press.isPressed;
|
||||
wasPressed = ts.primaryTouch.press.wasPressedThisFrame;
|
||||
wasReleased = ts.primaryTouch.press.wasReleasedThisFrame;
|
||||
}
|
||||
else if (m != null)
|
||||
{
|
||||
screenPos = m.position.ReadValue();
|
||||
isPressed = m.leftButton.isPressed;
|
||||
wasPressed = m.leftButton.wasPressedThisFrame;
|
||||
wasReleased = m.leftButton.wasReleasedThisFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 输入系统的坐标原点在左下,OnGUI 在左上
|
||||
var guiPos = new Vector2(screenPos.x, Screen.height - screenPos.y);
|
||||
|
||||
if (wasPressed)
|
||||
OnPointerPressed(guiPos);
|
||||
|
||||
if (_ballDragging)
|
||||
{
|
||||
if (isPressed)
|
||||
{
|
||||
Vector2 target = guiPos - _ballDragOffset;
|
||||
if (Vector2.Distance(target, _ballPos) > 6f) _ballMoved = true;
|
||||
_ballPos = ClampToScreen(target);
|
||||
}
|
||||
else if (wasReleased)
|
||||
{
|
||||
_ballDragging = false;
|
||||
if (!_ballMoved) _panelOpen = !_panelOpen; // 轻点 = 切换面板
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerPressed(Vector2 guiPos)
|
||||
{
|
||||
_ballDragging = false;
|
||||
_ballMoved = false;
|
||||
|
||||
if (_ballRect.Contains(guiPos))
|
||||
{
|
||||
_ballDragging = true;
|
||||
_ballDragOffset = guiPos - _ballPos;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_panelOpen) return;
|
||||
|
||||
if (_prevPageRect.Contains(guiPos)) { _page--; return; }
|
||||
if (_nextPageRect.Contains(guiPos)) { _page++; return; }
|
||||
if (_exportRect.Contains(guiPos)) { ExportLog(); return; }
|
||||
}
|
||||
|
||||
private static Vector2 ClampToScreen(Vector2 pos)
|
||||
{
|
||||
return new Vector2(
|
||||
Mathf.Clamp(pos.x, 0f, Mathf.Max(0f, Screen.width - 160f)),
|
||||
Mathf.Clamp(pos.y, 0f, Mathf.Max(0f, Screen.height - 64f)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 绘制
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EnsureStyles();
|
||||
DrawBall();
|
||||
if (_panelOpen)
|
||||
DrawPanel();
|
||||
}
|
||||
|
||||
private void DrawBall()
|
||||
{
|
||||
_ballRect = new Rect(_ballPos.x, _ballPos.y, 152f, 56f);
|
||||
|
||||
GUI.color = new Color(0f, 0f, 0f, 0.72f);
|
||||
GUI.DrawTexture(_ballRect, Texture2D.whiteTexture);
|
||||
GUI.color = Color.white;
|
||||
|
||||
GUI.Label(new Rect(_ballRect.x + 12f, _ballRect.y + 3f, 140f, 26f), $"AA包 {_records.Count}", _styleTitle);
|
||||
GUI.Label(new Rect(_ballRect.x + 12f, _ballRect.y + 28f, 140f, 24f), _panelOpen ? "点我收起" : "点我展开", _styleLine);
|
||||
}
|
||||
|
||||
private void DrawPanel()
|
||||
{
|
||||
float w = Mathf.Min(Screen.width - 32f, 980f);
|
||||
float h = Mathf.Min(Screen.height - 140f, 1500f);
|
||||
float x = Mathf.Clamp(_ballPos.x, 8f, Mathf.Max(8f, Screen.width - w - 8f));
|
||||
float y = Mathf.Clamp(_ballPos.y + 64f, 8f, Mathf.Max(8f, Screen.height - h - 8f));
|
||||
var panel = new Rect(x, y, w, h);
|
||||
|
||||
GUI.color = new Color(0f, 0f, 0f, 0.84f);
|
||||
GUI.DrawTexture(panel, Texture2D.whiteTexture);
|
||||
GUI.color = Color.white;
|
||||
|
||||
string status = EditorStatusLine();
|
||||
float statusH = status == null ? 0f : 58f;
|
||||
float headerH = 108f + statusH;
|
||||
const float footerH = 64f;
|
||||
const float rowH = 30f;
|
||||
|
||||
// ---- 概要 ----
|
||||
GUI.Label(new Rect(panel.x + 16f, panel.y + 8f, w - 32f, 30f), $"AA 已加载包监控 共 {_records.Count} 个", _styleTitle);
|
||||
GUI.Label(new Rect(panel.x + 16f, panel.y + 42f, w - 32f, 26f), MemSummary(), _styleLine);
|
||||
GUI.Label(new Rect(panel.x + 16f, panel.y + 70f, w - 32f, 26f),
|
||||
$"运行 {(Time.realtimeSinceStartup - _appStartTime):F0}s 黄色 = 近 {HighlightDuration:F0} 秒新增(新加载的包在列表最上方)", _styleLine);
|
||||
if (status != null)
|
||||
GUI.Label(new Rect(panel.x + 16f, panel.y + 96f, w - 32f, statusH), status, _styleWrap);
|
||||
|
||||
// ---- 列表分页 ----
|
||||
_rowsPerPage = Mathf.Max(4, (int)((panel.height - headerH - footerH - 12f) / rowH));
|
||||
int totalPages = Mathf.Max(1, Mathf.CeilToInt(_sorted.Count / (float)_rowsPerPage));
|
||||
_page = Mathf.Clamp(_page, 0, totalPages - 1);
|
||||
int start = _page * _rowsPerPage;
|
||||
|
||||
float rowY = panel.y + headerH;
|
||||
for (int i = 0; i < _rowsPerPage; i++)
|
||||
{
|
||||
int idx = start + i;
|
||||
if (idx >= _sorted.Count) break;
|
||||
|
||||
var r = _sorted[idx];
|
||||
bool isNew = Time.realtimeSinceStartup - r.firstSeen < HighlightDuration;
|
||||
var style = isNew ? _styleNew : _styleOld;
|
||||
string sceneTag = r.streamedScene ? "[场景] " : "";
|
||||
string info = string.IsNullOrEmpty(r.tag)
|
||||
? (r.assetCount > 0 ? $"{r.assetCount}项" : "")
|
||||
: $"【{r.tag}】{r.assetCount}项";
|
||||
string text = $"{sceneTag}{r.shortName} {info} (+{r.firstSeen - _appStartTime:F0}s)";
|
||||
GUI.Label(new Rect(panel.x + 18f, rowY, w - 36f, rowH), text, style);
|
||||
rowY += rowH;
|
||||
}
|
||||
|
||||
// ---- 底部按钮(自采样点击,IMGUI 按钮不可用)----
|
||||
float btnY = panel.yMax - 52f;
|
||||
float btnW = 150f;
|
||||
_prevPageRect = new Rect(panel.x + 16f, btnY, btnW, 44f);
|
||||
_nextPageRect = new Rect(panel.x + 16f + btnW + 12f, btnY, btnW, 44f);
|
||||
_exportRect = new Rect(panel.xMax - btnW - 16f, btnY, btnW, 44f);
|
||||
|
||||
DrawFakeButton(_prevPageRect, "上一页");
|
||||
DrawFakeButton(_nextPageRect, "下一页");
|
||||
DrawFakeButton(_exportRect, "导出日志");
|
||||
|
||||
GUI.Label(new Rect(panel.x + 16f + (btnW + 12f) * 2f, btnY + 10f, 160f, 26f), $"{_page + 1} / {totalPages}", _styleLine);
|
||||
}
|
||||
|
||||
private void DrawFakeButton(Rect r, string text)
|
||||
{
|
||||
GUI.color = new Color(1f, 1f, 1f, 0.22f);
|
||||
GUI.DrawTexture(r, Texture2D.whiteTexture);
|
||||
GUI.color = Color.white;
|
||||
GUI.Label(new Rect(r.x, r.y + 8f, r.width, 28f), text, _styleButton);
|
||||
}
|
||||
|
||||
private void EnsureStyles()
|
||||
{
|
||||
if (_styleTitle != null) return;
|
||||
|
||||
_styleTitle = new GUIStyle(GUI.skin.label) { fontSize = 26, fontStyle = FontStyle.Bold };
|
||||
_styleTitle.normal.textColor = Color.white;
|
||||
|
||||
_styleLine = new GUIStyle(GUI.skin.label) { fontSize = 22 };
|
||||
_styleLine.normal.textColor = new Color(0.82f, 0.9f, 1f);
|
||||
|
||||
_styleOld = new GUIStyle(GUI.skin.label) { fontSize = 23 };
|
||||
_styleOld.normal.textColor = Color.white;
|
||||
|
||||
_styleNew = new GUIStyle(GUI.skin.label) { fontSize = 23, fontStyle = FontStyle.Bold };
|
||||
_styleNew.normal.textColor = new Color(1f, 0.82f, 0.2f);
|
||||
|
||||
_styleButton = new GUIStyle(GUI.skin.label) { fontSize = 24, alignment = TextAnchor.UpperCenter };
|
||||
_styleButton.normal.textColor = Color.white;
|
||||
|
||||
_styleWrap = new GUIStyle(GUI.skin.label) { fontSize = 20, wordWrap = true };
|
||||
_styleWrap.normal.textColor = new Color(0.95f, 0.9f, 0.62f);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 导出
|
||||
|
||||
private void ExportLog()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"[AA包监控] 导出时间 {DateTime.Now:yyyy-MM-dd HH:mm:ss},共 {_records.Count} 个包 | {MemSummary()}");
|
||||
foreach (var r in _sorted)
|
||||
sb.AppendLine($" {(r.streamedScene ? "[场景] " : "")}{r.name} (+{r.firstSeen - _appStartTime:F1}s)");
|
||||
|
||||
string text = sb.ToString();
|
||||
Debug.Log(text);
|
||||
try { GUIUtility.systemCopyBuffer = text; } catch { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd70cad3c45605a4f824c9eaf1eb081d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -261,12 +261,15 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
if (btn_TurretMinus != null)
|
||||
btn_TurretMinus.onClick.AddListener(() => ChangeTurretMinusConsumeNum());
|
||||
|
||||
// ⭐ 自动攻击开关:先检测自身 GameObject 激活状态,没激活就激活(预制体/外部可能把它藏了,
|
||||
// 隐藏状态下点不到,自动攻击无法开关);再挂监听:关闭时本地座位炮台切回 Idle(原 GameMainPanel 的 toggle_SkillAuto 逻辑)
|
||||
// ⭐ 自动攻击开关:默认隐藏,等玩家入座时由 ShowPlayer 按"是否本地座位"决定显隐。
|
||||
// ⚠️ 以前这里是"没激活就无条件激活"(为修预制体把按钮藏了、点不到的问题),
|
||||
// 但第二个人加入时他的座位才第一次激活、Awake 此刻才执行 → 会把他的"自动"按钮也打开,
|
||||
// 屏幕上出现两个"自动"按钮。改为默认隐藏 + 入座时按本地/他座显隐(本地按钮不会再被藏)。
|
||||
// 监听照旧:关闭时本地座位炮台切回 Idle(原 GameMainPanel 的 toggle_SkillAuto 逻辑)
|
||||
if (toggle_AutoAttack != null)
|
||||
{
|
||||
if (!toggle_AutoAttack.gameObject.activeSelf)
|
||||
toggle_AutoAttack.gameObject.SetActive(true);
|
||||
if (toggle_AutoAttack.gameObject.activeSelf)
|
||||
toggle_AutoAttack.gameObject.SetActive(false);
|
||||
toggle_AutoAttack.onValueChanged.AddListener(OnAutoAttackToggleChanged);
|
||||
}
|
||||
|
||||
@@ -1101,6 +1104,11 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
transform.GetChild(1).gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// ⭐ "自动"按钮只属于本地玩家:本地座位显示、其他座位隐藏
|
||||
// (第二个人加入时他的座位才第一次激活,Awake 已改为默认隐藏,这里按座位归属再定一次)
|
||||
if (toggle_AutoAttack != null)
|
||||
toggle_AutoAttack.gameObject.SetActive(user == GameManager.Instance?.user?.id);
|
||||
|
||||
// 如果是本地玩家的座位,自动注册并加载装备
|
||||
if (user == GameManager.Instance?.user?.id)
|
||||
{
|
||||
@@ -1134,6 +1142,10 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
/// </summary>
|
||||
public void ShowWaiting()
|
||||
{
|
||||
// ⭐ 离座:自动按钮一并隐藏(XJMH 也要处理——空座位不该留"自动"按钮)
|
||||
if (toggle_AutoAttack != null)
|
||||
toggle_AutoAttack.gameObject.SetActive(false);
|
||||
|
||||
if (turretControlMode == TurretControlMode.XJMH) return;
|
||||
|
||||
if (transform.childCount > 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json;
|
||||
using Spine.Unity;
|
||||
using System;
|
||||
using System.Collections;
|
||||
@@ -20,10 +20,20 @@ public class AudioResourcesData
|
||||
static Dictionary<int, AudioClip> audioClipDefaultDic=new Dictionary<int, AudioClip>();
|
||||
static Dictionary<int, AudioClip> audioClipGameDic=new Dictionary<int, AudioClip>();
|
||||
const string Audio_AALabel="Audio";
|
||||
|
||||
// ⭐ 句柄显式管理(修复"包只增不减"的根源):
|
||||
// 之前 Load 的句柄直接丢弃(泄漏,包永不卸载),UnLoad 再重新 Load 一遍拿句柄释放
|
||||
// (净引用数 0,等于什么都没卸载)。现在:加载时保存句柄,卸载时真正 Release。
|
||||
// 注意:游戏音频物理上打在鱼包里(Audio+玩法 交集 = 鱼包),释放本句柄是鱼包能卸载的前提之一。
|
||||
/// <summary>默认音频句柄(Audio+Default,进程常驻,不卸载)</summary>
|
||||
static AsyncOperationHandle<IList<AudioClip>> _defaultAudioHandle;
|
||||
/// <summary>当前玩法游戏音频句柄(Audio+玩法,进房加载/离房释放)</summary>
|
||||
static AsyncOperationHandle<IList<AudioClip>> _gameAudioHandle;
|
||||
|
||||
static AudioResourcesData()
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
//这里要添加默认的音效 背景 按钮点击
|
||||
LoadDefaultAudioGame();
|
||||
}
|
||||
@@ -39,7 +49,7 @@ public class AudioResourcesData
|
||||
name_IDDic[item.audioResourcesPath]=item.audioID;
|
||||
}
|
||||
var keys = new List<string> { Audio_AALabel, "Default" };
|
||||
await Addressables.LoadAssetsAsync<AudioClip>(keys, audio =>
|
||||
_defaultAudioHandle = Addressables.LoadAssetsAsync<AudioClip>(keys, audio =>
|
||||
{
|
||||
Debug.Log("加载音频: " + audio.name);
|
||||
if (name_IDDic.ContainsKey(audio.name))
|
||||
@@ -47,7 +57,8 @@ public class AudioResourcesData
|
||||
Debug.Log("加载音频ID: " + name_IDDic[audio.name]);
|
||||
audioClipDefaultDic.Add(name_IDDic[audio.name],audio);
|
||||
}
|
||||
}, MergeMode.Intersection).Task;
|
||||
}, MergeMode.Intersection);
|
||||
await _defaultAudioHandle.Task;
|
||||
foreach (var item in audioClipDefaultDic)
|
||||
{
|
||||
audioClipDic.Add(item.Key, item.Value);
|
||||
@@ -82,13 +93,22 @@ public class AudioResourcesData
|
||||
|
||||
try
|
||||
{
|
||||
await Addressables.LoadAssetsAsync<AudioClip>(keys, audio =>
|
||||
// ⭐ 防御:上一轮句柄未释放(如离房被跳过)时先释放,避免引用计数累加
|
||||
if (_gameAudioHandle.IsValid())
|
||||
Addressables.Release(_gameAudioHandle);
|
||||
|
||||
// ⭐ 双标签交集(Audio + 当前玩法):只加载当前玩法标记的音频。
|
||||
// Union 会按 "Audio" 标签把其它玩法的音频包一并打开,
|
||||
// 而这些音频物理上和鱼的 Prefab 打在同一个 LZMA 包里 → 整包解压进内存导致 iOS 被杀
|
||||
// 句柄保存到 _gameAudioHandle,离房时 UnLoadAudioGame 真正释放 → 鱼包才能卸载
|
||||
_gameAudioHandle = Addressables.LoadAssetsAsync<AudioClip>(keys, audio =>
|
||||
{
|
||||
if (name_IDDic != null && name_IDDic.ContainsKey(audio.name))
|
||||
{
|
||||
audioClipGameDic[name_IDDic[audio.name]] = audio;
|
||||
}
|
||||
}, MergeMode.Union).Task;
|
||||
}, MergeMode.Intersection);
|
||||
await _gameAudioHandle.Task;
|
||||
|
||||
audioClipDic = new Dictionary<int, AudioClip>();
|
||||
if (audioClipDefaultDic != null)
|
||||
@@ -107,40 +127,21 @@ public class AudioResourcesData
|
||||
Debug.LogError($"加载游戏音频失败: {e.Message}");
|
||||
}
|
||||
}
|
||||
public static async Task UnLoadAudioGame()
|
||||
public static Task UnLoadAudioGame()
|
||||
{
|
||||
GameType gameType = GameManager.Instance.gameData.currGameType;
|
||||
var keys = new List<string> { Audio_AALabel, gameType.ToString() };
|
||||
// ⭐ 真正的卸载:释放加载时保存的句柄(引用归零后 Audio+玩法 命中的 bundle 才会真正卸载)。
|
||||
// 旧实现"重新 Load 一遍拿句柄再 Release"是净 0 操作,什么都卸不掉。
|
||||
if (_gameAudioHandle.IsValid())
|
||||
Addressables.Release(_gameAudioHandle);
|
||||
|
||||
// 加载对应的句柄(只是为了拿到引用,之后释放)
|
||||
AsyncOperationHandle<IList<AudioClip>> handle = Addressables.LoadAssetsAsync<AudioClip>(keys, null, MergeMode.Intersection);
|
||||
await handle.Task;
|
||||
// 清空游戏音频字典(包卸载后 AudioClip 对象已失效,残留引用会导致播放 null)
|
||||
audioClipGameDic.Clear();
|
||||
|
||||
// 遍历卸载对应的音频
|
||||
foreach (var audio in handle.Result)
|
||||
{
|
||||
if (name_IDDic.ContainsKey(audio.name))
|
||||
{
|
||||
int id = name_IDDic[audio.name];
|
||||
if (audioClipGameDic.ContainsKey(id))
|
||||
{
|
||||
audioClipGameDic.Remove(id);
|
||||
Debug.Log($"卸载音频: {audio.name} (ID={id})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 释放 Addressables 资源句柄
|
||||
Addressables.Release(handle);
|
||||
|
||||
// 重建总字典:保留默认音频 + 剩余游戏音频
|
||||
// 重建总字典:只保留默认音频
|
||||
audioClipDic = new Dictionary<int, AudioClip>(audioClipDefaultDic);
|
||||
foreach (var item in audioClipGameDic)
|
||||
{
|
||||
audioClipDic[item.Key] = item.Value;
|
||||
}
|
||||
|
||||
Debug.Log("卸载完成,当前音频数量:" + audioClipDic.Count);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using static UnityEngine.AddressableAssets.Addressables;
|
||||
|
||||
[Serializable]
|
||||
@@ -77,6 +78,14 @@ public class FishResourcesData
|
||||
public static Dictionary<int, FishResourcesData> fishResourcesDatasDic;//id--FishResourcesData
|
||||
public static Dictionary<int, Sprite> fishResourcesSpritesDic;//id--Sprite
|
||||
private static Dictionary<int, SkeletonDataAsset> diePrefabDic;//id--SkeletonDataAsset
|
||||
|
||||
// ⭐ 句柄显式管理(修复"包只增不减"的根源):
|
||||
// 旧实现加载完立即 Release 句柄,但 fishPrefabDic 还持有 prefab 引用 ——
|
||||
// 包没被卸载全靠 AudioResourcesData 泄漏的音频句柄"误打误撞"撑着(音频物理上就在鱼包里)。
|
||||
// 现在:加载时保存句柄(prefab/dieSpine/sprite 三类),离房时 UnLoadFishAssetsData 统一 Release,
|
||||
// 引用归零后鱼包真正从内存卸载 —— 依次进所有玩法不再累加内存。
|
||||
private static readonly List<AsyncOperationHandle> _fishHandles = new List<AsyncOperationHandle>();
|
||||
|
||||
public static async Task LoadFishAssetsData()
|
||||
{
|
||||
// 清空对象池
|
||||
@@ -86,6 +95,13 @@ public class FishResourcesData
|
||||
diePrefabDic = new Dictionary<int, SkeletonDataAsset>();
|
||||
fishResourcesSpritesDic = new Dictionary<int, Sprite>();
|
||||
|
||||
// ⭐ 防御:上一轮句柄未释放(如离房流程被跳过)时先释放,避免引用计数累加
|
||||
foreach (var h in _fishHandles)
|
||||
{
|
||||
if (h.IsValid()) Addressables.Release(h);
|
||||
}
|
||||
_fishHandles.Clear();
|
||||
|
||||
// ---------------- 1. 预下载所有依赖资源(关键) ----------------
|
||||
var labels = new List<string>
|
||||
{
|
||||
@@ -120,7 +136,8 @@ public class FishResourcesData
|
||||
}, MergeMode.Intersection);
|
||||
|
||||
await prefabHandle.Task;
|
||||
Addressables.Release(prefabHandle);
|
||||
// ⭐ 不再立即 Release:保存句柄保持包存活,离房时统一卸载
|
||||
_fishHandles.Add(prefabHandle);
|
||||
Debug.Log($"Prefab 加载完成,共 {fishPrefabDic.Count} 个");
|
||||
|
||||
// ---------------- 3. 加载死亡 Spine 动效 ----------------
|
||||
@@ -138,7 +155,7 @@ public class FishResourcesData
|
||||
}, MergeMode.Intersection);
|
||||
|
||||
await dieHandle.Task;
|
||||
Addressables.Release(dieHandle);
|
||||
_fishHandles.Add(dieHandle);
|
||||
Debug.Log($"死亡 Spine 加载完成,共 {diePrefabDic.Count} 个");
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -159,7 +176,7 @@ public class FishResourcesData
|
||||
}, MergeMode.Intersection);
|
||||
|
||||
await spriteHandle.Task;
|
||||
Addressables.Release(spriteHandle);
|
||||
_fishHandles.Add(spriteHandle);
|
||||
Debug.Log($"Sprite 加载完成,共 {fishResourcesSpritesDic.Count} 个");
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -171,81 +188,26 @@ public class FishResourcesData
|
||||
}
|
||||
|
||||
|
||||
public static async Task UnLoadFishAssetsData()
|
||||
public static Task UnLoadFishAssetsData()
|
||||
{
|
||||
// ⭐ 真正的卸载:释放加载时保存的全部句柄(引用归零后鱼包才会真正卸载)。
|
||||
// 旧实现"重新 Load 一遍拿句柄再 Release"是净 0 操作,什么都卸不掉。
|
||||
Pool.Instance.Clear();
|
||||
|
||||
// 卸载 Prefab
|
||||
var keys = new List<string> { prefabFish_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
|
||||
var prefabHandle = Addressables.LoadAssetsAsync<GameObject>(keys, null, MergeMode.Intersection);
|
||||
await prefabHandle.Task;
|
||||
|
||||
if (prefabHandle.Result != null)
|
||||
foreach (var h in _fishHandles)
|
||||
{
|
||||
foreach (var prefab in prefabHandle.Result)
|
||||
{
|
||||
if (FishResourcesPrefabsDic.TryGetValue(prefab.name, out int id))
|
||||
{
|
||||
if (fishPrefabDic.Remove(id))
|
||||
{
|
||||
Debug.Log($"卸载鱼Prefab: {prefab.name} (ID={id})");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (h.IsValid())
|
||||
Addressables.Release(h);
|
||||
}
|
||||
Addressables.Release(prefabHandle);
|
||||
_fishHandles.Clear();
|
||||
|
||||
// 卸载死亡 Spine 动效
|
||||
keys = new List<string> { dieSpine_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
|
||||
var dieHandle = Addressables.LoadAssetsAsync<SkeletonDataAsset>(keys, null, MergeMode.Intersection);
|
||||
await dieHandle.Task;
|
||||
// ⭐ 清空字典(包卸载后对象已失效,残留引用会指向已销毁资源)
|
||||
fishPrefabDic?.Clear();
|
||||
diePrefabDic?.Clear();
|
||||
fishResourcesSpritesDic?.Clear();
|
||||
|
||||
if (dieHandle.Result != null)
|
||||
{
|
||||
foreach (var data in dieHandle.Result)
|
||||
{
|
||||
if (FishResourcesSpineDieDic.TryGetValue(data.name, out int id))
|
||||
{
|
||||
if (diePrefabDic.Remove(id))
|
||||
{
|
||||
Debug.Log($"卸载鱼死亡动效: {data.name} (ID={id})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Addressables.Release(dieHandle);
|
||||
|
||||
// 卸载鱼 Sprite
|
||||
// ⭐ try-catch 防护:Addressables 可能找不到 TuJian+游戏类型 交集的 Sprite,
|
||||
// 抛 InvalidKeyException 导致整个 UnLoadFishAssetsData 中断,后续清理无法执行。
|
||||
// Sprite 加载时已有 try-catch,卸载时也应对称处理
|
||||
try
|
||||
{
|
||||
keys = new List<string> { Sprite_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
|
||||
var spriteHandle = Addressables.LoadAssetsAsync<Sprite>(keys, null, MergeMode.Intersection);
|
||||
await spriteHandle.Task;
|
||||
|
||||
if (spriteHandle.Result != null)
|
||||
{
|
||||
foreach (var sprite in spriteHandle.Result)
|
||||
{
|
||||
if (FishResourcesSpriteDic.TryGetValue(sprite.name, out int id))
|
||||
{
|
||||
if (fishResourcesSpritesDic.Remove(id))
|
||||
{
|
||||
Debug.Log($"卸载鱼Sprite: {sprite.name} (ID={id})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Addressables.Release(spriteHandle);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[FishResourcesData] Sprite 卸载失败(游戏类型={GameManager.Instance.gameData.currGameType}),跳过此项: {e.Message}");
|
||||
}
|
||||
|
||||
Debug.Log($"卸载完成,剩余Prefab数量: {fishPrefabDic.Count}, 死亡动效数量: {diePrefabDic.Count}, Sprite数量: {fishResourcesSpritesDic.Count}");
|
||||
Debug.Log($"[FishResourcesData] 鱼资源卸载完成");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11994,7 +11994,7 @@ MonoBehaviour:
|
||||
drawLineSegments: 60
|
||||
drawLineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
|
||||
bossName:
|
||||
isToUI: 1
|
||||
isToUI: 0
|
||||
tMP_CurrBossScore: {fileID: 0}
|
||||
currBossScoreValue: 0
|
||||
bossScoreValue: 0
|
||||
|
||||
@@ -1035,6 +1035,11 @@ PrefabInstance:
|
||||
propertyPath: m_Layer
|
||||
value: 6
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1758318735507541674, guid: f11065bf68488f64e9d9b8acc8c4caff,
|
||||
type: 3}
|
||||
propertyPath: m_TagString
|
||||
value: Fish
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1848564584791591582, guid: f11065bf68488f64e9d9b8acc8c4caff,
|
||||
type: 3}
|
||||
propertyPath: m_Layer
|
||||
|
||||
@@ -14838,7 +14838,7 @@ MonoBehaviour:
|
||||
drawLineSegments: 60
|
||||
drawLineColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
|
||||
bossName:
|
||||
isToUI: 1
|
||||
isToUI: 0
|
||||
tMP_CurrBossScore: {fileID: 0}
|
||||
currBossScoreValue: 0
|
||||
bossScoreValue: 0
|
||||
|
||||
@@ -192,7 +192,8 @@ public class RotatePan_XJMH : BJRedPacketEvent
|
||||
// 内圈:可在选项范围内随机偏移(中心角度 ± 半角)
|
||||
float neiCenterAngle = OptionIdToAngle((int)_innerOpt.optionId, innerCount);
|
||||
float neiHalfAngle = (360f / innerCount) / 2f;
|
||||
float neiTargetAngle = neiCenterAngle + Random.Range(-neiHalfAngle, neiHalfAngle);
|
||||
//float neiTargetAngle = neiCenterAngle + Random.Range(-neiHalfAngle, neiHalfAngle);
|
||||
float neiTargetAngle = neiCenterAngle;
|
||||
Debug.Log($"[XingYunFeiDie] 内圈目标角度: OptionId={_innerOpt.optionId} count={innerCount} 中心={neiCenterAngle}° 随机后={neiTargetAngle}°");
|
||||
|
||||
// 先转内圈
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 84a92b25f83d49b9bc132d206b370281, type: 3}
|
||||
m_Name: 592228afbce16145
|
||||
m_EditorClassIdentifier:
|
||||
hashCode: -1919871374
|
||||
material: {fileID: 8548082164682178837}
|
||||
materialHashCode: 0
|
||||
m_Version: 1.1.0
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName:
|
||||
m_StyleName:
|
||||
m_PointSize: 0
|
||||
m_Scale: 0
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 0
|
||||
m_AscentLine: 0
|
||||
m_CapLine: 0
|
||||
m_MeanLine: 0
|
||||
m_Baseline: 0
|
||||
m_DescentLine: 0
|
||||
m_SuperscriptOffset: 0
|
||||
m_SuperscriptSize: 0
|
||||
m_SubscriptOffset: 0
|
||||
m_SubscriptSize: 0
|
||||
m_UnderlineOffset: 0
|
||||
m_UnderlineThickness: 0
|
||||
m_StrikethroughOffset: 0
|
||||
m_StrikethroughThickness: 0
|
||||
m_TabWidth: 0
|
||||
spriteSheet: {fileID: 2800000, guid: 1b70eadb887fad44abd4ece91ee38a6d, type: 3}
|
||||
m_SpriteCharacterTable:
|
||||
- m_ElementType: 2
|
||||
m_Unicode: 65534
|
||||
m_GlyphIndex: 0
|
||||
m_Scale: 1
|
||||
m_Name: 592228afbce16145
|
||||
m_HashCode: -1919871374
|
||||
m_SpriteGlyphTable:
|
||||
- m_Index: 0
|
||||
m_Metrics:
|
||||
m_Width: 127
|
||||
m_Height: 136
|
||||
m_HorizontalBearingX: -63.5
|
||||
m_HorizontalBearingY: 117.5
|
||||
m_HorizontalAdvance: 127
|
||||
m_GlyphRect:
|
||||
m_X: 0
|
||||
m_Y: 0
|
||||
m_Width: 127
|
||||
m_Height: 136
|
||||
m_Scale: 1
|
||||
m_AtlasIndex: 0
|
||||
m_ClassDefinitionType: 0
|
||||
sprite: {fileID: 21300000, guid: 1b70eadb887fad44abd4ece91ee38a6d, type: 3}
|
||||
spriteInfoList: []
|
||||
fallbackSpriteAssets: []
|
||||
--- !u!21 &8548082164682178837
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: TextMeshPro/Sprite
|
||||
m_Shader: {fileID: 4800000, guid: cf81c85f95fe47e1a27f6ae460cf182c, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 1b70eadb887fad44abd4ece91ee38a6d, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _ColorMask: 15
|
||||
- _CullMode: 0
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca36565f9fa2172499feaedffabf3ee8
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
@@ -0,0 +1,153 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b70eadb887fad44abd4ece91ee38a6d
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -161,7 +161,7 @@ MonoBehaviour:
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 11400000, guid: ca36565f9fa2172499feaedffabf3ee8, type: 2}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
|
||||
@@ -103,6 +103,7 @@ using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
@@ -699,23 +700,38 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
});
|
||||
|
||||
// ⭐ 大喇叭:开/关弹幕输入面板
|
||||
// ⭐ 绑定在 OnShow 里:先 RemoveAllListeners 再 Add,防止面板重复 OnShow 叠加监听器
|
||||
// (叠加后点一次发送 = 发 N 次 API = 多扣 N 个道具)
|
||||
if (dalaba != null)
|
||||
{
|
||||
dalaba.onClick.RemoveAllListeners();
|
||||
dalaba.onClick.AddListener(() =>
|
||||
{
|
||||
if (obj_DaLaBaPanel != null)
|
||||
obj_DaLaBaPanel.SetActive(!obj_DaLaBaPanel.activeSelf);
|
||||
});
|
||||
}
|
||||
if (btn_DaLaBaSend != null)
|
||||
{
|
||||
btn_DaLaBaSend.onClick.RemoveAllListeners();
|
||||
btn_DaLaBaSend.onClick.AddListener(OnClickDaLaBaSend);
|
||||
}
|
||||
if (btn_DaLaBaClose != null)
|
||||
{
|
||||
btn_DaLaBaClose.onClick.RemoveAllListeners();
|
||||
btn_DaLaBaClose.onClick.AddListener(() =>
|
||||
{
|
||||
if (obj_DaLaBaPanel != null) obj_DaLaBaPanel.SetActive(false);
|
||||
if (obj_DaLaBaPanel != null)
|
||||
obj_DaLaBaPanel.SetActive(false);
|
||||
});
|
||||
}
|
||||
|
||||
// ⭐ 召唤卡:使用召唤卡召唤Boss
|
||||
// ⭐ 召唤卡:使用召唤卡召唤Boss(同样防重复绑定)
|
||||
if (zhanhuanka != null)
|
||||
{
|
||||
zhanhuanka.onClick.RemoveAllListeners();
|
||||
zhanhuanka.onClick.AddListener(OnClickZhanHuanKa);
|
||||
}
|
||||
|
||||
// 服务器广播监听
|
||||
EventCenter.Instance.AddEventListener<SyncGameData>(ConstEventString.SyncGameData_Rotate, SyncGameData_Rotate);
|
||||
@@ -1253,13 +1269,21 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
await AudioResourcesData.LoadAudioGame();
|
||||
if (flow != _resourceFlowToken) return;
|
||||
|
||||
await Addressables.LoadAssetsAsync<AudioClip>("Audio", clip =>
|
||||
{
|
||||
if (flow != _resourceFlowToken) return; // 残留流程不再写面板字段
|
||||
if (clip.name == "PW_Shoot")
|
||||
bulletClip = clip;
|
||||
}).Task;
|
||||
// ⭐ 开火音效 PW_Shoot 在 Default Local Group(Audio+PTCBZS 双标签交集检索):
|
||||
// 只命中 Default 小包,不把其它玩法的巨型音频包拉进内存;句柄由 LoadBulletClip 静态保存,离房释放
|
||||
await LoadBulletClip();
|
||||
if (flow != _resourceFlowToken) return;
|
||||
if (_bulletClipHandle.IsValid() && _bulletClipHandle.Result != null)
|
||||
{
|
||||
foreach (var clip in _bulletClipHandle.Result)
|
||||
{
|
||||
if (clip.name == "PW_Shoot")
|
||||
{
|
||||
bulletClip = clip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetLoadProgress(0.8f);
|
||||
await Task.Delay(100);
|
||||
@@ -1321,6 +1345,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
if (flow != _resourceFlowToken) return; // ⭐ 期间已有新流程(新面板加载),剩余卸载作废
|
||||
await AudioResourcesData.UnLoadAudioGame();
|
||||
if (flow != _resourceFlowToken) return;
|
||||
UnLoadBulletClip(); // ⭐ 释放开火音效句柄(引用计数归零)
|
||||
await MonsterMoveLine.UnLoadBezier();
|
||||
if (flow != _resourceFlowToken) return;
|
||||
// ⭐ 清空子弹池 + 特效池(鱼池已在 UnLoadFishAssetsData 内清理)
|
||||
@@ -1332,6 +1357,32 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
/// <summary>资源是否已卸载(避免 OnHide 重复卸载)</summary>
|
||||
private bool _resourcesUnloaded = false;
|
||||
|
||||
/// <summary>
|
||||
/// ⭐ 开火音效 PW_Shoot 的加载句柄(static:新老面板实例共享)。
|
||||
/// PW_Shoot 在 Default Local Group(Audio+PTCBZS),该包因默认音频常驻本就不会卸载,
|
||||
/// 但句柄仍要显式保存/释放,避免每次进房引用计数 +1 无限累加。
|
||||
/// </summary>
|
||||
private static AsyncOperationHandle<IList<AudioClip>> _bulletClipHandle;
|
||||
|
||||
/// <summary>加载开火音效(Audio+PTCBZS 交集,只命中 Default Local Group 里的 PW_Shoot)</summary>
|
||||
private static async Task LoadBulletClip()
|
||||
{
|
||||
// 防御:上一轮句柄未释放时先释放
|
||||
if (_bulletClipHandle.IsValid())
|
||||
Addressables.Release(_bulletClipHandle);
|
||||
|
||||
_bulletClipHandle = Addressables.LoadAssetsAsync<AudioClip>(new List<string> { "Audio", "PTCBZS" }, null,
|
||||
Addressables.MergeMode.Intersection);
|
||||
await _bulletClipHandle.Task;
|
||||
}
|
||||
|
||||
/// <summary>释放开火音效句柄(离房卸载流程调用)</summary>
|
||||
private static void UnLoadBulletClip()
|
||||
{
|
||||
if (_bulletClipHandle.IsValid())
|
||||
Addressables.Release(_bulletClipHandle);
|
||||
}
|
||||
|
||||
/// <summary>离房 socket 响应等待信号</summary>
|
||||
private TaskCompletionSource<bool> _leaveRoomResponseTcs;
|
||||
/// <summary>正在离开的游戏面板类型(完成后关闭它切到 home)</summary>
|
||||
@@ -1383,11 +1434,20 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
{
|
||||
if (JinDuTiao != null) JinDuTiao.Show();
|
||||
|
||||
// ⭐ 先退房销毁场上活鱼,再卸载资源(与 UnLoadResources 顺序一致):
|
||||
// 现在句柄真正会释放、包内资源(贴图/Spine)会被销毁,
|
||||
// 若先卸载后销毁鱼,残留活鱼会在淡出期间丢失材质花屏
|
||||
CreateFishManager.Instance.ExitRoom();
|
||||
CreateFishManager.Instance.isResources = false;
|
||||
BulletPool.Instance.ClearAll();
|
||||
EffectPool.Instance.ClearAll();
|
||||
|
||||
SetUnloadProgress(0.2f);
|
||||
await FishResourcesData.UnLoadFishAssetsData();
|
||||
|
||||
SetUnloadProgress(0.4f);
|
||||
await AudioResourcesData.UnLoadAudioGame();
|
||||
UnLoadBulletClip(); // ⭐ 释放开火音效句柄(引用计数归零)
|
||||
|
||||
SetUnloadProgress(0.6f);
|
||||
await MonsterMoveLine.UnLoadBezier();
|
||||
@@ -1395,11 +1455,6 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
SetUnloadProgress(0.8f);
|
||||
await Task.Delay(100);
|
||||
|
||||
CreateFishManager.Instance.ExitRoom();
|
||||
CreateFishManager.Instance.isResources = false;
|
||||
// ⭐ 清空子弹池 + 特效池(鱼池已在 UnLoadFishAssetsData 内清理)
|
||||
BulletPool.Instance.ClearAll();
|
||||
EffectPool.Instance.ClearAll();
|
||||
SetUnloadProgress(0.9f);
|
||||
|
||||
// ⭐ 卡在 0.9 等待 socket 返回 LeaveRoomResult
|
||||
@@ -1862,8 +1917,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
/// 大喇叭发送:输入弹幕 → /api/Hall/SendBroadcast 全服广播
|
||||
/// (与背包大喇叭 OnClickFaSong 流程一致),发送成功后清空输入框并关闭面板。
|
||||
/// </summary>
|
||||
/// <summary>大喇叭发送中标志:防止回调返回前连点发送按钮导致多发多扣道具</summary>
|
||||
private bool _isSendingDaLaBa;
|
||||
|
||||
private void OnClickDaLaBaSend()
|
||||
{
|
||||
// ⭐ 防重入:上次请求回调还没回来时连点直接忽略(多发一次 = 多扣一个大喇叭)
|
||||
if (_isSendingDaLaBa) return;
|
||||
string msg = tmp_DaLaBaInput?.text?.Trim();
|
||||
if (string.IsNullOrEmpty(msg))
|
||||
{
|
||||
@@ -1871,8 +1931,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
return;
|
||||
}
|
||||
|
||||
APIRequestList.SendBroadcast("广播:" + msg, (result) =>
|
||||
_isSendingDaLaBa = true;
|
||||
// ⭐ 显示格式:"<sprite index=0>【小*鱼】:内容"(前面加喇叭图标 TMP 标签;名字打码:首尾保留、中间一个 *)
|
||||
var userName = GameManager.Instance.user?.BaseInfo?.userName;
|
||||
if (string.IsNullOrEmpty(userName)) userName = "玩家";
|
||||
APIRequestList.SendBroadcast($"<sprite index=0>【{MaskBroadcastName(userName)}】:{msg}", (result) =>
|
||||
{
|
||||
_isSendingDaLaBa = false;
|
||||
// 发送成功:清空输入框并关闭面板(广播内容会通过 LoginBroadcast 全服弹幕显示)
|
||||
if (tmp_DaLaBaInput != null) tmp_DaLaBaInput.text = "";
|
||||
if (obj_DaLaBaPanel != null) obj_DaLaBaPanel.SetActive(false);
|
||||
@@ -1887,6 +1952,18 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 玩家名打码(广播格式):保留首尾字符、中间一个 *("小金鱼"→"小*鱼"、"我是大帅哥"→"我*哥")。
|
||||
/// 与召唤卡提示的 MaskUserName(三个星)区分,广播用单星。
|
||||
/// </summary>
|
||||
private static string MaskBroadcastName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return name;
|
||||
name = name.Trim();
|
||||
if (name.Length <= 1) return name;
|
||||
return name[0] + "*" + name[name.Length - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用召唤卡:从背包找到召唤卡道具(type=11)拿道具编号
|
||||
/// → /api/SummonCard/use 召唤Boss(Boss鱼由服务端 OnFishSpawn 下发给房间所有人)
|
||||
|
||||
@@ -72,7 +72,11 @@ public class UIHome_BY_BackPackPanel : SubUIBase
|
||||
if (DaLaBaPanel != null)
|
||||
DaLaBaPanel.SetActive(false);
|
||||
if (btn_FaSong != null)
|
||||
{
|
||||
// ⭐ 先清再绑:防止面板重复 Show 叠加监听器(点一次发 N 次 = 多扣 N 个大喇叭)
|
||||
btn_FaSong.onClick.RemoveAllListeners();
|
||||
btn_FaSong.onClick.AddListener(OnClickFaSong);
|
||||
}
|
||||
|
||||
// 数量选择面板(默认隐藏)
|
||||
if (useObj != null) useObj.SetActive(false);
|
||||
@@ -147,23 +151,51 @@ public class UIHome_BY_BackPackPanel : SubUIBase
|
||||
_curUseCountAction = null;
|
||||
}
|
||||
|
||||
/// <summary>大喇叭发送中标志:防止回调返回前连点发送按钮导致多发多扣道具</summary>
|
||||
private bool _isSendingFaSong;
|
||||
|
||||
private void OnClickFaSong()
|
||||
{
|
||||
string msg = "广播:"+ tMPText_DaLaBaLabel?.text?.Trim();
|
||||
if (string.IsNullOrEmpty(msg))
|
||||
// ⭐ 防重入:上次请求回调还没回来时连点直接忽略
|
||||
if (_isSendingFaSong) return;
|
||||
// ⭐ 先取文本判空再拼前缀(原"广播:"+text 判空永远不成立,空内容也会发送扣道具)
|
||||
string content = tMPText_DaLaBaLabel?.text?.Trim();
|
||||
if (string.IsNullOrEmpty(content))
|
||||
{
|
||||
UIManager.Instance.ShowBoardError("请输入广播内容");
|
||||
return;
|
||||
}
|
||||
|
||||
APIRequestList.SendBroadcast(msg, (result) =>
|
||||
_isSendingFaSong = true;
|
||||
// ⭐ 显示格式:"<sprite index=0>【小*鱼】:内容"(前面加喇叭图标 TMP 标签;名字打码与游戏内大喇叭同格式)
|
||||
var userName = GameManager.Instance.user?.BaseInfo?.userName;
|
||||
if (string.IsNullOrEmpty(userName)) userName = "玩家";
|
||||
APIRequestList.SendBroadcast($"<sprite index=0>【{MaskBroadcastName(userName)}】:{content}", (result) =>
|
||||
{
|
||||
//UIManager.Instance.ShowBoardGongGao($"广播: {msg}");
|
||||
_isSendingFaSong = false;
|
||||
tMPText_DaLaBaLabel.text = "";
|
||||
DaLaBaPanel.SetActive(false);
|
||||
// ⭐ 发送成功=服务端已扣大喇叭:拉最新用户数据刷新背包数量
|
||||
APIRequestList.GetUser((user) =>
|
||||
{
|
||||
if (user != null)
|
||||
GameManager.Instance.UpdataUserData(user);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 玩家名打码(广播格式):保留首尾字符、中间一个 *("小金鱼"→"小*鱼")。
|
||||
/// 与 GameMainPanel_FishBase.MaskBroadcastName 同格式(背包面板独立副本)。
|
||||
/// </summary>
|
||||
private static string MaskBroadcastName(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return name;
|
||||
name = name.Trim();
|
||||
if (name.Length <= 1) return name;
|
||||
return name[0] + "*" + name[name.Length - 1];
|
||||
}
|
||||
|
||||
private void OnClickConfirmChangeName()
|
||||
{
|
||||
string newName = tMPText_NewName?.text?.Trim();
|
||||
|
||||
Reference in New Issue
Block a user