任务8:前端-登录注册界面和使用UI组件及ReferenceCollector

为了方便大家练习,本节提供了登录注册界面资源,下载后放到\Assets\Bundles\Landlords\目录下。

LandLogin.zip (163.56KB)

使用ReferenceCollector脚本为游戏物体绑定游戏资源

Global下面创建UI空物体

使用ReferenceCollector脚本添加引用绑定Canvas在UI物体上

绑定方法是:

  1. 选择需要添加引用绑定的物体,给他挂ReferenceCollector脚本
  2. 拖动层级面板中的物体到右边Reference组件上面“添加引用”下方的空白处,即可挂载绑定元件

Global下面创建一个Camera

设置为Depth only,UI,Orthographic

把Camera作为Canvas的渲染相机

Bundles>picture 下有Loading图片设置为Sprite。

在层级面板中,Canvas下创建一个Image,把上面的Loading_bg作为Source

LandLogin界面的元件绑定

注意一下啊,可能你下载界面资源到你的项目目录,用unity打开项目后,出现丢失脚本的问题,
你需要对照上面的图都一一重新挂好ReferenceCollector脚本,并挂载好界面元件。

而且需要一一把丢失脚本的元件都挂好ReferenceCollector脚本并挂载好绑定元件,再保存,不然是保存不了的。

在前端的Init.cs中添加UI组件和调用初始场景界面

\Assets\Model\Init.cs

//添加UI组件
Game.Scene.AddComponent<UIComponent>();

//执行斗地主初始事件,也就是创建LandLogin界面
Game.EventSystem.Run(UIEventType.LandInitSceneStart);

Run的参数UIEventType.LandInitSceneStart是如何关联到我们定义的事件方法的呢?

如下图,我们只需要给定义的事件方法加上[Event(UIEventType.LandInitSceneStart)]特性,就可以用Game.EventSystem.Run() 方法调用对应的事件方法。(接下来UIEventType.cs中有定义)

在前端添加UIEventType

 \Assets\Model\Landlords\LandUI\UIEventType.cs 

using System;
using System.Collections.Generic;

namespace ETModel
{

    public static partial class LandUIType
    {
        public const string LandLogin = "LandLogin";
        
    }

    public static partial class UIEventType
    {
        public const string LandInitSceneStart = "LandInitSceneStart";
    }
    
    [Event(UIEventType.LandInitSceneStart)]
    public class InitSceneStart_CreateLandLogin : AEvent
    {
        public override void Run()
        {
            Game.Scene.GetComponent<UIComponent>().Create(LandUIType.LandLogin);
        } 
    }

}

添加登录注册界面的工厂类LandLoginFactory

上面我们使用 Game.Scene.GetComponent<UIComponent>().Create(LandUIType.LandLogin) 即是调用LandLoginFactory创建了登录注册界面。

这是如何做到的呢?

ETCore帮我们实现了对程序集中有定义了[UIFactory(LandUIType.LandLogin)]特性的类对象的Create方法的调用。

\Assets\Model\Landlords\LandUI\LandLogin\LandLoginFactory.cs

using System;
using UnityEngine;

namespace ETModel
{
    [UIFactory(LandUIType.LandLogin)]
    public class LandLoginFactory:IUIFactory
    {
        public UI Create(Scene scene, string type, GameObject parent)
        {
            try
            {
                //加载AB包
                ResourcesComponent resourcesComponent = Game.Scene.GetComponent<ResourcesComponent>();
                resourcesComponent.LoadBundle($"{type}.unity3d");

                //加载登录注册界面预设并生成实例
                GameObject bundleGameObject = (GameObject)resourcesComponent.GetAsset($"{type}.unity3d", $"{type}");
                GameObject landLogin = UnityEngine.Object.Instantiate(bundleGameObject);

                //设置UI层级,只有UI摄像机可以渲染
                landLogin.layer = LayerMask.NameToLayer(LayerNames.UI);
                UI ui = ComponentFactory.Create<UI, GameObject>(landLogin);

                ui.AddComponent<LandLoginComponent>();
                return ui;
            }
            catch (Exception e)
            {
                Log.Error(e);
                return null;
            }
        }

        public void Remove(string type)
        {
            Game.Scene.GetComponent<ResourcesComponent>().UnloadBundle($"{type}.unity3d");
        }
    }
    
}

添加LandLoginComponent组件

上面在LandLogin工厂中创建了登录界面:

UI ui = ComponentFactory.Create<UI, GameObject>(landLogin);
ui.AddComponent<LandLoginComponent>();

这就是ETCore的UI组件的用法:

  • 传入UI实例创建UI实体
  • UI实体添加UI组件
  • 在UI组件中获取UI的绑定元件和添加事件方法等

借助ReferenceCollector 组件,获取绑定引用

ReferenceCollector rc = this.GetParent<UI>().GameObject.GetComponent<ReferenceCollector>()

例如LandLoginComponent,UI组件的父对象是UI实体,UI实体持有UI实例,再获取实例上的ReferenceCollector脚本组件。

\Assets\Model\Landlords\LandUI\LandLogin\LandLoginComponent.cs 

using UnityEngine;
using UnityEngine.UI;
namespace ETModel
{
    [ObjectSystem]
    public class LandLoginComponentAwakeSystem : AwakeSystem<LandLoginComponent>
    {
        public override void Awake(LandLoginComponent self)
        {
            self.Awake();
        }
    }

    public class LandLoginComponent : Component
    {
        //提示文本
        public Text prompt;

        public InputField account;
        public InputField password;

        //是否正在登录中(避免登录请求还没响应时连续点击登录)
        public bool isLogining;
        //是否正在注册中(避免登录请求还没响应时连续点击注册)
        public bool isRegistering;

        public void Awake()
        {
            ReferenceCollector rc = this.GetParent<UI>().GameObject.GetComponent<ReferenceCollector>();

            //初始化数据
            account = rc.Get<GameObject>("Account").GetComponent<InputField>();
            password = rc.Get<GameObject>("Password").GetComponent<InputField>();
            prompt = rc.Get<GameObject>("Prompt").GetComponent<Text>();
            this.isLogining = false;
            this.isRegistering = false;

            //添加事件
            rc.Get<GameObject>("LoginButton").GetComponent<Button>().onClick.Add(() => LoginBtnOnClick());
            rc.Get<GameObject>("RegisterButton").GetComponent<Button>().onClick.Add(() => RegisterBtnOnClick());
        }

        public void LoginBtnOnClick()
        {
            if (this.isLogining || this.IsDisposed)
            {
                return;
            }
            this.isLogining = true; 
        }

        public void RegisterBtnOnClick()
        {
            if (this.isRegistering || this.IsDisposed)
            {
                return;
            }
            this.isRegistering = true;
        }
    }
}

大功告成,Unity中Play运行,就可以看到登录注册界面了!

posted @ 2023-01-30 18:51  Domefy  阅读(114)  评论(0编辑  收藏  举报