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(队列)类主要实现了一个FIFO(First 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;
        });
}
时间: 2024-11-10 22:11:33

C# IEnumerator与 IEnumerable(2) 托管使用的相关文章

C# IEnumerator与 IEnumerable

1. 接口的使用 (1)  首先定义接口 public interface IBattleMapManager : { Stages CurrentStage { get; } event EventHandler<BeginFightEventArgs> EnterFight; } (2) 用定义实现类- 实现接口 public class BattleMapManager : IBattleMapManager, IDisposable { public Stages CurrentSta

IEnumerator和IEnumerable接口

枚举器和可枚举类型 前面我们已经知道了使用foreach语句可以遍历数组中的元素.但是为什么那么做呢? 原因是数组按需提供了一个叫做枚举器的对象.枚举器可以依次返回请求数组中的元素. 枚举器知道项的次序并且跟踪它所在序列中的位置,然后返回请求的当前项. 获取一个对象枚举器的方法是调用对象的GetEnumerator方法.实现GetEnumerator方法的类型叫做可枚举类型. 数组是可枚举类型. IEnumerator接口 实现了IEnumerator接口的枚举器包含3个函数成员:Current

IEnumerator和IEnumerable详解

IEnumerator和IEnumerable 从名字常来看,IEnumerator是枚举器的意思,IEnumerable是可枚举的意思. 了解了两个接口代表的含义后,接着看源码: IEnumerator: public interface IEnumerator { // Interfaces are not serializable // Advances the enumerator to the next element of the enumeration and // returns

在自己的对象里实现IEnumerator和IEnumerable

平时工作中我们经常用foreach来迭代一个集合.比如 1 foreach (Student student in myClass) 2 { 3 Console.WriteLine(student); 4 } 5 基本所有的集合都能够foreach,但是必须要实现IEnumerable接口.IEnumerable接口很简单,就只有一个IEnumerator GetEnumerator() 方法.看这个方法的定义就知道,仅仅是公开了另一个接口IEnumerator.而IEnumerator才是真正

【C#】 26. 关于IEnumerable和IEnumerator

终于把硕士所有的课业都完成了... 今天就写一点关于IEnumerator和IEnumerable这两个概念,之前写金融模型的时候用到过,当时也没太搞清楚,这两天看了C#in Depth,觉得里面解释的不错,虽然例子有点错误.所以今天就写一篇关于这两个概念的文章. 首先,我有一个先入为主的概念,IEnumerable就好比是一个数组类型.一想到数组,我们就能很轻而易举地联想到Foreach遍历的语法.那么问题是Foreach是怎么实现的呢?答案就是你调用Foreach的时候这个类似数组的IEnu

IList, ICollection ,IEnumerable AND IEnumerator in C#

IList, ICollection ,IEnumerable 很显然,这些都是集合接口的定义,先看看定义: 1 // 摘要: 2 // 表示可按照索引单独访问的对象的非泛型集合. 3 [ComVisible(true)] 4 public interface IList : ICollection, IEnumerable 5 { 6 7 bool IsFixedSize { get; } 8 9 bool IsReadOnly { get; } 10 11 object this[int i

C# IEnumerable、IEnumerator和foreach的联系与解析

1.关于foreach和for foreach和for都是循环的关键字,使用这两个关键字可以对集合对象进行遍历,获取里面每一个对象的信息进行操作. static void Main(string[] args) { string[] strList = new string[] { "1","2","3","4" }; for (int i = 0; i < strList.Length; i++) { Console.

IEnumerable、IEnumerator与yield的学习

我们知道数组对象可以使用foreach迭代进行遍历,同时我们发现类ArrayList和List也可以使用foreach进行迭代.如果我们自己编写的类也需要使用foreach进行迭代时该怎么办呢? IEnumerable: 1 public interface IEnumerable 2 { 3 IEnumerator GetEnumerator(); 4 } 如果自己编写的类需要foreach进行迭代就需要实现IEnumerable接口,表示当前的类可以进行迭代. 我们发现该接口唯一的方法返回的

IEnumerator/ IEnumerable/ yield return/ StartCoroutine 详解

IEnumerator/ IEnumerable public interface IEnumerable { IEnumerator GetEnumerator(); } public interface IEnumerator { bool MoveNext(); void Reset(); Object Current { get; } } 在两者的使用上,有下面几点需要注意 1.一个Collection要支持foreach方式的遍历,必须实现IEnumerable接口(亦即,必须以某种方