using Assets.MyGame.Scripts.Net; using Assets.MyGame.Scripts.Net.API; using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass; using CameraShake; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityEngine.Video; public class GameManager : MonoSingleton { [Header("人机")] public bool enableBot = true; // 人机总开关 public BotConfig botConfig; // 人机AI详细配置(Inspector可调,本地测试用) [Tooltip("是否使用后端下发的 BotConfig。false=用 Inspector 本地配置(默认,方便测试);true=用后端 GameConfig 返回的 botConfig 覆盖本地")] public bool useRemoteBotConfig = false; public GameConfig gameConfig; public ActivityConfig activityConfig; public Dictionary dic_fishTypeConfigs = new Dictionary(); public UserData user; public GameData gameData = new GameData(); public Scene scene; /// /// 头像更新事件(换了头像后触发,所有头像控件统一刷新) /// /// 头像更新事件 public event Action OnAvatarChanged; /// 头像框更新事件 public event Action OnAvatarFrameChanged; /// 用户数据更新事件(金币/钻石/等级等发生变化时触发) public event Action OnUserDataChanged; /// 头像字典(name → sprite),从 Resources/Avatar 加载 private Dictionary avatarSpriteDict = new Dictionary(); /// 头像框字典(name → sprite),从 Resources/AvatarK 加载 private Dictionary avatarFrameDict = new Dictionary(); /// 默认头像(新账号无头像时使用) private Sprite defaultAvatar; /// 默认头像框 private Sprite defaultAvatarFrame; /// 触发头像更新事件 public void TriggerAvatarChanged(Sprite sprite) { OnAvatarChanged?.Invoke(sprite); } public CameraShaker cameraShake; public Camera ZhuCam; // // 指定此方法在加载时立即调用,在显示启动动画前之前执行 // [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)] // private static void BeforeSplashScreen() // { // //平台适配 //#if UNITY_WEBGL // // 如果在 WebGL 平台上运行,立即停止启动动画 // SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate); //#else // // 如果不是在 WebGL 平台上,启动一个异步任务来停止启动动画 // System.Threading.Tasks.Task.Run(() => // { // SplashScreen.Stop(SplashScreen.StopBehavior.StopImmediate); // }); //#endif // } /// /// 初始化头像缓存(从 Resources/Avatar 加载所有Sprite) /// public void InitAvatarCache() { avatarSpriteDict.Clear(); var sprites = Resources.LoadAll("Avatar"); foreach (var s in sprites) avatarSpriteDict[s.name] = s; } /// /// 根据名称获取头像 Sprite /// public Sprite GetAvatarSprite(string avatarName) { if (avatarSpriteDict.Count == 0) InitAvatarCache(); if (string.IsNullOrEmpty(avatarName) || !avatarSpriteDict.TryGetValue(avatarName, out var sprite)) sprite = GetDefaultAvatar(); return sprite; } private Sprite GetDefaultAvatar() { if (defaultAvatar == null && avatarSpriteDict.Count > 0) { // 取缓存中第一个头像作为默认 foreach (var kv in avatarSpriteDict) { defaultAvatar = kv.Value; break; } } return defaultAvatar; } /// /// 更换头像:上传服务端 → 更新本地 → 触发全局刷新 /// public void ApplyAvatar(string avatarUrl) { APIRequestList.UpdateAvatar(avatarUrl, (result) => { user.BaseInfo.avatarUrl = avatarUrl; user.BaseInfo.avatarSprite = null; var sprite = GetAvatarSprite(avatarUrl); TriggerAvatarChanged(sprite); }); } // ==================== 头像框 ==================== /// 触发头像框更新事件 public void TriggerAvatarFrameChanged(Sprite sprite) { OnAvatarFrameChanged?.Invoke(sprite); } /// /// 初始化头像框缓存(从 Resources/AvatarK 加载所有Sprite) /// public void InitAvatarFrameCache() { avatarFrameDict.Clear(); var sprites = Resources.LoadAll("AvatarK"); foreach (var s in sprites) avatarFrameDict[s.name] = s; } /// /// 根据名称获取头像框 Sprite /// public Sprite GetAvatarFrameSprite(string avatarFrameName) { if (avatarFrameDict.Count == 0) InitAvatarFrameCache(); if (string.IsNullOrEmpty(avatarFrameName) || !avatarFrameDict.TryGetValue(avatarFrameName, out var sprite)) sprite = GetDefaultAvatarFrame(); return sprite; } private Sprite GetDefaultAvatarFrame() { if (defaultAvatarFrame == null && avatarFrameDict.Count > 0) { foreach (var kv in avatarFrameDict) { defaultAvatarFrame = kv.Value; break; } } return defaultAvatarFrame; } /// /// 更换头像框:上传服务端 → 更新本地 → 触发全局刷新 /// public void ApplyAvatarFrame(string avatarFrameName) { APIRequestList.UpdateAvatarFrame(avatarFrameName, (result) => { user.BaseInfo.avatarFrame = avatarFrameName; var sprite = GetAvatarFrameSprite(avatarFrameName); TriggerAvatarFrameChanged(sprite); }); } public void UpdataUserData(UserData user) { this.user = user; OnUserDataChanged?.Invoke(); } protected override void Awake() { // ⭐ botConfig 默认初始化,避免 null 导致技能系统不跑 if (botConfig == null) botConfig = new BotConfig(); // ⭐ 游戏启动时加载已保存的画质和帧率设置 int quality = PlayerPrefs.GetInt("GraphicsQuality", 1); QualitySettings.SetQualityLevel(quality, true); int fps = PlayerPrefs.GetInt("TargetFps", 1); Application.targetFrameRate = fps switch { 0 => 30, 1 => 60, 2 => -1, _ => 60 }; AudioResourcesData audioResourcesData = new AudioResourcesData(); InItLoad(); //TurretResourcesData turretResourcesData = new TurretResourcesData(); Application.runInBackground = true; base.Awake(); cameraShake = Camera.main.GetComponent(); gameData.currUser = "123"; //string json = Resources.Load("Config/GameConfig").text; //gameConfig = JsonConvert.DeserializeObject>(json).data; APIManager.Response(APIType.GameConfig_Get, res => { gameConfig = res; var v = CreateFishManager.Instance.CreateDic; foreach (var item in gameConfig.fishTypeConfigs) { dic_fishTypeConfigs[item.fishNumber] = item; } // ⭐ 后端 BotConfig 覆盖本地(开关开启且后端返回了 botConfig) if (useRemoteBotConfig && gameConfig.botConfig != null) { botConfig = gameConfig.botConfig; Debug.Log("[BotConfig] 已使用后端下发的配置覆盖本地"); } }); APIRequestList.GetActivityConfig(res => { activityConfig = res; }); } public async Task InItLoad() { await TurretResourcesData.LoadTurretAssetsData(); } public void StartGame(Action action) { switch (gameData.currGameType) { case GameType.JQQD: break; case GameType.defaultPanel: UIManager.Instance.ShowAsync(UIPanel.MainGamePanelDefault); break; case GameType.FLZY: //UIManager.Instance.ShowAsync(UIPanel.MainGamePanelFLZY); ConnectGameSocket(action); break; case GameType.YYSC: ConnectGameSocket(action); break; case GameType.ZGXQ: //UIManager.Instance.ShowAsync(UIPanel.MainGamePanelZGXQ); //这里设置触发棋盘的初始化 break; case GameType.XJMH: ConnectGameSocket(action); break; case GameType.HHWK: //UIManager.Instance.ShowAsync(UIPanel.MainGamePanelDefault); ConnectGameSocket(action); break; default: break; } } /// /// 通过 /api/Room/Assign 获取房间专属 socket 地址后连接 game socket /// private void ConnectGameSocket(Action action) { string roomId = gameData.currRoomData?.roomId; if (string.IsNullOrEmpty(roomId)) { #if UNITY_EDITOR Debug.LogWarning("[GameManager] currRoomData.roomId 为空,使用默认 game socket 地址"); #endif WebSocketManager.Instance.Connect(SocketType.game, action); return; } APIRequestList.RoomAssign(roomId, url => { if (!string.IsNullOrEmpty(url)) WebSocketManager.Instance.Connect(SocketType.game, url, action); else WebSocketManager.Instance.Connect(SocketType.game, action); }); } /// /// 快速加入:用 /api/Room/QuickJoin 返回的 url 直接连 game socket(无需再调 Assign) /// /// QuickJoin 返回的房间专属 socket 地址 /// 连接成功后的回调(一般是 JoinRoom(roomId, userId, -1)) public void StartGameQuickJoin(string url, Action action) { switch (gameData.currGameType) { case GameType.FLZY: case GameType.YYSC: case GameType.XJMH: case GameType.HHWK: if (!string.IsNullOrEmpty(url)) WebSocketManager.Instance.Connect(SocketType.game, url, action); else WebSocketManager.Instance.Connect(SocketType.game, action); break; default: WebSocketManager.Instance.Connect(SocketType.game, action); break; } } // Start is called before the first frame update public Button btn_Skip; public VideoClip startVideoClip; void Start() { var v = UIManager.Instance.ShowLoadPanel(startVideoClip); UIManager.Instance.ShowAsync(UIPanel.LoginPanel, null, (a) => { v.LoadBar(100); }, 28); btn_Skip.onClick.AddListener(() => { UIManager.Instance.StopShowPanel(); UIManager.Instance.ShowAsync(UIPanel.LoginPanel, null, null, 0); v.LoadBar(100); }); } // Update is called once per frame void Update() { #if UNITY_EDITOR if (Keyboard.current.qKey.wasPressedThisFrame) { UIManager.Instance.ShowBoardGongGao("太有实力了dadadadwawafdsdrgdfghdsufhkjghjksdfdgdffghgjhgykhjkhjghjfg"); } #endif // FPS 统计 fpsFrameCount++; fpsTimer += Time.unscaledDeltaTime; if (fpsTimer >= 0.5f) { fps = Mathf.RoundToInt(fpsFrameCount / fpsTimer); fpsFrameCount = 0; fpsTimer = 0f; } } // ===== FPS 显示 ===== private int fpsFrameCount; private float fpsTimer; private int fps; void OnGUI() { // 左上角显示帧数 GUIStyle style = new GUIStyle(GUI.skin.label) { fontSize = 28, fontStyle = FontStyle.Bold }; style.normal.textColor = fps >= 50 ? Color.green : (fps >= 30 ? Color.yellow : Color.red); GUI.Label(new Rect(10, 10, 200, 40), "FPS: " + fps, style); } public void Logout(Action onDone = null) { // 关闭所有 WebSocket 连接 WebSocketManager.Instance.CloseAll(); // 清空用户数据 user = null; // 关闭所有 UI UIManager.Instance.CloseAll(); // 切换到登录界面 UIManager.Instance.ShowAsync(UIPanel.LoginPanel, null, (panel) => { onDone?.Invoke(); }); } }