This commit is contained in:
2026-10-17 03:01:15 +08:00
parent 1932b8569b
commit c26b86c37a
435 changed files with 4037850 additions and 16884 deletions
@@ -8,6 +8,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
namespace Assets.MyGame.Scripts.Net
@@ -17,6 +20,15 @@ namespace Assets.MyGame.Scripts.Net
/// <summary>已加载(或正在加载)的游戏场景名集合,防止人机 RoomJoinNotice 触发重复 LoadSceneAsync</summary>
private static readonly HashSet<string> _loadedGameScenes = new HashSet<string>();
/// <summary>
/// 游戏场景的 Addressables 加载句柄。
/// 游戏场景(XJMH/FLZY/HHWK/YYSC)里挂的是热更脚本(BGManager/BgFit 等),
/// HybridCLR 要求热更脚本所在场景必须通过 AB/AA 加载,否则运行时会变成 missing script。
/// 卸载时也必须用这个句柄释放,不能只调 SceneManager.UnloadSceneAsync(否则 ab 包会泄漏)。
/// </summary>
private static readonly Dictionary<string, AsyncOperationHandle<SceneInstance>> _gameSceneHandles
= new Dictionary<string, AsyncOperationHandle<SceneInstance>>();
/// <summary>清除指定场景的加载标记(退出游戏时调用,下次进入可重新加载)</summary>
public static void ClearLoadedGameScene(string sceneName)
{
@@ -125,8 +137,7 @@ namespace Assets.MyGame.Scripts.Net
var s = SceneManager.GetSceneByName(sn);
if (s.IsValid() && s.isLoaded)
{
SceneManager.UnloadSceneAsync(sn);
_loadedGameScenes.Remove(sn);
UnloadGameScene(sn);
}
}
@@ -187,8 +198,19 @@ namespace Assets.MyGame.Scripts.Net
var targetScene = SceneManager.GetSceneByName(sceneName);
if (!targetScene.IsValid() || !targetScene.isLoaded)
{
var op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
while (op != null && !op.isDone) yield return null;
// ⭐ 必须通过 Addressables 加载:场景里挂的是热更脚本(Game.Hotfix 里的 BGManager/BgFit 等),
// 如果走 Build Settings(随主包)加载,热更脚本会解析失败变成 missing script —— 背景就会不动。
var handle = Addressables.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
_gameSceneHandles[sceneName] = handle;
while (!handle.IsDone) yield return null;
if (handle.Status != AsyncOperationStatus.Succeeded)
{
Debug.LogError($"[GameScene] Addressables 加载场景失败: {sceneName} → {handle.OperationException}。" +
$"请确认已在 Addressables 里把该场景标记为可寻址,且 address = \"{sceneName}\"。");
_loadedGameScenes.Remove(sceneName);
_gameSceneHandles.Remove(sceneName);
}
}
}
@@ -197,6 +219,26 @@ namespace Assets.MyGame.Scripts.Net
fishPanel.BeginLoadResources();
}
/// <summary>
/// 卸载一个已加载的游戏场景。
/// 如果该场景是通过 Addressables 加载的,必须用句柄释放(否则 ab 包会一直驻留);
/// 没有句柄时退回 SceneManager 卸载,兼容历史上用 SceneManager 加载的场景。
/// </summary>
public static void UnloadGameScene(string sceneName)
{
if (_gameSceneHandles.TryGetValue(sceneName, out var handle))
{
if (handle.IsValid())
Addressables.UnloadSceneAsync(handle, true);
_gameSceneHandles.Remove(sceneName);
}
else
{
SceneManager.UnloadSceneAsync(sceneName);
}
_loadedGameScenes.Remove(sceneName);
}
/// <summary>
/// 把 RoomJoinNotice 玩家数据写入 currRoomData.players(存在则更新,不存在则添加)。
/// JoinGame 里 SetUserInfo 按 userId 从 currRoomData.players 查显示信息