1
This commit is contained in:
@@ -30,6 +30,11 @@ MonoBehaviour:
|
||||
m_SerializedLabels:
|
||||
- Default
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 88507e399a88aa744970855b92a576a8
|
||||
m_Address: Assets/MyGame/aa/UI/Home/Sub/Turret/ZhanShen.renderTexture
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
m_ReadOnly: 0
|
||||
m_Settings: {fileID: 11400000, guid: 3d7ea06370502a34e82011fabf822b45, type: 2}
|
||||
m_SchemaSet:
|
||||
|
||||
Binary file not shown.
@@ -16,6 +16,15 @@ using UnityEngine;
|
||||
/// </summary>
|
||||
public class AssetDependencyAnalyzer : EditorWindow
|
||||
{
|
||||
// ============================ 日志开关 ============================
|
||||
// 启用: Player Settings → Scripting Define Symbols 添加 ENABLE_EDITOR_LOG
|
||||
// 关闭: 删除该符号。未定义时所有 Log/LogError 调用被编译器自动移除,零开销
|
||||
[System.Diagnostics.Conditional("ENABLE_EDITOR_LOG")]
|
||||
private static void Log(string msg) { Debug.Log(msg); }
|
||||
|
||||
[System.Diagnostics.Conditional("ENABLE_EDITOR_LOG")]
|
||||
private static void LogError(string msg) { Debug.LogError(msg); }
|
||||
|
||||
#region 内部类
|
||||
|
||||
[Serializable]
|
||||
@@ -438,7 +447,7 @@ public class AssetDependencyAnalyzer : EditorWindow
|
||||
if (o != null) objs.Add(o);
|
||||
}
|
||||
Selection.objects = objs.ToArray();
|
||||
Debug.Log($"[依赖分析器] 已选中 {objs.Count} 个非AA资源到 Project 视图");
|
||||
Log($"[依赖分析器] 已选中 {objs.Count} 个非AA资源到 Project 视图");
|
||||
}
|
||||
|
||||
private void DrawDependencyRow(DependencyInfo info)
|
||||
@@ -571,12 +580,12 @@ public class AssetDependencyAnalyzer : EditorWindow
|
||||
allTypes = dependencies.Select(d => d.typeName).Distinct().OrderBy(t => t).ToList();
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
Debug.Log($"[依赖分析器] 分析完成,共 {dependencies.Count} 个依赖资源");
|
||||
Log($"[依赖分析器] 分析完成,共 {dependencies.Count} 个依赖资源");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
Debug.LogError($"[依赖分析器] 分析失败: {e}");
|
||||
LogError($"[依赖分析器] 分析失败: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,13 +762,13 @@ public class AssetDependencyAnalyzer : EditorWindow
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log(sb.ToString());
|
||||
Log(sb.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
Debug.LogError($"[依赖分析器] 反向查找失败: {e}");
|
||||
LogError($"[依赖分析器] 反向查找失败: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,7 +805,7 @@ public class AssetDependencyAnalyzer : EditorWindow
|
||||
|
||||
File.WriteAllText(savePath, sb.ToString(), Encoding.UTF8);
|
||||
EditorUtility.DisplayDialog("完成", $"报告已导出到:\n{savePath}", "确定");
|
||||
Debug.Log($"[依赖分析器] 报告已导出: {savePath}");
|
||||
Log($"[依赖分析器] 报告已导出: {savePath}");
|
||||
}
|
||||
|
||||
private string EscapeCsv(string s)
|
||||
@@ -833,7 +842,7 @@ public class AssetDependencyAnalyzer : EditorWindow
|
||||
sb.AppendLine(info.aaAddress ?? info.assetPath);
|
||||
}
|
||||
GUIUtility.systemCopyBuffer = sb.ToString();
|
||||
Debug.Log($"[依赖分析器] 已复制 {selected.Count} 条地址到剪贴板");
|
||||
Log($"[依赖分析器] 已复制 {selected.Count} 条地址到剪贴板");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -17,6 +17,15 @@ public class TurretPrefabAALabeler : EditorWindow
|
||||
private const string LABEL_PT = "PT";
|
||||
private const string LABEL_DEFAULT = "Default";
|
||||
|
||||
// ============================ 日志开关 ============================
|
||||
// 启用: Player Settings → Scripting Define Symbols 添加 ENABLE_EDITOR_LOG
|
||||
// 关闭: 删除该符号。未定义时所有 Log/LogError 调用被编译器自动移除,零开销
|
||||
[System.Diagnostics.Conditional("ENABLE_EDITOR_LOG")]
|
||||
private static void Log(string msg) { Debug.Log(msg); }
|
||||
|
||||
[System.Diagnostics.Conditional("ENABLE_EDITOR_LOG")]
|
||||
private static void LogError(string msg) { Debug.LogError(msg); }
|
||||
|
||||
[MenuItem("Tools/炮台/配置Prefab AA标签(PT+Default)", false, 102)]
|
||||
public static void SetupAddressableLabels()
|
||||
{
|
||||
@@ -40,7 +49,7 @@ public class TurretPrefabAALabeler : EditorWindow
|
||||
|
||||
string absoluteDir = Path.Combine(Application.dataPath, "MyGame/aa/Game/Turrets");
|
||||
string[] prefabFiles = Directory.GetFiles(absoluteDir, "paotai*.prefab");
|
||||
Debug.Log($"[TurretPrefabAA] 扫描到 {prefabFiles.Length} 个炮台 Prefab");
|
||||
Log($"[TurretPrefabAA] 扫描到 {prefabFiles.Length} 个炮台 Prefab");
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
@@ -74,7 +83,7 @@ public class TurretPrefabAALabeler : EditorWindow
|
||||
entry.SetLabel(LABEL_DEFAULT, true, true);
|
||||
|
||||
count++;
|
||||
Debug.Log($"[TurretPrefabAA] ✓ {fileName}");
|
||||
Log($"[TurretPrefabAA] ✓ {fileName}");
|
||||
}
|
||||
|
||||
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, null, true);
|
||||
@@ -91,7 +100,7 @@ public class TurretPrefabAALabeler : EditorWindow
|
||||
if (!settings.GetLabels().Contains(label))
|
||||
{
|
||||
settings.AddLabel(label);
|
||||
Debug.Log($"[TurretPrefabAA] 新增标签: {label}");
|
||||
Log($"[TurretPrefabAA] 新增标签: {label}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,15 @@ public class TurretSpriteAALabeler : EditorWindow
|
||||
private const string LABEL_PT = "PT";
|
||||
private const string LABEL_DEFAULT = "Default";
|
||||
|
||||
// ============================ 日志开关 ============================
|
||||
// 启用: Player Settings → Scripting Define Symbols 添加 ENABLE_EDITOR_LOG
|
||||
// 关闭: 删除该符号。未定义时所有 Log/LogError 调用被编译器自动移除,零开销
|
||||
[System.Diagnostics.Conditional("ENABLE_EDITOR_LOG")]
|
||||
private static void Log(string msg) { Debug.Log(msg); }
|
||||
|
||||
[System.Diagnostics.Conditional("ENABLE_EDITOR_LOG")]
|
||||
private static void LogError(string msg) { Debug.LogError(msg); }
|
||||
|
||||
[MenuItem("Tools/炮台/配置AA标签(PT+Default)", false, 101)]
|
||||
public static void SetupAddressableLabels()
|
||||
{
|
||||
@@ -52,7 +61,7 @@ public class TurretSpriteAALabeler : EditorWindow
|
||||
}
|
||||
|
||||
string[] pngFiles = Directory.GetFiles(absoluteSpritesDir, "paotai*.png");
|
||||
Debug.Log($"[TurretSpriteAA] 扫描到 {pngFiles.Length} 个炮台 PNG 文件");
|
||||
Log($"[TurretSpriteAA] 扫描到 {pngFiles.Length} 个炮台 PNG 文件");
|
||||
|
||||
// 强制刷新 AssetDatabase,确保所有 PNG 都被识别
|
||||
AssetDatabase.Refresh();
|
||||
@@ -72,7 +81,7 @@ public class TurretSpriteAALabeler : EditorWindow
|
||||
if (importer == null)
|
||||
{
|
||||
// 文件可能还没导入,强制导入
|
||||
Debug.Log($"[TurretSpriteAA] 强制导入: {assetPath}");
|
||||
Log($"[TurretSpriteAA] 强制导入: {assetPath}");
|
||||
AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
|
||||
importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
||||
}
|
||||
@@ -119,7 +128,7 @@ public class TurretSpriteAALabeler : EditorWindow
|
||||
entry.SetLabel(LABEL_DEFAULT, true, true);
|
||||
|
||||
count++;
|
||||
Debug.Log($"[TurretSpriteAA] ✓ {fileName}: address={entry.address}, labels=PT+Default");
|
||||
Log($"[TurretSpriteAA] ✓ {fileName}: address={entry.address}, labels=PT+Default");
|
||||
}
|
||||
|
||||
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, null, true);
|
||||
@@ -137,7 +146,7 @@ public class TurretSpriteAALabeler : EditorWindow
|
||||
if (!settings.GetLabels().Contains(label))
|
||||
{
|
||||
settings.AddLabel(label);
|
||||
Debug.Log($"[TurretSpriteAA] 新增标签: {label}");
|
||||
Log($"[TurretSpriteAA] 新增标签: {label}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,7 +908,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 22400762, guid: 67117722a812a2e46ab8cb8eafbf5f5e, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -0.000022888184
|
||||
value: -0.000015258789
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 22426080, guid: 67117722a812a2e46ab8cb8eafbf5f5e, type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
@@ -6005,6 +6005,7 @@ MonoBehaviour:
|
||||
sendLeaveRoom: 1
|
||||
showWaitingAfterExit: 1
|
||||
useRemoteBotConfig: 0
|
||||
enableLogFile: 1
|
||||
gameConfig:
|
||||
id:
|
||||
isDelete: 0
|
||||
|
||||
@@ -1389,10 +1389,36 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
UIManager.Instance.uiRoot.GetComponent<Canvas>());
|
||||
|
||||
var coinScript = award.GetComponent<BJBase>();
|
||||
coinScript.Init(coinNum.Amount, v3Point);
|
||||
coinScript.isBoss = true;
|
||||
coinScript.isLocalCoin = isLocal;
|
||||
coinScript.SetCoinCount();
|
||||
if (coinScript != null)
|
||||
{
|
||||
// 普通爆奖(BJBase 体系)
|
||||
coinScript.Init((int)coinNum.Amount, v3Point);
|
||||
coinScript.isBoss = true;
|
||||
coinScript.isLocalCoin = isLocal;
|
||||
coinScript.SetCoinCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 特殊鱼爆奖(DieEffect_TSY 体系:小鱼/Boss 模式互通)
|
||||
var tsy = award.GetComponent<DieEffect_TSY>();
|
||||
if (tsy != null)
|
||||
{
|
||||
tsy.startPoint = award.transform.position;
|
||||
tsy.isLocalCoin = isLocal;
|
||||
tsy.monster = monster;
|
||||
tsy.coinCount = coinNum.Amount;
|
||||
|
||||
if (tsy.baoJiangMode == TSYBaoJiangMode.Boss爆奖)
|
||||
{
|
||||
var sit = currGameType.currSitData;
|
||||
tsy.InitBossAward((int)coinNum.Amount,
|
||||
sit != null ? sit.posID : 0,
|
||||
sit != null ? (int)sit.consumeGoldNum : 1,
|
||||
monster.monsterData.fishTypeConfig.fishScore, 1, null);
|
||||
}
|
||||
tsy.SetCoinCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MonsterDieList.Instance.SmallHuangYiHuang(
|
||||
@@ -1441,7 +1467,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
// 4. 设置 CoinScript 的终点为 targetWorldPos
|
||||
var coinScript = award.GetComponent<CoinScript>();
|
||||
|
||||
coinScript.Init(coinNum.Amount, targetWorldPos);
|
||||
coinScript.Init((int)coinNum.Amount, targetWorldPos);
|
||||
coinScript.isBoss = true;
|
||||
coinScript.isLocalCoin = isLocal;
|
||||
coinScript.SetCoinCount();
|
||||
@@ -1487,8 +1513,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
sitData.goldNum += goldToAdd; // 使用副本,不再依赖 killFish 对象
|
||||
sitData.tMP_GoldNum.text = sitData.goldNum.ToString();
|
||||
AudioManager.Instance.PlayerFX(audioID);
|
||||
// ⭐ 记录金币流水:杀鱼获得金币
|
||||
GameManager.LogGoldFlow("KillFish", $"击中鱼原有金币={oldGold} 增加金币=+{goldToAdd} 剩余金币={sitData.goldNum} 鱼ID={fishId} 座位={sitData.posID} 房间={GameManager.Instance.gameData?.roomInfo?.roomId}");
|
||||
// ⭐ 记录金币流水:已加钱(杀鱼获得,本地已执行)
|
||||
GameManager.LogGoldFlowAppliedGain("KillFish", $"击中鱼原有金币={oldGold} 增加金币=+{goldToAdd} 剩余金币={sitData.goldNum} 鱼ID={fishId} 座位={sitData.posID} 房间={GameManager.Instance.gameData?.currRoomData?.roomId}");
|
||||
};
|
||||
//// 加分回调(在金币/加分面板飞完后执行)
|
||||
//Action<int> onScoreAdd = (audioID) =>
|
||||
@@ -1614,13 +1640,40 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
|
||||
|
||||
var coinScript = award.GetComponent<BJBase>();
|
||||
coinScript.startPoint = award.transform.position;
|
||||
coinScript.Init(killFish.gold, sitData.transform.position, killFish.userId, sitData.posID, killFish.param);
|
||||
coinScript.isLocalCoin = sitData.user == GameManager.Instance.user.id;
|
||||
coinScript.startPoint = award.transform.position;
|
||||
coinScript.isBoss = false;
|
||||
coinScript.JiaFen = onScoreAdd;
|
||||
coinScript.SetCoinCount();
|
||||
if (coinScript != null)
|
||||
{
|
||||
// 普通爆奖(BJBase 体系)
|
||||
coinScript.startPoint = award.transform.position;
|
||||
coinScript.Init(killFish.gold, sitData.transform.position, killFish.userId, sitData.posID, killFish.param);
|
||||
coinScript.isLocalCoin = sitData.user == GameManager.Instance.user.id;
|
||||
coinScript.isBoss = false;
|
||||
coinScript.JiaFen = onScoreAdd;
|
||||
coinScript.SetCoinCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 特殊鱼爆奖(DieEffect_TSY 体系:小鱼/Boss 模式互通)
|
||||
var tsy = award.GetComponent<DieEffect_TSY>();
|
||||
if (tsy != null)
|
||||
{
|
||||
tsy.startPoint = award.transform.position;
|
||||
tsy.isLocalCoin = sitData.user == GameManager.Instance.user.id;
|
||||
tsy.monster = monster;
|
||||
tsy.coinCount = killFish.gold;
|
||||
|
||||
if (tsy.baoJiangMode == TSYBaoJiangMode.Boss爆奖)
|
||||
{
|
||||
tsy.InitBossAward(killFish.gold, sitData.posID,
|
||||
(int)sitData.consumeGoldNum,
|
||||
monster.monsterData.fishTypeConfig.fishScore, 1, onScoreAdd);
|
||||
}
|
||||
else
|
||||
{
|
||||
tsy.JiaFenEx = onScoreAdd;
|
||||
}
|
||||
tsy.SetCoinCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// // Boss 鱼:显示浮动分数文本
|
||||
|
||||
@@ -23,6 +23,10 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
[Tooltip("是否使用后端下发的 BotConfig。false=用 Inspector 本地配置(默认,方便测试);true=用后端 GameConfig 返回的 botConfig 覆盖本地")]
|
||||
public bool useRemoteBotConfig = false;
|
||||
|
||||
[Header("日志文件")]
|
||||
[Tooltip("运行时开关:是否实际生成日志文件。需要同时启用 ENABLE_LOG_FILE 预编译指令才生效。\ntrue=生成日志文件;false=不生成(运行时关闭)")]
|
||||
public bool enableLogFile = true;
|
||||
|
||||
public GameConfig gameConfig;
|
||||
public ActivityConfig activityConfig;
|
||||
public Dictionary<string, FishTypeConfig> dic_fishTypeConfigs = new Dictionary<string, FishTypeConfig>();
|
||||
@@ -209,8 +213,12 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
// ⭐ 防止手机屏幕自动黑屏休眠
|
||||
Screen.sleepTimeout = SleepTimeout.NeverSleep;
|
||||
|
||||
#if ENABLE_LOG_FILE
|
||||
// ⭐ 启动日志文件自动保存:把所有 Debug.Log/Warning/Error 写入 persistentDataPath/Logs/
|
||||
InitLogFileWriter();
|
||||
// 需要在 Player Settings → Scripting Define Symbols 中添加 ENABLE_LOG_FILE 才会编译
|
||||
// 运行时可通过 Inspector 的 enableLogFile 勾选框关闭
|
||||
if (enableLogFile) InitLogFileWriter();
|
||||
#endif
|
||||
|
||||
AudioResourcesData audioResourcesData = new AudioResourcesData();
|
||||
InItLoad();
|
||||
@@ -244,8 +252,15 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
|
||||
}
|
||||
|
||||
// ⭐ 日志文件写入器:把 Application.logMessageReceived 的日志实时写入文件
|
||||
#if ENABLE_LOG_FILE
|
||||
// ============================ 日志文件系统 ============================
|
||||
// 启用方法: Player Settings → Other Settings → Scripting Define Symbols 添加 ENABLE_LOG_FILE
|
||||
// 关闭方法: 删除该符号,或 Inspector 中 enableLogFile 取消勾选
|
||||
// 说明: LogGoldFlow 用 [Conditional] 标记,未定义 ENABLE_LOG_FILE 时所有调用点会被编译器自动移除,零开销
|
||||
|
||||
private StreamWriter _logFileWriter;
|
||||
private StreamWriter _goldFlowWriter;
|
||||
|
||||
private void InitLogFileWriter()
|
||||
{
|
||||
try
|
||||
@@ -257,7 +272,6 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
Application.logMessageReceived += OnLogMessageReceived;
|
||||
Debug.Log($"[GameManager] 日志文件已创建: {logPath}");
|
||||
|
||||
// 同时初始化金币流水日志文件
|
||||
InitGoldFlowWriter(logDir);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -266,17 +280,23 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
}
|
||||
}
|
||||
|
||||
// ⭐ 金币流水日志写入器:单独写入"金币流水"文件,格式对齐后端日志
|
||||
private StreamWriter _goldFlowWriter;
|
||||
private void InitGoldFlowWriter(string logDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
string goldLogPath = Path.Combine(logDir, "金币流水_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".log");
|
||||
_goldFlowWriter = new StreamWriter(goldLogPath, true) { AutoFlush = true };
|
||||
|
||||
// ===== 文件头:只记录当前玩家自己(进游戏前可能 user 还没拉到,做 null 保护) =====
|
||||
string userName = user?.BaseInfo?.userName ?? "未登录";
|
||||
string userId = user?.id ?? "未登录";
|
||||
_goldFlowWriter.WriteLine($"# 金币流水日志 - 启动于 {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
_goldFlowWriter.WriteLine($"# 格式: 时间|service=client|INFO|GoldFlow|[金币流水] 玩家=名称(ID) 事件=xxx {描述}");
|
||||
_goldFlowWriter.WriteLine($"# 当前玩家: {userName}({userId})");
|
||||
_goldFlowWriter.WriteLine($"# 说明: 只记录当前玩家自己的金币变动,不记录其他玩家");
|
||||
_goldFlowWriter.WriteLine($"# 格式: 时间|service=client|INFO|GoldFlow|[分类] 玩家=名称(ID) 事件=target 描述");
|
||||
_goldFlowWriter.WriteLine($"# 分类: 收到加钱/已加钱/收到扣钱/已扣钱/金币流水(通用)");
|
||||
_goldFlowWriter.WriteLine(new string('-', 80));
|
||||
|
||||
Debug.Log($"[GameManager] 金币流水日志文件已创建: {goldLogPath}");
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -285,24 +305,6 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录金币流水(供全项目调用)
|
||||
/// 用法: GameManager.LogGoldFlow("KillFish", $"击中鱼原有金币={oldGold} 增加金币=+{addGold} 剩余金币={newGold} 房间={roomId}");
|
||||
/// </summary>
|
||||
public static void LogGoldFlow(string eventName, string description)
|
||||
{
|
||||
var inst = Instance;
|
||||
if (inst == null || inst._goldFlowWriter == null) return;
|
||||
try
|
||||
{
|
||||
string userName = inst.user?.BaseInfo?.userName ?? "未知";
|
||||
string userId = inst.user?.id ?? "未知";
|
||||
string timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
inst._goldFlowWriter.WriteLine($"{timeStr}|service=client|INFO|GoldFlow|[金币流水] 玩家={userName}({userId}) 事件={eventName} {description}");
|
||||
}
|
||||
catch { /* 写日志失败不影响游戏运行 */ }
|
||||
}
|
||||
|
||||
private void OnLogMessageReceived(string condition, string stackTrace, LogType type)
|
||||
{
|
||||
if (_logFileWriter == null) return;
|
||||
@@ -323,7 +325,7 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
_logFileWriter.WriteLine($" Stack: {stackTrace}");
|
||||
}
|
||||
}
|
||||
catch { /* 写日志失败不影响游戏运行 */ }
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
@@ -340,6 +342,82 @@ public class GameManager : MonoSingleton<GameManager>
|
||||
_goldFlowWriter = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================ 金币流水日志(与后端逐条对比) ============================
|
||||
// 拆成4类,方便和后端日志逐行对比:
|
||||
// - 收到扣钱信息(推送): 后端发来扣钱通知,客户端尚未执行
|
||||
// - 已扣钱(本地执行): 客户端本地已扣完金币
|
||||
// - 收到加钱信息(推送): 后端发来加钱通知,客户端尚未执行
|
||||
// - 已加钱(本地执行): 客户端本地已加完金币
|
||||
//
|
||||
// 控制方式:
|
||||
// 1. 编译时: 未定义 ENABLE_LOG_FILE 符号时,所有调用被编译器自动移除([Conditional]特性),零开销
|
||||
// 2. 运行时: 即使编译了,Inspector 中 enableLogFile=false 也不会写入文件
|
||||
//
|
||||
// 通用记录(无关扣/加,如退出房间)继续用 LogGoldFlow
|
||||
|
||||
/// <summary>记录"收到扣钱信息"(后端推送,尚未执行)。如:后端推送 SyncPlayerGold 差值为负</summary>
|
||||
[System.Diagnostics.Conditional("ENABLE_LOG_FILE")]
|
||||
public static void LogGoldFlowReceiveCost(string eventName, string description)
|
||||
{
|
||||
#if ENABLE_LOG_FILE
|
||||
WriteGoldFlow("收到扣钱", eventName, description);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>记录"已扣钱"(本地已执行扣金币)。如:开火 ConsumeGold 扣完</summary>
|
||||
[System.Diagnostics.Conditional("ENABLE_LOG_FILE")]
|
||||
public static void LogGoldFlowAppliedCost(string eventName, string description)
|
||||
{
|
||||
#if ENABLE_LOG_FILE
|
||||
WriteGoldFlow("已扣钱", eventName, description);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>记录"收到加钱信息"(后端推送,尚未执行)。如:RoomJoinNotice/RoomInfo 推送金币</summary>
|
||||
[System.Diagnostics.Conditional("ENABLE_LOG_FILE")]
|
||||
public static void LogGoldFlowReceiveGain(string eventName, string description)
|
||||
{
|
||||
#if ENABLE_LOG_FILE
|
||||
WriteGoldFlow("收到加钱", eventName, description);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>记录"已加钱"(本地已执行加金币)。如:杀鱼 KillFish 加完、进房 JoinGame 设置初始金币</summary>
|
||||
[System.Diagnostics.Conditional("ENABLE_LOG_FILE")]
|
||||
public static void LogGoldFlowAppliedGain(string eventName, string description)
|
||||
{
|
||||
#if ENABLE_LOG_FILE
|
||||
WriteGoldFlow("已加钱", eventName, description);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>通用金币流水记录(无关扣/加,如退出房间)。需要明确分类时请用上面4个方法</summary>
|
||||
[System.Diagnostics.Conditional("ENABLE_LOG_FILE")]
|
||||
public static void LogGoldFlow(string eventName, string description)
|
||||
{
|
||||
#if ENABLE_LOG_FILE
|
||||
WriteGoldFlow("金币流水", eventName, description);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_LOG_FILE
|
||||
/// <summary>金币流水核心写入(私有)。所有公开 LogGoldFlow* 方法最终都走这里</summary>
|
||||
private static void WriteGoldFlow(string category, string eventName, string description)
|
||||
{
|
||||
var inst = Instance;
|
||||
if (inst == null || !inst.enableLogFile || inst._goldFlowWriter == null) return;
|
||||
try
|
||||
{
|
||||
string userName = inst.user?.BaseInfo?.userName ?? "未知";
|
||||
string userId = inst.user?.id ?? "未知";
|
||||
string timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
inst._goldFlowWriter.WriteLine($"{timeStr}|service=client|INFO|GoldFlow|[{category}] 玩家={userName}({userId}) 事件={eventName} {description}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
#endif
|
||||
|
||||
public async Task InItLoad()
|
||||
{
|
||||
|
||||
@@ -16,7 +16,10 @@ namespace Assets.MyGame.Scripts.Net
|
||||
{
|
||||
public static Dictionary<APIType, string> dic_API = new Dictionary<APIType, string>();
|
||||
//public const string baseURL = "http://game5241.wzaxr.top";
|
||||
#if UNITY_EDITOR
|
||||
#if ENABLE_LOG_FILE
|
||||
public const string baseURL = "http://47.109.132.12";
|
||||
|
||||
#elif UNITY_EDITOR
|
||||
//public const string baseURL = "http://8.137.163.153";
|
||||
public const string baseURL = "http://47.109.132.12";
|
||||
|
||||
|
||||
@@ -29,9 +29,11 @@ namespace Assets.MyGame.Scripts.Net
|
||||
private readonly HashSet<SocketType> manualClosing = new();
|
||||
private float nextHeartbeatTime;
|
||||
private const float HeartbeatIntervalSeconds = 20f;
|
||||
#if ENABLE_LOG_FILE
|
||||
private const string baseUrl = "ws://47.109.132.12";
|
||||
|
||||
//private const string baseUrl = "ws://game5241.wzaxr.top";
|
||||
#if UNITY_EDITOR
|
||||
#elif UNITY_EDITOR
|
||||
//private const string baseUrl = "ws://8.137.163.153";
|
||||
private const string baseUrl = "ws://47.109.132.12";
|
||||
|
||||
|
||||
@@ -476,62 +476,79 @@ namespace Assets.MyGame.Scripts.Net
|
||||
break;
|
||||
case "Exception":
|
||||
{
|
||||
var va = JsonConvert.DeserializeObject<WebSocketResponseBase<string>>(msg).arguments[0];
|
||||
UIManager.Instance.ShowBoardError(va);
|
||||
switch (va)
|
||||
var ex = JsonConvert.DeserializeObject<WebSocketResponseBase<WebSocketReponseList.FishGameExceptionData>>(msg).arguments[0];
|
||||
if (ex == null) break;
|
||||
|
||||
// 根据错误码分类处理
|
||||
switch (ex.code)
|
||||
{
|
||||
case "房间人数已满":
|
||||
switch (GameManager.Instance.gameData.currGameType)
|
||||
case 1001: // 房间已满 → 弹窗提示并跳转房间列表
|
||||
UIManager.Instance.ShowTiShi(ex.message, () =>
|
||||
{
|
||||
case GameType.JQQD:
|
||||
break;
|
||||
case GameType.defaultPanel:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelDefault, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
|
||||
});
|
||||
break;
|
||||
case GameType.FLZY:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelFLZY, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
|
||||
});
|
||||
break;
|
||||
case GameType.YYSC:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelYYSC, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
|
||||
});
|
||||
break;
|
||||
case GameType.ZGXQ:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelZGXQ, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
|
||||
});
|
||||
break;
|
||||
case GameType.XJMH:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelXJMH, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
|
||||
});
|
||||
break;
|
||||
case GameType.HHWK:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelHHWK, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (GameManager.Instance.gameData.currGameType)
|
||||
{
|
||||
case GameType.JQQD:
|
||||
break;
|
||||
case GameType.defaultPanel:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelDefault, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
});
|
||||
break;
|
||||
case GameType.FLZY:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelFLZY, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
});
|
||||
break;
|
||||
case GameType.YYSC:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelYYSC, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
});
|
||||
break;
|
||||
case GameType.ZGXQ:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelZGXQ, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
});
|
||||
break;
|
||||
case GameType.XJMH:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelXJMH, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
});
|
||||
break;
|
||||
case GameType.HHWK:
|
||||
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelHHWK, null, (panel) =>
|
||||
{
|
||||
WebSocketSendList.GetRoomListFish(GameManager.Instance.gameData.currRoomData.roomLevel, 1);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// 资产/状态类错误 → 弹窗提示,玩家需明确知晓
|
||||
case 1002: // 金币不足
|
||||
case 1003: // 房间不存在
|
||||
case 1011: // 用户不存在
|
||||
case 1013: // 道具数量不足
|
||||
case 1014: // 钻石不足
|
||||
UIManager.Instance.ShowTiShi(ex.message);
|
||||
break;
|
||||
// 参数/配置/技术性错误 → Toast 轻提示
|
||||
case 1004: // 玩家不在房间
|
||||
case 1005: // 签名错误
|
||||
case 1006: // 请求已过期
|
||||
case 1007: // 鱼配置不存在
|
||||
case 1008: // 子弹参数无效
|
||||
case 1009: // 金币参数超出范围
|
||||
case 1012: // 道具配置不存在
|
||||
case 1015: // 炮倍参数无效
|
||||
default: // 0=未知错误
|
||||
UIManager.Instance.ShowBoardError(ex.message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +57,15 @@ namespace Assets.MyGame.Scripts.Net
|
||||
/// <param name="msg"></param>
|
||||
public static void RoomJoinNotice(string msg)
|
||||
{
|
||||
// ⭐ 记录金币流水:收到 RoomJoinNotice 推送
|
||||
// ⭐ 记录金币流水:收到加钱信息(RoomJoinNotice 推送,尚未执行)—— 只记录自己
|
||||
try
|
||||
{
|
||||
var notice = JsonConvert.DeserializeObject<WebSocketResponseBase<RoomJoinNotice>>(msg).arguments[0];
|
||||
GameManager.LogGoldFlow("RoomJoinNotice", $"推送金币={notice.gold} 钻石={notice.diamond} 炮台消耗={notice.cannonMultiple} 座位={notice.position}");
|
||||
string myId = GameManager.Instance.user?.id;
|
||||
if (!string.IsNullOrEmpty(myId) && notice.userId == myId)
|
||||
{
|
||||
GameManager.LogGoldFlowReceiveGain("RoomJoinNotice", $"推送金币={notice.gold} 钻石={notice.diamond} 炮台消耗={notice.cannonMultiple} 座位={notice.position}");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
@@ -226,22 +230,35 @@ namespace Assets.MyGame.Scripts.Net
|
||||
var panel = UIManager.Instance.Get<GameMainPanel_FishBase>(panelType);
|
||||
if (panel == null || panel.currSitData == null) return;
|
||||
long oldGold = panel.currSitData.goldNum;
|
||||
long diff = gold - oldGold;
|
||||
// ⭐ 记录金币流水:收到后端推送 SyncPlayerGold(尚未执行)
|
||||
if (diff > 0)
|
||||
GameManager.LogGoldFlowReceiveGain("SyncPlayerGold", $"推送金币={gold} 修正前金币={oldGold} 差值=+{diff} 座位={panel.currSitData.posID}");
|
||||
else if (diff < 0)
|
||||
GameManager.LogGoldFlowReceiveCost("SyncPlayerGold", $"推送金币={gold} 修正前金币={oldGold} 差值={diff} 座位={panel.currSitData.posID}");
|
||||
|
||||
panel.currSitData.goldNum = gold;
|
||||
if (panel.currSitData.tMP_GoldNum != null)
|
||||
panel.currSitData.tMP_GoldNum.text = gold.ToString();
|
||||
// ⭐ 记录金币流水:后端推送 SyncPlayerGold 修正
|
||||
GameManager.LogGoldFlow("SyncPlayerGold", $"推送金币={gold} 修正前金币={oldGold} 差值={gold - oldGold} 座位={panel.currSitData.posID}");
|
||||
|
||||
// ⭐ 记录金币流水:已执行修正(本地已写入)
|
||||
if (diff > 0)
|
||||
GameManager.LogGoldFlowAppliedGain("SyncPlayerGold", $"已修正金币={gold} 修正前金币={oldGold} 增加金币=+{diff} 座位={panel.currSitData.posID}");
|
||||
else if (diff < 0)
|
||||
GameManager.LogGoldFlowAppliedCost("SyncPlayerGold", $"已修正金币={gold} 修正前金币={oldGold} 扣除金币={diff} 座位={panel.currSitData.posID}");
|
||||
}
|
||||
public static void GetRoomInfoResult(string msg)
|
||||
{
|
||||
//GameManager.Instance.StartGame();RoomChangeResponse
|
||||
var roomData = JsonConvert.DeserializeObject<WebSocketResponseBase<RoomChangeResponse>>(msg).arguments[0];
|
||||
// ⭐ 记录金币流水:收到 RoomInfo 推送
|
||||
// ⭐ 记录金币流水:收到加钱信息(RoomInfo 推送玩家金币,尚未执行)—— 只记录自己
|
||||
if (roomData?.players != null)
|
||||
{
|
||||
string myId = GameManager.Instance.user?.id;
|
||||
foreach (var p in roomData.players)
|
||||
{
|
||||
GameManager.LogGoldFlow("RoomInfo", $"推送金币={p.gold} 钻石={p.diamond} 炮台消耗={p.cannonMultiple} 座位={p.position} 房间={roomData.roomId}");
|
||||
if (string.IsNullOrEmpty(myId) || p.userId != myId) continue;
|
||||
GameManager.LogGoldFlowReceiveGain("RoomInfo", $"推送金币={p.gold} 钻石={p.diamond} 炮台消耗={p.cannonMultiple} 座位={p.position} 房间={roomData.roomId}");
|
||||
}
|
||||
}
|
||||
UIHome_BY_SelectRoomLevelPanel.StartGame(roomData);
|
||||
@@ -1074,6 +1091,21 @@ namespace Assets.MyGame.Scripts.Net
|
||||
public string title;
|
||||
public string emailId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FishGameHub Exception 数据({code, message})
|
||||
/// code: 0=未知错误
|
||||
/// 1001=房间已满 1002=金币不足 1003=房间不存在 1004=玩家不在房间
|
||||
/// 1005=签名错误 1006=请求已过期 1007=鱼配置不存在 1008=子弹参数无效
|
||||
/// 1009=金币参数超出范围 1011=用户不存在 1012=道具配置不存在
|
||||
/// 1013=道具数量不足 1014=钻石不足 1015=炮倍参数无效
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FishGameExceptionData
|
||||
{
|
||||
public int code;
|
||||
public string message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -601,8 +601,8 @@ public class SitPosData : MonoBehaviour
|
||||
long oldGold = goldNum;
|
||||
goldNum = temp;
|
||||
tMP_GoldNum.text = goldNum.ToString();
|
||||
// ⭐ 记录金币流水:开火消耗金币
|
||||
GameManager.LogGoldFlow("Fire", $"开火消耗 原有金币={oldGold} 消耗金币=-{consumeGoldNum * mul} 剩余金币={goldNum} 座位={posID} 房间={GameManager.Instance.gameData?.roomInfo?.roomId}");
|
||||
// ⭐ 记录金币流水:已扣钱(开火消耗,本地已执行)
|
||||
GameManager.LogGoldFlowAppliedCost("Fire", $"开火消耗 原有金币={oldGold} 消耗金币=-{consumeGoldNum * mul} 剩余金币={goldNum} 座位={posID} 房间={GameManager.Instance.gameData?.currRoomData?.roomId}");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,90 +1,188 @@
|
||||
using Assets.MyGame.Scripts.Net.APIResponses.Enum;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 特殊鱼爆奖基类(Boss 爆奖体系)。
|
||||
/// 所有特殊鱼死亡事件(ZDX / SDY / 钻头 / 闪电…)的统一基类:
|
||||
///
|
||||
/// 1. 继承 BJEventBase —— 特殊鱼可直接走 Boss 完整爆奖流程(红包 → 滚分 → BJEndUI 结算);
|
||||
/// 2. baoJiangMode 枚举决定爆奖表现:
|
||||
/// 小鱼爆奖 = BaoJiangTSSmallFish 拓展(保留,爆奖/转盘样式);
|
||||
/// Boss爆奖 = BJEventBase 完整流程;
|
||||
/// 特殊鱼升 Boss、Boss 降特殊鱼只改这一个枚举(SetBaoJiangMode 支持运行时切换);
|
||||
/// 3. BJEndUI 用 endUIType 枚举选择,prefab 映射配在 endUIEntries;
|
||||
/// 4. 子类分工:
|
||||
/// SetCoinCount() —— 由 CreateFishManager 杀鱼流程调用(SDY 覆写为闪电链);
|
||||
/// PlayEffect() —— 由 MonsterDieList.SpecialDieFish 调用(ZDX 覆写为宝箱金币);
|
||||
/// CreateBaoJiangEffect() —— 子类自身流程结束后调用,按模式分发爆奖。
|
||||
/// </summary>
|
||||
public class DieEffect_TSY : BJEventBase
|
||||
{
|
||||
public int radius;
|
||||
public int count;
|
||||
public float time = 0.5f;
|
||||
[Header("====== 爆奖模式(特殊鱼/Boss 互通开关)======")]
|
||||
[Tooltip("小鱼爆奖 = 走 BaoJiangTSSmallFish 拓展;Boss爆奖 = 走 BJEventBase 完整流程")]
|
||||
public TSYBaoJiangMode baoJiangMode = TSYBaoJiangMode.小鱼爆奖;
|
||||
|
||||
[Header("爆奖特效")]
|
||||
public GameObject baoJiangEffectPrefab; // 爆奖特效预制体(转盘特效)
|
||||
public Transform parentTransform; // 父对象(在Inspector中指定)
|
||||
public Vector3 offsetPosition = new Vector3(0, 2, 0); // 世界坐标偏移量
|
||||
[Header("====== Boss 结算 UI(枚举选择)======")]
|
||||
public BJEndUIType endUIType = BJEndUIType.默认Boss结算;
|
||||
[Tooltip("枚举 → BJEndUI prefab 映射表")]
|
||||
public List<BJEndUIEntry> endUIEntries = new List<BJEndUIEntry>();
|
||||
|
||||
[Header("爆奖类型")]
|
||||
public TSBJ effectType = TSBJ.转盘; // 死亡动画的爆奖类型,默认转盘
|
||||
[Header("====== 通用 ======")]
|
||||
public MonsterContral monster; // 宿主鱼(由调用方赋值)
|
||||
public Vector3 startPoint; // 爆奖起点(特效/闪电起始位置)
|
||||
public long coinCount; // 爆奖总额
|
||||
public bool isLocalCoin; // 是否本地玩家的金币(金/银区分用)
|
||||
public Action<int> JiaFenEx; // 小鱼爆奖路径的加分回调(透传 BaoJiangTSSmallFish)
|
||||
|
||||
private void Start()
|
||||
[Header("====== 小鱼爆奖(BaoJiangTSSmallFish 拓展)======")]
|
||||
public GameObject baoJiangEffectPrefab; // 爆奖特效预制体(上挂 BaoJiangTSSmallFish)
|
||||
public Transform parentTransform; // 生成父节点(空则统一挂 bjEffectRoot)
|
||||
public Vector3 offsetPosition; // 生成位置偏移
|
||||
public TSBJ effectType; // 爆奖样式(暴富/完美/转盘…)
|
||||
|
||||
[Header("====== 时序表现 ======")]
|
||||
public GameObject[] onTimeObjs; // 爆奖期间激活的表现物件
|
||||
public float[] hitTimes; // 各阶段时间点(秒)
|
||||
public float time; // 通用等待时长
|
||||
public int dieEffectTesyNum; // 计数器(金币/链点完成数)
|
||||
|
||||
[Header("====== Boss 爆奖参数 ======")]
|
||||
public int minBJCount = 10; // 每次 CallBJ 最小红包数
|
||||
public int maxBJCount = 15; // 每次 CallBJ 最大红包数
|
||||
|
||||
protected bool _bossInited; // 是否已 InitBossAward
|
||||
|
||||
/// <summary>
|
||||
/// 运行时切换爆奖模式(特殊鱼↔Boss 互通入口)。
|
||||
/// </summary>
|
||||
public void SetBaoJiangMode(TSYBaoJiangMode mode, BJEndUIType? endUI = null)
|
||||
{
|
||||
paoBei = (int)CreateFishManager.Instance.currGameType.currSitData.consumeGoldNum;
|
||||
baoJiangMode = mode;
|
||||
if (endUI.HasValue) endUIType = endUI.Value;
|
||||
}
|
||||
|
||||
public void SetCoinCount()
|
||||
/// <summary>
|
||||
/// Boss 爆奖初始化。模式 = Boss爆奖 时由调用方先调本方法传齐参数,再调 SetCoinCount/Play。
|
||||
/// </summary>
|
||||
public void InitBossAward(int goldCount, int posID, int paobei, int fishScore, int beishu, Action<int> jiafen)
|
||||
{
|
||||
StartCoroutine(enumerator());
|
||||
// totalBJCount 在 Start() 里同步自 scoreCount,保证 CallBJ 后能自动 EffEnd
|
||||
if (scoreCount <= 0) scoreCount = 1;
|
||||
totalBJCount = scoreCount;
|
||||
|
||||
ResolveEndUI();
|
||||
_bossInited = true;
|
||||
Init(goldCount, posID, paobei, fishScore, beishu, jiafen);
|
||||
}
|
||||
|
||||
public virtual IEnumerator enumerator()
|
||||
/// <summary>结算 UI 枚举 → prefab:写入基类 bjEndUI,OnScoreEnd 时由基类实例化。</summary>
|
||||
protected virtual void ResolveEndUI()
|
||||
{
|
||||
yield return new WaitForSeconds(time);
|
||||
|
||||
// 在销毁前创建爆奖特效
|
||||
CreateBaoJiangEffect();
|
||||
|
||||
Destroy(gameObject);
|
||||
if (endUIType == BJEndUIType.无)
|
||||
{
|
||||
bjEndUI = null;
|
||||
return;
|
||||
}
|
||||
var entry = endUIEntries.Find(e => e.type == endUIType);
|
||||
if (entry != null && entry.prefab != null)
|
||||
{
|
||||
bjEndUI = entry.prefab;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[DieEffect_TSY] 未配置 {endUIType} 对应的 BJEndUI prefab");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>金币/爆奖启动入口(由 CreateFishManager 杀鱼流程调用,子类覆写)。</summary>
|
||||
public virtual void SetCoinCount() { }
|
||||
|
||||
/// <summary>死亡特效入口(由 MonsterDieList.SpecialDieFish 调用,子类覆写)。</summary>
|
||||
public virtual void PlayEffect(ParticleSystem effect)
|
||||
{
|
||||
if (effect != null) effect.Play();
|
||||
}
|
||||
|
||||
public void CreateBaoJiangEffect()
|
||||
/// <summary>爆奖总入口:按 baoJiangMode 分发(子类自身流程结束后调用)。</summary>
|
||||
public virtual void CreateBaoJiangEffect()
|
||||
{
|
||||
if (baoJiangMode == TSYBaoJiangMode.Boss爆奖)
|
||||
{
|
||||
PlayBossAward();
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaySmallFishAward();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 小鱼爆奖:实例化 BaoJiangTSSmallFish 拓展,按 effectType 播 爆奖/转盘。
|
||||
/// (移植自 EffectZuanTouDie 旧版 CreateBaoJiangEffect 的可用逻辑)
|
||||
/// </summary>
|
||||
protected virtual void PlaySmallFishAward()
|
||||
{
|
||||
if (baoJiangEffectPrefab == null)
|
||||
{
|
||||
Debug.LogWarning("爆奖特效预制体未设置!");
|
||||
Debug.LogWarning("[DieEffect_TSY] 小鱼爆奖模式但未配置 baoJiangEffectPrefab!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 确定父对象:优先用 Inspector 指定的 parentTransform → 否则用统一爆奖父节点 bjEffectRoot
|
||||
Transform parent = parentTransform != null ? parentTransform : CreateFishManager.Instance.bjEffectRoot;
|
||||
// 父对象:优先 Inspector 指定 → 否则统一爆奖父节点 bjEffectRoot
|
||||
Transform parent = parentTransform != null
|
||||
? parentTransform
|
||||
: CreateFishManager.Instance.bjEffectRoot;
|
||||
|
||||
// 获取源对象的世界坐标
|
||||
Vector3 sourcePosition = CreateFishManager.Instance.currGameType.currSitData.transform.position;
|
||||
// 基准位置:座位坐标 + 手调偏移
|
||||
Vector3 basePos = CreateFishManager.Instance.currGameType != null
|
||||
&& CreateFishManager.Instance.currGameType.currSitData != null
|
||||
? CreateFishManager.Instance.currGameType.currSitData.transform.position
|
||||
: transform.position;
|
||||
|
||||
// 计算生成位置(世界坐标 + 偏移量)
|
||||
Vector3 spawnPosition = sourcePosition + offsetPosition;
|
||||
|
||||
// 实例化爆奖特效,设置父对象
|
||||
GameObject effectObj = Instantiate(baoJiangEffectPrefab, parent);
|
||||
|
||||
// 设置位置(世界坐标)
|
||||
effectObj.transform.position = spawnPosition;
|
||||
|
||||
// 重置缩放(避免父对象缩放影响)
|
||||
var effectObj = Instantiate(baoJiangEffectPrefab, parent);
|
||||
effectObj.transform.position = basePos + offsetPosition;
|
||||
effectObj.transform.localScale = Vector3.one;
|
||||
|
||||
// 获取BaoJiangTSSmallFish组件
|
||||
BaoJiangTSSmallFish baoJiang = effectObj.GetComponent<BaoJiangTSSmallFish>();
|
||||
baoJiang.JiaFen = JiaFen;
|
||||
|
||||
if (baoJiang != null)
|
||||
var baoJiang = effectObj.GetComponent<BaoJiangTSSmallFish>();
|
||||
if (baoJiang == null)
|
||||
{
|
||||
// 计算总奖金
|
||||
long totalReward = count; // 可以根据需要修改
|
||||
Debug.LogWarning("[DieEffect_TSY] baoJiangEffectPrefab 上缺少 BaoJiangTSSmallFish 组件!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据枚举类型调用不同的方法
|
||||
if (effectType == TSBJ.转盘)
|
||||
{
|
||||
// 调用转盘特效(不带图片)
|
||||
baoJiang.ZP(totalReward, true, null, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 调用爆奖特效
|
||||
baoJiang.BJ(totalReward, effectType, true, true);
|
||||
}
|
||||
baoJiang.JiaFen = () => JiaFenEx?.Invoke(0);
|
||||
|
||||
// 根据枚举类型调用不同爆奖方法
|
||||
if (effectType == TSBJ.转盘)
|
||||
{
|
||||
baoJiang.ZP(coinCount, true, null, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
baoJiang.BJ(coinCount, effectType, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boss 爆奖:走 BJEventBase 完整流程。
|
||||
/// CallBJ → 协模拟金币逐个到达累分 → 自动 EffEnd → 滚分 → MoveToSit → BJEndUI → JiaFen → die。
|
||||
/// </summary>
|
||||
protected virtual void PlayBossAward()
|
||||
{
|
||||
if (!_bossInited)
|
||||
{
|
||||
Debug.LogWarning("[DieEffect_TSY] Boss爆奖模式需先调用 InitBossAward 传入爆奖参数!");
|
||||
return;
|
||||
}
|
||||
ResolveEndUI();
|
||||
CallBJ(minBJCount, maxBJCount);
|
||||
}
|
||||
|
||||
/// <summary>兼容旧子类的协程占位(EffectZuanTouDie 等历史代码)。</summary>
|
||||
public virtual IEnumerator enumerator()
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// 特殊鱼爆奖模式 —— 特殊鱼与 Boss 爆奖互通的核心开关。
|
||||
/// 策划后续"特殊鱼变 Boss / Boss 变特殊鱼"只改这一项(或运行时 SetBaoJiangMode 切换)。
|
||||
/// </summary>
|
||||
public enum TSYBaoJiangMode
|
||||
{
|
||||
小鱼爆奖 = 0, // 轻量流程:BaoJiangTSSmallFish 拓展(爆奖/转盘样式)
|
||||
Boss爆奖 = 1, // 完整流程:BJEventBase(红包 → 滚分 → BJEndUI 结算)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boss 爆奖结算 UI 类型(枚举选项,策划下拉选;prefab 映射配在 DieEffect_TSY.endUIEntries)。
|
||||
/// 后续有新结算样式:加枚举值 + 配一条映射即可,不改代码结构。
|
||||
/// </summary>
|
||||
public enum BJEndUIType
|
||||
{
|
||||
无 = 0,
|
||||
默认Boss结算 = 1,
|
||||
大奖结算 = 2,
|
||||
特殊Boss结算 = 3,
|
||||
}
|
||||
|
||||
/// <summary>BJEndUIType → BJEndUI prefab 映射项。</summary>
|
||||
[Serializable]
|
||||
public class BJEndUIEntry
|
||||
{
|
||||
public BJEndUIType type;
|
||||
public BJEndUI prefab;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de97264872500254bb686452a3b5deb6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -49,6 +49,7 @@ MonoBehaviour:
|
||||
silver: {fileID: 0}
|
||||
endPoint: {x: 0, y: 0, z: 0}
|
||||
isBoss: 0
|
||||
isLocalCoin: 0
|
||||
coinCount: 0
|
||||
userID:
|
||||
sitID: 0
|
||||
@@ -57,7 +58,8 @@ MonoBehaviour:
|
||||
count: 0
|
||||
paoBei: 0
|
||||
time: 0.5
|
||||
baoJiangEffectPrefab: {fileID: 0}
|
||||
baoJiangEffectPrefab: {fileID: 136624701376015062, guid: 8d6e13708cafa5d448d52c8fd7f00f1a,
|
||||
type: 3}
|
||||
parentTransform: {fileID: 0}
|
||||
offsetPosition: {x: 0, y: 2, z: 0}
|
||||
effectType: 5
|
||||
|
||||
@@ -2389,8 +2389,8 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
sit.goldNum = goldNum;
|
||||
sit.consumeGoldNum = consumeGold;
|
||||
|
||||
// ⭐ 记录金币流水:进房初始金币
|
||||
GameManager.LogGoldFlow("JoinGame", $"座位={sitNum} 初始金币={goldNum} 钻石={diamondNum} 炮台消耗={consumeGold} 房间={GameManager.Instance.gameData?.currRoomData?.roomId}");
|
||||
// ⭐ 记录金币流水:已加钱(进房设置初始金币,本地已执行)
|
||||
GameManager.LogGoldFlowAppliedGain("JoinGame", $"座位={sitNum} 初始金币={goldNum} 钻石={diamondNum} 炮台消耗={consumeGold} 房间={GameManager.Instance.gameData?.currRoomData?.roomId}");
|
||||
// ⭐ 同步 indexConsume 到后端下发的 cannonMultiple 对应档位,避免加减炮倍时从 0 档跳变
|
||||
sit.SyncIndexByConsume(consumeGold);
|
||||
|
||||
|
||||
@@ -705,40 +705,6 @@ public class UIHome_BY_ItemListPanels : SubUIBase
|
||||
{
|
||||
_currentPreviewObj = Instantiate(prefab, previewParent);
|
||||
_currentPreviewObj.SetActive(true);
|
||||
|
||||
// 打包后战神 prefab 自带相机的 targetTexture 引用会丢失(AA bundle 加载导致),
|
||||
// 需要从面板的 RawImage 取出 RenderTexture 重新赋给战神相机,否则投影不出来。
|
||||
FixZhanShenCameraTargetTexture(_currentPreviewObj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修复战神 prefab 实例化后相机 targetTexture 丢失的问题。
|
||||
/// 打包后从 AA 加载 prefab 时,相机上序列化的 RenderTexture 引用会变成 null,
|
||||
/// 这里从面板的 RawImage.texture 取出 RenderTexture 重新赋值给战神相机。
|
||||
/// </summary>
|
||||
private void FixZhanShenCameraTargetTexture(GameObject zhanShenInstance)
|
||||
{
|
||||
if (zhanShenInstance == null || rawImg_DetailPreview == null) return;
|
||||
|
||||
RenderTexture rt = rawImg_DetailPreview.texture as RenderTexture;
|
||||
if (rt == null)
|
||||
{
|
||||
// 兜底:从 previewParent 下的面板相机取 targetTexture
|
||||
var panelCam = previewParent != null ? previewParent.GetComponentInChildren<Camera>(true) : null;
|
||||
rt = panelCam != null ? panelCam.targetTexture : null;
|
||||
}
|
||||
if (rt == null) return;
|
||||
|
||||
// 战神 prefab 自带的相机(打包后 targetTexture 为 null)
|
||||
var cams = zhanShenInstance.GetComponentsInChildren<Camera>(true);
|
||||
foreach (var cam in cams)
|
||||
{
|
||||
if (cam.targetTexture == null)
|
||||
{
|
||||
cam.targetTexture = rt;
|
||||
Debug.Log($"[UIHome_BY_ItemListPanels] 修复战神相机 targetTexture: {cam.name} → {rt.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user