注:需要了解C#的迭代器,不然很难理解。

之前面试有被问到unity协程的原理,以及撇开unity用纯C#去实现协程的方法。后来了解一下,确实可以的。趁这会有空,稍微总结一下。

还是结合代码说事吧:

 /// <summary>
/// 等待接口
/// </summary>
public interface IWait
{
/// <summary>
/// 每帧检测是否等待结束
/// </summary>
/// <returns></returns>
bool Tick();
}

先定义一个等待接口,WaitForSeconds 和 WaitForFrames 实现接口的Tick()方法,每一帧调用Tick()方法检测是否等待结束

 /// <summary>
/// 按秒等待
/// </summary>
public class WaitForSeconds:IWait
{
float _seconds = 0f; public WaitForSeconds(float seconds)
{
_seconds = seconds;
} public bool Tick()
{
_seconds -= Time.deltaTime;
return _seconds <= ;
}
}
 /// <summary>
/// 按帧等待
/// </summary>
public class WaitForFrames:IWait
{
private int _frames = ;
public WaitForFrames(int frames)
{
_frames = frames;
} public bool Tick()
{
_frames -= ;
return _frames <= ;
}
}

定义 WaitForSeconds 和 WaitForFrames ,在构造函数初始化需要等待的时间/帧数

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; public class CoroutineManager
{
private static CoroutineManager _instance = null;
public static CoroutineManager Instance
{
get
{
if (_instance == null)
{
_instance = new CoroutineManager();
}
return _instance;
}
} private LinkedList<IEnumerator> coroutineList = new LinkedList<IEnumerator>(); public void StartCoroutine(IEnumerator ie)
{
coroutineList.AddLast(ie);
} public void StopCoroutine(IEnumerator ie)
{
try
{
coroutineList.Remove(ie);
}
catch (Exception e) { Console.WriteLine(e.ToString()); }
} public void UpdateCoroutine()
{
var node = coroutineList.First;
while (node != null)
{
IEnumerator ie = node.Value;
bool ret = true;
if (ie.Current is IWait)
{
IWait wait = (IWait)ie.Current;
//检测等待条件,条件满足,跳到迭代器的下一元素 (IEnumerator方法里的下一个yield)
if (wait.Tick())
{
ret = ie.MoveNext();
}
}
else
{
ret = ie.MoveNext();
}
//迭代器没有下一个元素了,删除迭代器(IEnumerator方法执行结束)
if (!ret)
{
coroutineList.Remove(node);
}
//下一个迭代器
node = node.Next;
}
}
}

这一段代码是这里最重要的部分。这里用一个链表记录了添加的所有“协程”,并在UpdateCoroutine()方法的每一次执行都去遍历这些“协程”以及检测等待是否结束。

 public class Time
{
//每帧时间(秒)
public static float deltaTime
{ get { return (float)deltaMilliseconds / ; } }
//每帧时间(毫秒)
public static int deltaMilliseconds
{ get { return ; }}
}

模拟一帧的时间。

运用测试:

 public class Program
{
static void Main(string[] args)
{
var t1 = Test01();
var t2 = Test02();
CoroutineManager.Instance.StartCoroutine(t1);
CoroutineManager.Instance.StartCoroutine(t2); while (true)// 模拟update
{
Thread.Sleep(Time.deltaMilliseconds);
CoroutineManager.Instance.UpdateCoroutine();
}
} static IEnumerator Test01()
{
Console.WriteLine("start test 01");
yield return new WaitForSeconds();
Console.WriteLine("after 5 seconds");
yield return new WaitForSeconds();
Console.WriteLine("after 10 seconds");
} static IEnumerator Test02()
{
Console.WriteLine("start test 02");
yield return new WaitForFrames();
Console.WriteLine("after 500 frames");
}
}

测试结果:

用秒表掐了 一下,好像没什么毛病。

用C# 模拟实现unity里的协程的更多相关文章

  1. Unity中的协程(一)

    这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines   这篇文章转自:http://blog.csdn. ...

  2. Unity C#笔记 协程

    什么是协程 协同程序,在主程序运行的同时,开启另外一段逻辑处理,来协同当前程序的执行. 可能看了这段文字介绍还是有点模糊,其实可以用多线程来比较. 多线程 多线程,顾名思义,多条同时执行的线程. 最初 ...

  3. Unity中的协程是什么?

    什么是协程? 1.协程是一个分部执行,遇到条件(yield return 语句)会挂起,直到条件满足才会被唤醒继续执行后面的代码. 2.Unity在每一帧(Frame)都会去处理对象上的协程.Unit ...

  4. Unity中使用协程进行服务端数据验证手段

    近期在做项目中的个人中心的一些事情,用户头像上传,下载,本地缓存,二级缓存,压缩,这些都要做,麻雀虽小五脏俱全啊,也是写的浑浑噩噩的, 当我们在上传用户头像的时候,向服务端发送上传头像请求之前,一般都 ...

  5. unity 自实现协程总结

    unity本人自实现了一个协程调用. 只是moveNext()的简单协程调用和封装,这个没什么好说的, 网上例子一大堆. 但使用的过程中遇到了几个问题. 1. 自己写的moveNext() 协程不能等 ...

  6. Unity XLua之协程

    如何使用xlua实现协程,示例代码如下: 转载请注明出处:https://www.cnblogs.com/jietian331/p/10735773.html local unpack = unpac ...

  7. xlua 实现协程替换Unity中的协程

    C#中的协程: IEnumerator ShowSpiritInfo() { UIMessageMgr.ShowMsgWait(true); DestroyUIModelInfo(); bool is ...

  8. 【Unity笔记】协程Coroutine的简单优化

    一个最简单的协程,也至少需要2帧才能完成.第一帧走到yield return null停止,第二帧从此处接着执行完下面的操作.需求:如果缓存中存在某数据则直接使用,否则联网异步下载. private ...

  9. Go语言模拟文件断点续传以及多协程读取写入文件操作

    今天整理了一个Go语言多协程拷贝文件的案例,之前用Java写过,这次用Go语言来写一下,代码不难,也很简单,但是网上没有案例,整了很长时间.下面贴出来,供其他人参考学习. func main(){ f ...

随机推荐

  1. BDD实战篇 - .NET Core里跑Specflow - 可以跑集成测试和单元测试

    这是<如何用ABP框架快速完成项目 >系列中和DevOps系列文章其中一篇文章.   BDD很赞!比TDD先进很多,能够大大提高编码效率.   上一篇文章说了如何在.NET Core里安装 ...

  2. 通过 python ssh库连接并发送命令给设备

    import paramiko import time hostname = '192.168.248.156' port = 22 user = 'zhou' passwd = ' paramiko ...

  3. 判断字符串a和b是否互为旋转词

    旋转词:把字符串str的任意部分移动到后面形成的新字符串叫做字符串str的旋转词. 比如abc的旋转词有 abc,acb,cba,... 判断str1和str2是否互为旋转词,其最优解可以是时间复杂度 ...

  4. Android 四大组件之broadcast的理解

    Android广播的两种类型: 1.静态广播 2.动态广播 静态注册广播: Manifeast中的代码块: <receiver android:name=".broadcast.MyS ...

  5. Unity编译时找不到AndroidSDK的问题 | Unable to list target platforms(转载)

    原文:http://www.jianshu.com/p/fe4c334ee9fe 现象 在用 Unity 编译 Android 平台的应用时,遇到 Unable to list target plat ...

  6. JHipster开发环境安装

    本文演示如何在CentOS7上安装Jhipster以及其依赖组件. 这里采用官方推荐的Yarn安装方法,操作系统版本为CentOS 7.4. 1 安装JDK 推荐版本:OpenJDK 1.8.0-64 ...

  7. Linux学习历程——Centos 7重置root密码

    一.自述 最近刚刚接触linux,因为我设置密码比较随性,把自己做系统的时候设置的root密码给forget,每当系统崩溃,重新把虚拟机备份还原后,就面临无法登陆的尴尬情况,只得重置root密码,好了 ...

  8. 【转载】Python中的垃圾回收机制

    GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...

  9. vim 高亮

    vim 高亮显示所选单词在文中全部出现的地方: ’g' + 'd'

  10. js判断手机系统

    var u = navigator.userAgent; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > - ...