1. 程式人生 > >【Unity3D技巧】在Unity中使用事件/委託機制(event/delegate)進行GameObject之間的通訊 (二) : 引入中間層NotificationCenter

【Unity3D技巧】在Unity中使用事件/委託機制(event/delegate)進行GameObject之間的通訊 (二) : 引入中間層NotificationCenter

QQ圖片20140529123319

一對多的觀察者模式機制有什麼缺點?

在前一篇部落格裡面,我們寫到:【Unity3D技巧】在Unity中使用事件/委託機制(event/delegate)進行GameObject之間的通訊,其中使用了EventHandler這個委託作為通用的事件型別,實現了一對多的觀察者模式。但是這樣做有什麼缺點呢?我們還是舉前文所說的小鳥撞上管道為例:

bird1

在這裡面,小鳥撞倒管道時,小鳥會發送一個 產生碰撞的 訊息傳送給所有觀察者,那麼,如果我們新加入一個名為天鵝,它也能在天上飛,那麼我們就要在它的類內部實現一個同樣功能的 產生碰撞的 訊息傳送給所有觀察者,這樣就產生了程式碼重複,軟體中解決程式碼重複的問題一般使用的事引入中間層的辦法,所以我仿照Cocos2d-x中的CCNotificationCenter寫了一個CCNotificationCenter來儲存各種訊息並轉發來當作中間層。

引入中間層 -- NotificationCenter

NotificationCenter基本的設計思路是基於MessageDispatcher模式的,即使用一個字典(Dictionary)來記錄各種需要轉發的資訊,以及這些資訊的觀察者,然後再恰當的時候進行訊息的轉發。NotificationCenter還應當提供觀察者訂閱和取消訂閱的方法。

NotificationCenter是基於單件模式的,它在第一次被呼叫GetInstance方法時被初始化的,使用單件的原因是要讓NotificationCenter的生命期比任何一個觀察者都長,這樣才不會出現NotificationCenter為空的情況。

在下面的程式碼裡,我把INotificationCenter做成抽象類的原因是:希望通過這個繼承這個類來建立多個子類,比如可以建立UINotificationCenter,BattleNotificationCenter,TradeNotificationCenter。來進行訊息的分組。

下面我把自己的程式碼分享一下,供大家參考:

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

// NotificationCenter的拓展類,在這裡弄出多個INotificationCenter的子類,
// 分別處理不同的訊息轉發,便於訊息分組 public class NotificationCenter : INotificationCenter { private static INotificationCenter singleton; private event EventHandler GameOver; private event EventHandler ScoreAdd; private NotificationCenter() : base() { // 在這裡新增需要分發的各種訊息 eventTable["GameOver"] = GameOver; eventTable["ScoreAdd"] = ScoreAdd; } public static INotificationCenter GetInstance() { if (singleton == null) singleton = new NotificationCenter(); return singleton; } } // NotificationCenter的抽象基類 public abstract class INotificationCenter { protected Dictionary<string, EventHandler> eventTable; protected INotificationCenter() { eventTable = new Dictionary<string, EventHandler>(); } // PostNotification -- 將名字為name,傳送者為sender,引數為e的訊息傳送出去 public void PostNotification(string name) { this.PostNotification(name, null, EventArgs.Empty); } public void PostNotification(string name, object sender) { this.PostNotification(name, name, EventArgs.Empty); } public void PostNotification(string name, object sender, EventArgs e) { if (eventTable[name] != null) { eventTable[name](sender, e); } } // 新增或者移除了一個回撥函式。 public void AddEventHandler(string name, EventHandler handler) { eventTable[name] += handler; } public void RemoveEventHandler(string name, EventHandler handler) { eventTable[name] -= handler; } }

對觀察者進行抽象化 -- 引入Observer

在加入了NotificationCenter之後,我們要面對的下一個問題就是,我們的每一個觀察者都需要在自己的Start方法中添加回調函式,在OnDestroy方法中取消回撥函式,那麼,我們可以把這部分的程式碼抽象在一個Observer元件中,使用另一個字典記載下所有的該GameObject註冊的回撥函式,在Observer的OnDestroy方法裡面一次全部取消訂閱。程式碼如下:

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

public class Observer : MonoBehaviour {
    private INotificationCenter center;
    private Dictionary<string, EventHandler> handlers;

    void Awake() {
        handlers = new Dictionary<string, EventHandler>();
        center = NotificationCenter.GetInstance();
    }

    void OnDestroy() {
        foreach (KeyValuePair<string, EventHandler> kvp in handlers) {
            center.RemoveEventHandler(kvp.Key, kvp.Value);
        }
    }

    public void AddEventHandler(string name, EventHandler handler) {
        center.AddEventHandler(name, handler);
        handlers.Add(name, handler);
    }
}

相關推薦

Unity3D技巧Unity使用事件/委託機制event/delegate進行GameObject之間通訊

引子 在前面兩篇文章: 我們瞭解了2D中的Sprite,Animation,RigidBody和Collider,在繼續開發遊戲的過程中,我們會遇到這樣的問題,如何處理GameObject之間的相互呼叫,比如說在FlappyBird中我們在小鳥撞倒管子的時候,要把這個訊息通知給許多GameOb

Unity3D技巧Unity使用事件/委託機制event/delegate進行GameObject之間通訊 () : 引入中間NotificationCenter

一對多的觀察者模式機制有什麼缺點? 在前一篇部落格裡面,我們寫到:【Unity3D技巧】在Unity中使用事件/委託機制(event/delegate)進行GameObject之間的通訊,其中使用了EventHandler這個委託作為通用的事件型別,實現了一對多的觀察者模式。但是這樣做有什麼

Unity使用事件/委託機制event/delegate進行GameObject之間通訊

C#中標準的委託型別 我們在構建事件/委託機制的時候,首先要定義委託型別,參考在Cocos2d-x中的CCCallback,我先定義了以下三種類型的委託: // 該委託不傳任何引數 public delegate void CallFunc(); // 該委託會傳入發生事件的GameObject,即sen

JS事件迴圈機制event loop

一 前言 相信所有學過 JavaScript 都知道它是一門單執行緒的語言,這也就意味著 JS 無法進行多執行緒程式設計,但是 JS 當中卻有著無處不在的非同步概念 。在初期許多人會把非同步理解成類似多執行緒的程式設計模式,其實他們中有著很大的差別,要完全理解非

Unity技巧Unity的優化技術

移動設備 完整 物體 動態 多少 each blank screen text 寫在前面 這一篇是在Digital Tutors的一個系列教程的基礎上總結擴展而得的~Digital Tutors是一個非常棒的教程網站,包含了多媒體領域很多方面的資料,非常酷!除此之外,還

Unity3D技巧一個簡單的Unity-UI框架的實現

如何使用 請直接匯入UnityUIFramework這個UnityPackage,然後進入名為Test的Scene即可開始體驗各種特性,Enjoy!你可以通過訪問我的Github進行查閱和下載。 View,Context和UI的定義 UI是遊戲中主要介面和它的子節點上的物體的統稱,如裝備列表介面中的裝備列表

技巧Eclipse 創建Maven項目後沒有WEB-INF文件夾以及web.xml文件

出現 可能 pan 3.0 開始 自動創建 TP 應該 xml文件 懶得截圖了,一張圖配下面步驟搞定。 1、右鍵項目,選擇propertities後選擇圖中①(被遮住了); 2、先不②勾選去掉,點擊Apply;然後在把②處勾選上。此時④位置會出現東東,點擊藍色超鏈接。填入

隨堂筆記unitysocket的用法、伺服器與客戶端之間簡單的資料傳遞

主要實現伺服器與客戶端之間簡單的資料傳輸(單次) 伺服器程式碼 using System; using System.Net; using System.Net.Sockets; namespace SeverSocket { class Program {

unity3d開發unity接入unity Ads詳細流程

unity官方提供的廣告外掛unity Ads總體來說還是很方便的,目前只支援安卓和iOS的廣告,而且官方已經處理好了unity和安卓或者iOS的呼叫所以根本不需要再為平臺編寫中介軟體進行互動,這點還是很棒的。 看看unity官方宣傳,拿《天天過馬路》45天賺了1百萬美元

Unity3d基礎Unity換裝系統(2)

using UnityEngine; using System.Collections; using System.Collections.Generic; public class CombineMesh : MonoBehaviour { void OnGUI() { i

Flume原始碼分析flume事件Event的資料結構分析以及Event分流

前言 首先來看一下flume官網中對Event的定義 一行文字內容會被反序列化成一個event【序列化是將物件狀態轉換為可保持或傳輸的格式的過程。與序列化相對的是反序列化,它將流轉換為物件。這兩個過程結合起來,可以輕鬆地儲存和傳輸資料】,event的最大定義為2048位元

Android-3Android的任務棧Task

集合 情況下 清除 bsp 生命周期方法 任務棧 保存 sin 也會 一、Android任務棧 概述:Android中的任務棧其實就是Activity的集合,在Android中退出程序的時候必須把任務棧中的所有Activity清除出棧,此時才能安全的完全的退出程序, 任務棧

Java事件委託機制的簡單Demo

public class Test04_DelegatedEvent { //Java中的事件委託機制 //監聽器就是使用了事件委託機制的設計模式實現的,例如swing中的監聽器 //事件委託機制比觀察者模式耦合度更低 //觀察者模式程式碼:略(需要一個被觀察者介

物流系統——C#Oracle批量匯入

前提     匯入資料量1W,因為在小編做這個xml匯入之前系統中已經有execl匯入了,小編也沒多想,就按照前人的封裝做了一版,數量不大的時候使用起來完全沒有毛病。     封裝在DbHelper中,執行多條SQL語句,實現資料庫事務的方法。資料庫用的Oracle

HDU 5305Friends 多校第二場雙向DFS

tor typedef type clu name article using ring eof 依據題意的話最多32條邊,直接暴力的話 2 ^ 32肯定超時了。我們能夠分兩次搜索時間復雜度降低為 2 * 2 ^ 16 唯一須要註意的就是對眼下狀態的哈希處理。 我採用

蘿蔔學院產品經理實戰訓練營課程67課完整版

產品經理 註意 pan 百度網盤 思考 洞察力 職場 修煉 為什麽 課程大致目錄:第1課時 產品經理入門自我修煉必備第2課時 產品6問第3課時 產品要關註的用戶體驗設計原則和能力第4課時 敏銳的洞察力及碎片時間的利用第5課時 日常生活的思考及分享從自己開始第6課時 市場分析

敏捷開發經驗構件庫-Java版exp-libs

完整原文(含原始碼):http://exp-blog.com/2018/09/22/pid-2382/ (轉載請註明出處,僅供分享學習,嚴禁用於商業用途) 環境 簡介 此構件庫為本人多年程式設計總結提煉而成,把常用的功能模組作為原子API

Qt事件處理機制event

Qt事件也就是Qt程式中出現的一系列“事情”,包括對使用者操作做出反應時發出的滑鼠或鍵盤事件等;以及系統內部自動發出的定時器事件等。總之,出現了這些事件後就需要對這些事件進行處理,處理的方法便是“事件處理機制”。 圖1 Qt事件產生 以

遊戲開發directx遊戲專案——第一部分未完

目的: 編寫啟動渲染系統的程式碼,用於初始化Direct3D,將螢幕清屏為指定的顏色以及關閉系統。 main.h標頭檔案 //main.h #ifndef _UGP_MAIN_H_ #define _UGP_MAIN_H_ #include "StrandedE

資料結構鏈式棧的實現C語言

棧的鏈式儲存稱為鏈式棧,鏈式棧是一種特殊的單鏈表,它的插入和刪除規定在單鏈表的同一端進行。鏈式棧的棧頂指標一般用top表示。(個人理解:相當於只對單鏈表的第一個結點進行操作) 鏈式棧要掌握以下基本操作: 1、建立一個空鏈式棧 2、判斷鏈式棧是否為空 3、讀鏈式棧的