Unity3D C# IEnumerator与 IEnumerable(2) 托管使用

1. 首先创建单例模式类

using System;
using UnityEngine;

// 首先定义一个单例模式类并且也继承MonoBehaviour
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    private static T instance = null; //单例模式变量
    public static T Instance          //变量get方法
    {
        get
        {
            if (instance != null) return instance; //空判断
            Type type = typeof(T);                 // 
            T localInstance = GameObject.FindObjectOfType(type) as T; // 检测实例是否存在
            if (localInstance == null)
            {
                string typeName = type.ToString();
                var gameObject = new GameObject(typeName, type);
                localInstance = gameObject.GetComponent<T>();
                if (localInstance == null)
                    Debug.LogError("Problem during the creation of " + typeName, gameObject);
                else
                    Initialize(localInstance);
            }
            return instance;
        }
    }
    // 第一次创建的时候 对创建类进行一下关联的初始化
    private static void Initialize(T localInstance)
    {
        if (instance == null)
        {
            instance = localInstance;
            instance.OnInitialize();
            OnInstanceReady();
        }
        else if (instance != localInstance)
        {
            DestroyImmediate(localInstance.gameObject); //如果创建的类和存在的类不一致 则立即收回资源
        }
    }
    protected virtual void Awake()        // 虚函数 创建实例的类 挂在对象加载时 如果不重写Awake方法 单例实例会被立刻创建
    {
        Initialize(this as T);
    }
    private void OnApplicationQuit()      // 销毁的执行顺序  OnApplicationQuit OnDisable OnDestroy
    {
        Destroyed(this as T);
    }
    private void OnDisable()
    {
        Destroyed(this as T);
    }
    private void OnDestroy()
    {
        Destroyed(this as T);
    }
    private static void Destroyed(T localInstance)
    {
        if (instance == localInstance)
        {
            instance.OnFinalize();
            instance = null;
        }
    }
    public virtual void OnInitialize() {} //虚函数 创建实例的类 创建时可以重写此方法 创建后可执行初始化
    public virtual void OnFinalize() {}   //虚函数 创建实例的类 创建时可以重写此方法 销毁对象之前会调用
    ///////////////////////////////////////////////////////////////////////
    public static bool Exists
    {
        get { return instance != null; }
    }
    public static bool IsInstanceReady
    {
        get { return instance != null; }
    }
    //////////////////////////////单例被创建后 调用Event事件进行相应处理 /////////////////////////////////////////
    public static event EventHandler InstanceReady;
    private static void OnInstanceReady()
    {
        var handler = InstanceReady;
        if (handler != null)
            handler(null, EventArgs.Empty);
    }
}


2. Scheduler 执行顺序管理类

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Scheduler : MonoSingleton<Scheduler>
{
    private Queue<Action> tasks = new Queue<Action>(); // Queue(队列)类主要实现了一个FIFOFirst In First Out,先进先出)的机制
//1. 挂在对象启动后 实例化单例模式
    //2. 当加载一个新关卡时,所有场景中所有的物体被销毁,然后新关卡中的物体被加载进来。
// 为了保持在加载新关卡时物体不被销毁,使用DontDestroyOnLoad保持,
    // 如果物体是一个组件或游戏物体,它的整个transform层次将不会被销毁,全部保留下来。
protected virtual void Awake() { base.Awake();
DontDestroyOnLoad(
this); } public void Schedule(Action task) { if (task == null) return; lock (tasks) tasks.Enqueue(task); } public Coroutine AwaitNextFrame(Action onDone) { if (onDone == null) return null; return StartCoroutine(AwaitNextFrameInternal(onDone)); } public Coroutine AwaitForSeconds(float seconds, Action onDone) { if (seconds < 0.0f || onDone == null) return null; return StartCoroutine( x => x.Return = new WaitForSeconds(seconds), x => onDone()); } public Coroutine While(Func<bool> statement, Action onDone) { if (statement == null || onDone == null) return null; return StartCoroutine(RunWhile(statement, onDone)); } public Coroutine StartCoroutine(params Func<object>[] statements) { if (statements.Length == 0) return null; return StartCoroutine(RunStatements(statements)); } public Coroutine StartCoroutine(params Action<ReturnValue>[] statements) { if (statements.Length == 0) return null; return StartCoroutine(RunStatements(statements)); } // === privates ================================================================ private void Update() { lock (tasks) { int throttle = 15; while (tasks.Count > 0 && throttle > 0) { tasks.Dequeue()(); throttle--; } } } private static IEnumerator RunStatements(Func<object>[] statements) { foreach (var statement in statements) { var st = statement(); if (st is IEnumerator) yield return Scheduler.Instance.StartCoroutine((IEnumerator)st); else yield return st; } } private static IEnumerator RunStatements(Action<ReturnValue>[] statements) { foreach (var statement in statements) { var param = new ReturnValue(); statement(param); if (param.Return is IEnumerator) yield return Scheduler.Instance.StartCoroutine((IEnumerator)param.Return); else yield return param.Return; } } private static IEnumerator RunWhile(Func<bool> statement, Action onDone) { while (statement()) yield return null; onDone(); } private static IEnumerator AwaitNextFrameInternal(Action callback) { yield return null; callback(); } public class ReturnValue { public object Return; } }

3 使用方式

使用方式1

Scheduler.Instance.StartCoroutine(InitializeBattleAsync());

private
IEnumerator InitializeBattleAsync() { battleCharacterManager = new BattleCharacterManager(); yield return battleCharacterManager.CreateRawGameObject( new CharacterCreationInfo(CharacterType.Summon, CharacterClass.SummonDragon), go => { summon = go; //托管 第五步执行 summon.SetActive(false); }); }
public class BattleCharacterManager : IBattleCharacterManager
{
// 逻辑函数第二步调用 CreateOneCharacterInstanceAsync 执行结束后返回
public YieldInstruction CreateRawGameObject(CharacterCreationInfo characterCreationInfo, Action<GameObject> whenDone) { return Scheduler.Instance.StartCoroutine(CreateOneCharacterInstanceAsync(characterCreationInfo, whenDone)); }
// 逻辑处理函数第三部调用
private IEnumerator CreateOneCharacterInstanceAsync(CharacterCreationInfo info, Action<GameObject> whenDone) { if (whenDone == null) throw new ArgumentNullException("whenDone"); UnityEngine.Object prefab = null; if (characterPrefabs.TryGetValue(info.CharacterClass, out prefab) == false) { var basePath = BattleConstants.CharacterConstants.CharacterPrefabsPath; if (info.CharacterType == CharacterType.Summon) basePath = BattleConstants.CharacterConstants.SummonPrefabsPath; var prefabFullPath = basePath + ResolvePrefabName(info); var resourceRequest = Resources.LoadAsync(prefabFullPath); yield return resourceRequest; yield return null; prefab = resourceRequest.asset; if (prefab == null) throw new InvalidOperationException("Impossible to find prefab '" + prefabFullPath + "'"); characterPrefabs.Add(info.CharacterClass, prefab); } var instance = GameObject.Instantiate(prefab) as GameObject; if (instance == null) throw new InvalidOperationException("Impossible to create instance of prefab '" + info.CharacterClass + "'");
// 托管执行 whenDone(instance); } }

使用方式2

void battleWin
{
    SceneManager.Instance.RootStateMachine.PerformAction(RootActionTokens.Next);
    // result win 
    Scheduler.Instance.StartCoroutine(
        x => x.Return = new WaitForSeconds(0.5f),
        x => BattleResult.Instance.BattleWin());
    return;
}


使用方式3 :

 private void RunAwaiter(CharacterAnimationStates state, Action whenDone)
 {
        Scheduler.Instance.While(
()
=> { if (previousState != state) { RequestAction(state); return true; } return false; }, () => { if (whenDone != null) whenDone(); }); }

使用方式4

public void UnloadCurrentMap()
{
     Scheduler.Instance.AwaitNextFrame(
()
=> { OnMapUnloaded(new MapEventArgs(CurrentStage, StartPositions)); CurrentStage = Stages.None; }); }

 

posted on 2014-10-24 17:36  小魔一剑  阅读(1690)  评论(0编辑  收藏  举报