前言
很遗憾,Mirror包括UNET的场景管理不支持Addressables。我做手机游戏,需要实现服务器广播场景切换,但主程序没有场景,热更代码和资源都在AB包里。我已经在Google上搜索了一段时间,没有找到有用的解决方案。
Reddit上的某人建议使用Fishnet,它支持Addressables。但这在项目进行到一半的时候是不可能的。所以我自己动手开始改NetworkManager。后来考虑了一下,寻思抽出来做一个demo开源,真的希望能帮助/启发那些也在找解决办法苦苦挣扎的人。
https://github.com/Shepherd0619/MirrorAddressablesDemo
说实话,只要你知道Mirror如何管理场景,改造就不会很复杂。
我把所有的自定义脚本和2个演示场景(源自TanksDemo)放在了_Project文件夹下。
目前能发现的是原先拖拖乐的OnlineScene和OfflineScene我没做支持,但这个我感觉一般都不会用那个东西。
最终效果如图:
1. Host/Server:
2. 客户端侧:
实现
如果你希望自己将Addressables实现到Mirror的场景管理中,你需要按照以下步骤进行操作,这也是我实现过程的概述:
1. Editor下右键空白处使用Mirror的模板创建自己的NetworkManager。(如果你已经有一个,请跳过此步骤。)
2. 将'loadingSceneAsync'的类型更改为'AsyncOperationHandle'。
public static new AsyncOperationHandle<SceneInstance> loadingSceneAsync;
3. 重写/覆盖场景管理代码块下的几乎所有函数,包括但不限于ServerChangeScene、OnClientSceneChanged、ClientChangeScene、OnClientSceneInternal和UpdateScene。
PS:我们主要用Addressable替换使用SceneManager的代码行。例如:
loadingSceneAsync = Addressables.LoadSceneAsync(newSceneName);
4. 需要注意的一点是'UpdateScene'函数调用的NetworkClient.AddPlayer。由于loadingSceneAsync现在是一个结构体,你不能将其设置为null,并且在加载完成后,需要一段时间让loadingSceneAsync.IsValid()变为false。因此,我将结构体设置为default,以防止多次调用FinishLoadScene。
5. 现在应该可以运行了,不要忘记将你的场景添加到Addressables Group中。