Unity消息事件的封装(转)

Unity学了有大半年了,懵懵懂懂,不断试错。自学的难点就是会碰到很多弯路,不知道下一步该怎么学。最近买了一本Unity实战技术的书,书中的知识我感觉都是挺实用,相对于大多数只是教教基础的教程来说。

当Unity工程中模块越多,为了解耦,模块之间的消息传递肯定少不了,下面是一个简单的消息事件的封装。上代码!

事件的基类:

using UnityEngine;
using System.Collections;

public enum CEventType
{
    GAME_OVER,
    GAME_WIN,
    PAUSE,
    ENERGY_EMEPTY,
    GAME_DATA,

}

public class CBaseEvent
{
    protected Hashtable arguments;
    protected CEventType type;
    protected object sender;



    /// <summary>
    /// Type属性
    /// </summary>
    public CEventType Type
    {
        get { return this.type; }
        set { this.type = value; }
    }

    public IDictionary Params//属性
    {
        get { return this.arguments; }
        set { this.arguments = (value as Hashtable); }
    }

    public object Sender//属性
    {
        get { return this.sender; }
        set { this.sender = value; }
    }

    public override string ToString()//重写ToString
    {
        return this.type + "[" + ((this.sender == null) ? "null" : this.sender.ToString()) + "]";
    }


    /// <summary>
    /// 克隆基类的方法
    /// </summary>
    /// <returns></returns>
    public CBaseEvent Clone()
    {
        return new CBaseEvent(this.type, this.arguments, Sender);
    }

    /// <summary>
    /// 三个参数的构造函数
    /// </summary>
    /// <param name="type">类型</param>
    /// <param name="args"></param>
    /// <param name="sender"></param>
    public CBaseEvent(CEventType type, Hashtable args, object sender)
    {
        this.Type = type;
        this.arguments = args;
        this.Sender = sender;
        if (this.arguments==null)
        {
            this.arguments = new Hashtable();
        }
    }

    /// <summary>
    /// 两个参数的构造函数
    /// </summary>
    /// <param name="type"></param>
    /// <param name="sender"></param>
    public CBaseEvent(CEventType type, object sender)
    {
        this.Type = type;
        Sender = sender;
        if (this.arguments==null)
        {
            this.arguments = new Hashtable();
        }
    }
}

这个是事件派发类,包含消息注册、消息移除和消息派发的方法

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public delegate void CEventListenerDelegate(CBaseEvent evt);

public class CEventDispatcher {

    //做成单例模式
    static CEventDispatcher instance;
    public static CEventDispatcher GetInstance()
    {
        if (instance==null)
        {
            instance = new CEventDispatcher();
        }
        return instance;
    }

    //创建一个哈希表用于存放添加的监听
    private Hashtable listeners = new Hashtable();


    /// <summary>
    /// 添加监听
    /// </summary>
    /// <param name="eventType">事件类型</param>
    /// <param name="listener">监听(委托类型)</param>
    public void AddEventListener(CEventType eventType, CEventListenerDelegate listener)
    {
        //添加监听
        listeners.Add(eventType, listener);


        /*
        //直接将事件类型赋值给表,然后得到他的值
        CEventListenerDelegate ceventListenerDelegate = this.listeners[eventType] as CEventListenerDelegate;


        //把监听添加到委托当中
        ceventListenerDelegate = (CEventListenerDelegate)Delegate.Combine(ceventListenerDelegate, listener);

        //事件(委托)重新赋值给键为eventType的监听
        this.listeners[eventType] = ceventListenerDelegate;
        */
    }

    /// <summary>
    /// 移除监听
    /// </summary>
    /// <param name="eventType"></param>
    /// <param name="listener"></param>
    public void RemoveEventListener(CEventType eventType, CEventListenerDelegate listener)
    {
        /*
        CEventListenerDelegate ceventListenerDelegate = this.listeners[eventType] as CEventListenerDelegate;
        if (ceventListenerDelegate!=null)
        {
            //如果事件(委托存在),则将里面的监听移除
            ceventListenerDelegate = (CEventListenerDelegate)Delegate.Remove(ceventListenerDelegate, listener);
        }
        this.listeners[eventType] = ceventListenerDelegate;
        */

        //移除监听
        listeners.Remove(eventType);
    }

    /// <summary>
    /// 分发事件消息
    /// </summary>
    /// <param name="evt">事件类型</param>
    public void DispatchEvent(CBaseEvent evt)
    {
        //从哈希表里得到事件监听
        CEventListenerDelegate ceventListenerDelegate = this.listeners[evt.Type] as CEventListenerDelegate;

        if (ceventListenerDelegate!=null)
        {
            try
            {
                //如果事件监听不为null,则将参数:事件类型 赋值给委托,由此触发事件函数
                ceventListenerDelegate(evt);
            }
            catch
            {

            }
        }
    }

    public void RemoveAll()
    {
        this.listeners.Clear();
    }
}

在AddEventListener方法和RemoveEventListener方法中,注释的那一段是书本中原文的写法,个人不太理解是什么意思(如果有知道的大神恳请给予指点)。而且用原文写法后,测试不成功。于是乎用添加列表的方法代替了原来一大串代码,结果测试成功。

这个是我自己写的测试类

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sender : MonoBehaviour {

    // Use this for initialization

    void Start()
    {
        //注册消息
        CEventDispatcher.GetInstance().AddEventListener(CEventType.GAME_WIN, GameWin);

        //传入事件类型和object类型的Sender,如果事件类型匹配消息列表里的值,则触发事件函数
        CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.GAME_WIN, "sender"));
    }





    /// <summary>
    /// 用于测试的事件函数
    /// </summary>
    /// <param name="evt"></param>
    private void GameWin(CBaseEvent evt)
    {
        Debug.Log("Game Win!");
    }

}

这里写图片描述

初步理解了消息事件的封装,若想灵活运用,还是要在项目中多写多试。

以下是一个简单的Unity C#脚本,用于将获取网络图片并换为Sprite的过程封装成一个方法: ```c# using UnityEngine; using System.Collections; using System.Net; public class ImageDownloader : MonoBehaviour { public void DownloadImage(string url, System.Action<Sprite> onComplete) { StartCoroutine(DownloadImageCoroutine(url, onComplete)); } IEnumerator DownloadImageCoroutine(string url, System.Action<Sprite> onComplete) { using (WWW www = new WWW(url)) { yield return www; if (www.error != null) { Debug.LogError("Failed to download image: " + www.error); onComplete(null); yield break; } Texture2D texture = www.texture; Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero); onComplete(sprite); } } } ``` 这个脚本有一个名为`DownloadImage`的公共方法,用于获取网络图片并换为Sprite。这个方法有两个参数:要获取的图片的URL和一个`Action<Sprite>`类型的回调函数,用于在获取和换完成后将结果返回给调用方。 在这个方法中,我们首先启动一个协程来获取网络图片。在协程中,我们使用WWW类从网络中获取图片,然后将获取到的Texture2D对象用于创建Sprite对象。如果获取或换过程中出现错误,我们将调用回调函数并将Sprite对象设置为null。如果获取和换都成功完成了,我们将调用回调函数并将获取到的Sprite对象作为参数传递给它。 你可以将这个脚本添加到一个GameObject上,然后在需要获取网络图片并换为Sprite的地方,使用以下代码调用: ```c# ImageDownloader imageDownloader = GetComponent<ImageDownloader>(); imageDownloader.DownloadImage("https://example.com/image.png", OnImageDownloaded); void OnImageDownloaded(Sprite sprite) { // 在这里使用获取到的sprite,比如将它设置为一个UI Image的Sprite等 } ``` 在这个示例代码中,我们首先获取ImageDownloader组件,然后调用DownloadImage方法来获取网络图片并换为Sprite。在回调函数OnImageDownloaded中,我们可以使用获取到的Sprite对象进行后续的操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值