GameFramework---事件(四)

特别提示: 本系列基于Unity 2019.4.8,框架版本GameFramework 2021.05.31

本系列博客地址: 传送门

Game Framework 支持在游戏逻辑监听、抛出事件。其中很多模块在完成操作后都会抛出内置事件,监听这些事件将大大解除游戏逻辑之间的耦合。除了 Game Framework 内置事件外,使用者也可以定义自己的游戏逻辑事件,游戏中所有事件均派生自 GameEventArgs 类,事件对象使用了引用池技术,以避免使用事件过程中频繁的内存分配。

对事件还不熟的先自行去补基础, Game Framework 内置事件都已经写好了直接使用就行了,这里讲讲怎么使用自定义事件

一、创建自定义事件

所有的事件都继承GameEventArgs 类,变量跟方法可以随意定义,但是最少包含Id和Clear()方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework.Event;
using GameFramework;


public class KeyCodePressEventArgs : GameEventArgs
{
	public static readonly int EventId = typeof(KeyCodePressEventArgs).GetHashCode();
	public override int Id
	{
		get { return EventId; }
	}
	public KeyCode KeyCode
	{
		get;
		private set;
	}
	public KeyCodePressEventArgs()
	{
		KeyCode = KeyCode.None;
	}
	public static KeyCodePressEventArgs Create(KeyCode keyCode)
	{
		// 使用引用池技术,避免频繁内存分配
		KeyCodePressEventArgs keyCodePressEventArgs = ReferencePool.Acquire<KeyCodePressEventArgs>();
		keyCodePressEventArgs.KeyCode = keyCode;
		return keyCodePressEventArgs;
	}
	public override void Clear()
	{
		// 使用引用池技术,注意清理事件实例数据
		KeyCode = KeyCode.None;
	}


}

二、订阅自定义事件

可以写在任意地方只要逻辑没有错误
在这里插入图片描述
官方建议定义一个EventHandler,来降低将方法转换为 EventHandler 时的内存开销

EventHandler<GameEventArgs> KeyCodePressEventHandler;
KeyCodePressEventHandler = KeyCodePress;
eventComponent.Subscribe(KeyCodePressEventArgs.EventId, KeyCodePressEventHandler);
eventComponent.Unsubscribe(KeyCodePressEventArgs.EventId, KeyCodePressEventHandler);

三、抛出事件

达到特定条件抛出事件,执行所有订阅此事件的回调函数在这里插入图片描述

四、取消订阅

事件的订阅与取消订阅在使用生命周期内,应当成对出现。Game Framework 会严格检查事件订阅的匹配情况,不允许出现重复订阅,也不允许出现重复取消订阅或取消订阅尚未订阅的事件处理函数,如果出现这些情况,将会抛出异常。在这里插入图片描述

五、常见问题

1、错误地缓存了事件实例

事件处理函数处理事件时,不应该缓存 GameEventArgs 实例,GameEventArgs 实例的有效生命周期,仅限于事件处理函数内。Game Framework 为了降低内存分配,事件实例使用了引用池技术。一个事件被其所有事件处理函数处理完成后,事件实例会被立刻清理并回收(调用 GameEventArgs 中的 Clear 方法)。后续逻辑访问缓存的事件实例时,将无法访问到任何有效数据。因此,缓存事件实例是完全错误的,这将导致难以追踪的 BUG。

//这是错误的示例!
KeyCodePressEventArgs keyCodePressEventArgs=null;
void KeyCodePress(object sender, GameEventArgs e)
{
	keyCodePressEventArgs = (KeyCodePressEventArgs)e;
	Log.Error($"{keyCodePressEventArgs.KeyCode}被按下");
}

2、自定义事件类的 Clear 方法实现不完整


自定义事件类使用了引用池技术,事件实例是会被复用的。当回收某个事件实例时,不完整的 Clear 实现无法清理干净事件实例中的数据,进而将脏数据带到下一次复用事件实例的逻辑中去,这可能导致难以追踪的 BUG。


3、事件模块不工作


事件模块需要被轮询才能正常调用事件处理函数,请确认正确初始化了 Game Framework。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫铭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值