Unity进阶之ET网络游戏开发框架 08-深入登录成功消息

版权申明:

  • 本文原创首发于以下网站:
  1. 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123
  2. 优梦创客的官方博客:https://91make.top
  3. 优梦创客的游戏讲堂:https://91make.ke.qq.com
  4. 『优梦创客』的微信公众号:umaketop
  • 您可以自由转载,但必须加入完整的版权声明!

由来

  • 上篇文章中,我们修改了登录页面的异步处理,下面我们修改登录成功后进入主游戏场景的代码:
namespace ETHotfix
{
    [Event(MyEventType.MyLoginFinish)]
    class MyLoginFinish : AEvent
    {
        public override void Run()
        {
            RunAsync().Coroutine();
        }

        private async ETVoid RunAsync()
        {
            Log.Debug("移除登录UI");
            UI uiLogin = Game.Scene.GetComponent<UIComponent>().Get(MyUIType.MyStartUI.ToString());
            uiLogin.GameObject.SetActive(false);

            Log.Debug("加载游戏场景");

            // 方法1:同步加载
            //SceneManager.LoadScene(1);

            // 方法2:从ab包异步加载
            var rc = ETModel.Game.Scene.GetComponent<ResourcesComponent>();

            await rc.LoadBundleAsync(MySceneType.MyGame.StringToAB());

            // 异步加载游戏场景
            using (var scc = ETModel.Game.Scene.AddComponent<SceneChangeComponent>())
            {
                await scc.ChangeSceneAsync(MySceneType.MyGame); // => SceneManager.LoadSceneAsync(MySceneType.MyGame)
            } // SceneChangeComponent.Dispose()会从该组件所在的Entity上移除其自身

            // 发出场景加载完毕消息
            Game.EventSystem.Run(MyEventType.MyGameSceneLoaded);
        }
    }
}

场景切换

  • 这里的场景切换组件就有点意思了!先上代码再分析:
[ObjectSystem]
public class SceneChangeComponentUpdateSystem: UpdateSystem<SceneChangeComponent>
{
    public override void Update(SceneChangeComponent self)
    {
        if (self.loadMapOperation.isDone)
        {
            self.tcs.SetResult();
        }
    }
}

public class SceneChangeComponent: Component
{
    public AsyncOperation loadMapOperation;
    public ETTaskCompletionSource tcs;
    public float deltaTime;
    public int lastProgress = 0;

    public ETTask ChangeSceneAsync(string sceneName)
    {
        this.tcs = new ETTaskCompletionSource();
        // 加载map
        this.loadMapOperation = SceneManager.LoadSceneAsync(sceneName);
        return this.tcs.Task;
    }

    public int Process
    {
        get
        {
            if (this.loadMapOperation == null)
            {
                return 0;
            }
            return (int)(this.loadMapOperation.progress * 100);
        }
    }

    public void Finish()
    {
        this.tcs.SetResult();
    }

    public override void Dispose()
    {
        if (this.IsDisposed)
        {
            return;
        }

        if (this.Entity.IsDisposed)
        {
            this.Entity.RemoveComponent<SceneChangeComponent>();
        }

        base.Dispose();
    }
}
  • ETTaskCompletionSource和ETTask的关系就好比Unity中Animator和AnimationClip的关系——前者是任务管理者,后者是被管理者
  • 首先,外部调用ChangeSceneAsync()方法时,该方法会创建一个ETTask对象tcs和一个异步加载场景的AsyncOperation对象loadMapOperation
  • 但是,细心的同学会发现,这两者( tcs和loadMapOperation对象)并无关联!
  • 唯一一点联系,大概就是代码最上端的组件更新系统SceneChangeComponentUpdateSystem中Update函数一直不停检测loadMapOperation.isDone标志,并据此调用tcs.SetResult()方法
  • 但即使如此,也未发现SceneChangeComponent类中Process属性和Finish被调用的痕迹(没有直接调用,也不是被override的virtual方法),经打印测试,这两个成员都没有被调用,也许是留作手动获取场景加载进度(Process)和手动结束场景加载(Finish())的吧!

计划:

  • 下一步就要进入到游戏场景的玩法实现了,做了这么多铺垫,就要进入真正和游戏玩法相关的部分了!

猜你喜欢

转载自www.cnblogs.com/raymondking123/p/11369739.html