性能优化:游戏对象之间的通信方式比较之消息系统

第4种:消息传递系统。任何游戏对象都可以通过该系统把消息传递给任何可能该消息感兴趣的对象。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
 * Author:W
 * 消息系统
 */

/// <summary>
/// 消息基本类型
/// </summary>
public class Msg
{
	public string type;

	public Msg() {
		type = this.GetType().Name;
	}
}


/// <summary>
/// 侦听器回调类型定义
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public delegate bool OnMsgHandlerDelegate(Msg msg);

/// <summary>
/// 游戏消息传递系统
/// </summary>
public class MessageSystem : MonoSingleton<MessageSystem> {

	/// <summary>
	/// 游戏消息侦听回调列表
	/// </summary>
	private Dictionary<string, List<OnMsgHandlerDelegate>> msgListenerDict = new Dictionary<string, List<OnMsgHandlerDelegate>>();


	/// <summary>
	/// 限制当前帧处理时间的阔值,超过该值,游戏可能会出现卡顿,我们可以通过该检测指标
	/// 来衡量是否暂停当前帧的消息的处理,剩下的消息留到下一帧来继续处理
	/// </summary>
	private const int maxQueueProcessTime = 16667;
	private System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
	/// <summary>
	/// 待处理的消息队列
	/// </summary>
	private Queue<Msg> QueueMsgs = new Queue<Msg>();
	/// <summary>
	/// 将要传递的消息压入消息队列中【性能优化版的消息处理】
	/// 比较适合对当前帧不那么重要的消息。
	/// </summary>
	/// <param name="msg"></param>
	public void EnqueueMsg(Msg msg)
	{
		if (!msgListenerDict.ContainsKey(msg.type))
		{
			return;
		}

		QueueMsgs.Enqueue(msg);
	}

	void Update()
	{
		timer.Start();
		while (QueueMsgs.Count > 0)
		{
			//当前帧消息处理时间超过我们预设的阔值,说明会影响到游戏的流畅,此时应该终止当前帧对消息的
			//继续处理
			if (maxQueueProcessTime > 0)
			{
				if (timer.Elapsed.Milliseconds > maxQueueProcessTime)
				{
					timer.Stop();
					return;
				}
			}


			Msg curMsg = QueueMsgs.Dequeue();
			//当前消息处理
			TrigeerMsg(curMsg);
		}
	}


	/// <summary>
	/// 消息处理【立即处理消息】
	/// 特点:对帧率影响比较大
	/// 比较适合需要立马处理地消息,否则会导致奇怪的现象发生。
	/// </summary>
	/// <param name="msg"></param>
	public void TrigeerMsg(Msg msg)
	{
		string typeName = msg.type;

		if (!msgListenerDict.ContainsKey(typeName))
		{
			Debug.Log("消息列表中没有该类型的消息");
			return;
		}

		List<OnMsgHandlerDelegate> onMsgHandlerDelegates = msgListenerDict[typeName];
		for (int i = 0; i < onMsgHandlerDelegates.Count; i++)
		{
			onMsgHandlerDelegates[i](msg);
		}
	}


	/// <summary>
	/// 消息监听注册
	/// </summary>
	/// <param name="msgType"></param>
	/// <param name="onMsgHandlerDelegate"></param>
	public void AddMsgListener(System.Type msgType, OnMsgHandlerDelegate onMsgHandlerDelegate)
	{
		if (msgType == null)
		{
			Debug.Log("消息类型为Null,消息侦听注册不上");
			return;
		}

		string typeName = msgType.Name;
		if (!msgListenerDict.ContainsKey(typeName))
		{
			msgListenerDict.Add(typeName,new List<OnMsgHandlerDelegate>());
		}

		List<OnMsgHandlerDelegate> onMsgHandlerDelegates = msgListenerDict[typeName];
		if (onMsgHandlerDelegates.Contains(onMsgHandlerDelegate))
		{
			Debug.Log("该侦听回调已经注册了,无需重复注册");
			return;
		}

		onMsgHandlerDelegates.Add(onMsgHandlerDelegate);
	}


	/// <summary>
	/// 消息监听注销
	/// </summary>
	/// <param name="msgType"></param>
	/// <param name="onMsgHandlerDelegate"></param>
	public void RemoveMsgListener(System.Type msgType, OnMsgHandlerDelegate onMsgHandlerDelegate)
	{
		if (msgType == null)
		{
			Debug.Log("消息类型为Null,注销失败!");
			return;
		}

		string typeName = msgType.Name;
		if (!msgListenerDict.ContainsKey(typeName))
		{
			Debug.Log("没有该消息的侦听回调,注销失败!");
			return;
		}

		List<OnMsgHandlerDelegate> onMsgHandlerDelegates = msgListenerDict[typeName];
		if (!onMsgHandlerDelegates.Contains(onMsgHandlerDelegate))
		{
			Debug.Log("该消息的侦听回调列表中没有该回调,注销失败!");
			return;
		}

		onMsgHandlerDelegates.Remove(onMsgHandlerDelegate);

	}
}

总结:这是优化版的消息传递分发系统。需要立马处理的消息使用TriggerMsg()接口;对及时性或当前帧影响不大的,推荐使用EnqueueMsg()接口。后者对性能比较友好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Data菌

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

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

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

打赏作者

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

抵扣说明:

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

余额充值