毕设项目需要用到UNet,而UNet有大量的回调函数,需要在回调时进行相应的逻辑处理
例如匹配房间列表会回调NetworkLobbyManager.OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList), 需要根据回调函数传来的信息进行逻辑处理。如果直接在回调函数中写逻辑代码就会显得逻辑混乱,脱离了UGF的模块化思想。UGF的Procedure是专门用来分离逻辑的,我希望UNet所有的回调可以通过EventComponent.Subscribe()来订阅,并统一在Procedure中进行逻辑处理。
一.自定义事件类
例如UGF内置的打开UI成功事件,Subscribe第一个参数是事件分发ID,第二个参数是回调函数。OpenUIFormSuccessEventArgs类相当于一个桥梁,用于传递变量,比如我们可以在回调事件中访问成功打开的这个UIForm,这样就可以在打开成功后对该UIForm进行初始化。
UGF.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OpenUIFormSuccess);
private void OpenUIFormSuccess(object sender, GameEventArgs e)
{
OpenUIFormSuccessEventArgs uiEvent = (OpenUIFormSuccessEventArgs)e;
Log.Info("Open UIForm({0}) Success",uiEvent.UIForm.UIFormAssetName);
}
以自定义MatchList为例:
①首先创建一个事件类继承GameFramework.Event.GameEventArgs
②重写基类抽象方法,其中Id是事件Id, Clear()清理事件
③添加事件需要的变量,匹配游戏房间回调函数OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)包含的参数都需要定义在事件类中以实现参数传递
④初始化事件变量,Fill(arg0,arg1....)函数是为了把OnMatchList回调方法的形参赋值给事件对应的变量
using GameFramework.Event;
using System.Collections.Generic;
using UnityEngine.Networking.Match;
namespace ShadowTank
{
public sealed class UNetMatchListEventArgs : GameEventArgs
{
public static readonly int EventId = typeof(UNetMatchListEventArgs).GetHashCode();
public override int Id
{
get
{
return EventId;
}
}
public bool Success { get; private set; }
public string ExtendedInfo { get; private set; }
public List<MatchInfoSnapshot> MatchList { get; private set; }
public override void Clear()
{
Success = false;
ExtendedInfo = default(string);
MatchList = null;
}
public UNetMatchListEventArgs Fill(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)
{
Success = success;
ExtendedInfo = extendedInfo;
MatchList = matchList;
return this;
}
}
}
二、设置事件的唤醒环境
我希望NetworkLobbyManager.OnMatchList()回调时会调用已订阅的UNetMatchListEventArgs事件
①新建一个类继承UnityEngine.Networking.NetworkLobbyManager并重写OnMatchList方法
②定义引用委托链表头和事件成员的增/减:
private EventHandler<UNetMatchListEventArgs> m_MatchListEventHandler;
public event EventHandler<UNetMatchListEventArgs> UNetMatchList
{
add
{
m_MatchListEventHandler += value;
}
remove
{
m_MatchListEventHandler -= value;
}
}
③在OnMatchList方法执行委托,ReferencePool.Acquire是从引用池获取对象,如果没有会自动创建:
public override void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)
{
base.OnMatchList(success, extendedInfo, matchList);
if(null!=m_MatchListEventHandler)
{
lock (m_MatchListEventHandler)
{
m_MatchListEventHandler(this, ReferencePool.Acquire<UNetMatchListEventArgs>().Fill(success, extendedInfo, matchList));
}
}
}
撸了这么多代码你以为这就算搞定了?那你就太小看UGF的上手难度了,本着UGF一贯对新手不友好的作风,你可能得花两天时间来自定义一个逻辑事件
三、自定义框架组件
我需要将NetworkLobbyManager的功能封装到框架组件,方便管理和模块间的访问。
①新建一个类继承UnityGameFramework.Runtime.GameFrameworkComponent
②抛出事件(将事件添加到事件队列)
using UnityEngine;
using GameFramework;
using UnityGameFramework.Runtime;
using System;
namespace ShadowTank
{
public class UNetComponent : GameFrameworkComponent
{
[SerializeField]
private UNetLobbyManager m_LobbyManager = null;
protected override void Awake()
{
base.Awake();
m_LobbyManager.UNetMatchList += OnMatchList;
}
private void OnMatchList(object sender, UNetMatchListEventArgs e)
{
//抛出事件
UGF.Event.Fire(this, e);
}
}
}
是不是有点乱?乱就对了。来捋捋思路,我们在UNetComponet类中把UNetComponet.OnMatchList()方法通过“m_LobbyManager.UNetMatchList += OnMatchList“附加给了委托UNetLobbyManager.m_MatchListEventHandler,这时候m_MatchListEventHandler非空,所以UNetLobbyManager.OnMatchList()回调时会执行m_MatchListEventHandler委托,相当于执行了UNetComponet.OnMatchList()把事件抛出,事件池中已订阅的事件就会被调用。
四、订阅自定义逻辑事件并验证
为了验证自定义逻辑事件是不是能用,写个Procedure订阅一个事件看看是否成功调用:
protected override void OnEnter(IFsm<IProcedureManager> procedureOwner)
{
base.OnEnter(procedureOwner);
UGF.Event.Subscribe(UNetMatchListEventArgs.EventId, (object sender, GameEventArgs e) => {
var info = (UNetMatchListEventArgs)e;
Log.Info("匹配游戏房间是否成功:{0}",info.Success);
});
}
验证成功!自定义逻辑事件就是这么..........................简单(mmp,写了这么多装个13不介意吧)