#游戏unity-VR场景漫游#统一管理回调函数——观察者模式

26 篇文章 1 订阅
13 篇文章 0 订阅

我们不防把上面这样一件工作成为一个计数器——Timer(这个名字可能不太恰当),把需要被通知者成为观察者——Oberver,而像下载管理器这样的对象成为一个主题——Subject。

首先,我们来定义观察者和主题对象。TimerObserverOrSubject.cs如下:

using UnityEngine;  
using System.Collections;  

public class TimerObserverOrSubject : MonoBehaviour {  

    virtual protected void OnDestroy ()  
    {  
        if(Singleton.IsCreatedInstance("TimerController"))  
        {  
            (Singleton.getInstance("TimerController") as TimerController).ClearTimer(this);  
        }  
    }  
}  

TimerObserverOrSubject.cs的内容非常简单,它的工作就是在该脚本被析构时,及时地从计数器管理器里面删除涉及这个对象的所有Timer。

计数器管理器的脚本——TimerController.cs如下:

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

public class TimerController : MonoBehaviour {  

    public delegate void OnCallBack(object arg);  
    public delegate bool OnIsCanDo(object arg);  

    public class Timer {  
        public TimerObserverOrSubject m_Observer;  
        public OnCallBack m_Callback = null;  
        public object m_Arg = null;  

        public TimerObserverOrSubject m_Subject;  
        public OnIsCanDo m_IsCanDoFunc = null;   
        public object m_ArgForIsCanDoFunc = null;  

        public float m_PassTime = 0;  

        public Timer(TimerObserverOrSubject observer, OnCallBack callback, object arg,   
            TimerObserverOrSubject subject, OnIsCanDo isCanDoFunc, object argForIsCanDo) {  
            m_Observer = observer;  
            m_Callback = callback;  
            m_Arg = arg;  

            m_Subject = subject;  
            m_IsCanDoFunc = isCanDoFunc;  
            m_ArgForIsCanDoFunc = argForIsCanDo;  

            m_PassTime = 0;  
                }  

        public Timer(TimerObserverOrSubject observer, OnCallBack callback, object arg, float time) {  
            m_Observer = observer;  
            m_Callback = callback;  
            m_Arg = arg;  

            m_Subject = null;  
            m_IsCanDoFunc = null;  
            m_ArgForIsCanDoFunc = null;  

            m_PassTime = time;  
        }  
        }  
    private List<Timer> m_Timers = new List<Timer>();  
    private List<Timer> m_NeedRemoveTimer = new List<Timer>();  
    private List<Timer> m_CurRunTimer = new List<Timer>();  

    /// <summary>  
    /// Sets the timer.  
    /// </summary>  
    /// <param name='observer'>  
    /// The TimerObserverOrSubject you need to listen  
    /// </param>  
    /// <param name='callback'>  
    /// The callback when condition is true.  
    /// </param>  
    /// <param name='arg'>  
    /// Argument of the callback.  
    /// </param>  
    /// <param name='observer'>  
    /// The TimerObserverOrSubject you need to observe  
    /// </param>  
    /// <param name='isCanDoFunc'>  
    /// The condition function, must return a boolean.  
    /// </param>  
    /// <param name='argForIsCanDo'>  
    /// Argument for condition function.  
    /// </param>  
    public void SetTimer(TimerObserverOrSubject observer, OnCallBack callback ,object arg,  
        TimerObserverOrSubject subject, OnIsCanDo isCanDoFunc,object argForIsCanDo) {  
        if (observer == null || subject == null || callback == null || isCanDoFunc == null) return;  

        if (isCanDoFunc(argForIsCanDo)) {  
            callback(arg);  
            return;  
        }  

        Timer timer = new Timer(observer, callback, arg, subject, isCanDoFunc, argForIsCanDo);       
        m_Timers.Add(timer);  
    }  

    /// <summary>  
    /// Sets the timer.  
    /// </summary>  
    /// <param name='observer'>  
    /// The TimerObserverOrSubject you need to listen  
    /// </param>  
    /// <param name='callback'>  
    /// The callback when time is up.  
    /// </param>  
    /// <param name='arg'>  
    /// Argument of the callback.  
    /// </param>  
    /// <param name='timepass'>  
    /// Timepass before calling the callback.  
    /// </param>  
    public void SetTimer(TimerObserverOrSubject observer, OnCallBack callback , object arg, float timepass) {  
        if (observer != null && callback != null) {             
            Timer timer = new Timer(observer, callback, arg, timepass);  
            m_Timers.Add(timer);  
        }  
    }  

    /// <summary>  
    /// Clears all Timers of the observer.  
    /// </summary>  
    /// <param name='observer'>  
    /// The TimerObserverOrSubject you need to clear  
    /// </param>  
    public void ClearTimer(TimerObserverOrSubject observer) {  
        List<Timer> needRemovedTimers = new List<Timer>();  

        foreach (Timer timer in m_Timers) {  
            if (timer.m_Observer == observer || timer.m_Subject) {  
                needRemovedTimers.Add(timer);  
            }  
        }  

        foreach (Timer timer in needRemovedTimers) {  
            m_Timers.Remove(timer);  
        }  
    }  

        // Update is called once per frame  
        void Update ()   
    {  
        InitialCurTimerDict();  
        RunTimer();  
        RemoveTimer();  
        }  

    private void InitialCurTimerDict() {  
        m_CurRunTimer.Clear();  

        foreach (Timer timer in m_Timers) {  
            m_CurRunTimer.Add(timer);  
        }  
    }  

    private void RunTimer() {  
        m_NeedRemoveTimer.Clear();  

        foreach (Timer timer in m_CurRunTimer) {          
            if (timer.m_IsCanDoFunc == null) {  
                timer.m_PassTime =  timer.m_PassTime - Time.deltaTime;  
                if (timer.m_PassTime < 0) {  
                    timer.m_Callback(timer.m_Arg);  
                    m_NeedRemoveTimer.Add(timer);  
                }  
            } else {  
                if (timer.m_IsCanDoFunc(timer.m_ArgForIsCanDoFunc)) {  
                    timer.m_Callback(timer.m_Arg);  
                    m_NeedRemoveTimer.Add(timer);  
                }  
            }     
        }  
    }  

    private void RemoveTimer() {  
        foreach (Timer timer in m_NeedRemoveTimer) {  
            if (m_Timers.Contains(timer)) {  
                m_Timers.Remove(timer);  
            }  
        }  
    }  

}  

定义了回调函数的类型:

public delegate void OnCallBack(object arg);  
public delegate bool OnIsCanDo(object arg);  

定义了一个数据类型Timer用于保存一个计数器的各个信息。

接下来,就是TimerController的两个重要的SetTimer函数。我们先看第一个SetTimer函数:

public void SetTimer(TimerObserverOrSubject observer, OnCallBack callback ,object arg,  
    TimerObserverOrSubject subject, OnIsCanDo isCanDoFunc,object argForIsCanDo) {  
    if (observer == null || subject == null || callback == null || isCanDoFunc == null) return;  

    if (isCanDoFunc(argForIsCanDo)) {  
        callback(arg);  
        return;  
       }  

    Timer timer = new Timer(observer, callback, arg, subject, isCanDoFunc, argForIsCanDo);       
    m_Timers.Add(timer);  
}  

根据函数说明可以看出,它负责建立一个计数器,当subject的isCanDoFunc(argForIsCanDo)函数返回true时,通知observer,执行observer的callback(arg)函数。

第二个SetTimer函数更简单:

public void SetTimer(TimerObserverOrSubject observer, OnCallBack callback , object arg, float timepass) {  
    if (observer != null && callback != null) {             
        Timer timer = new Timer(observer, callback, arg, timepass);  
        m_Timers.Add(timer);  
    }  
}  

它负责建立一个计数器,在timepass的时间后,通知observer,执行observer的callback(arg)函数。

Update()函数里面负责检查所有Timer是否可以触发以及是否需要删除

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值