调用协同程序

LuaCoroutine.lua.txt

  1. local util = require "xlua.util" -- 加载 Resources/xlua/util.lua.txt
  2. local coroutineInstance = CS.UnityEngine.GameObject.FindObjectOfType(typeof(CS.shenjun.Coroutine))
  3. local function async_yield_return(to_yield, cb)
  4. coroutineInstance:InvokeSpawn(to_yield, cb)
  5. end
  6. -- 将调用C#协同的方法 转换为可以在lua协同中调用的方法 yield_return需要在lua协同中执行
  7. local yield_return = util.async_to_sync(async_yield_return)
  8. local function coroutine_callback()
  9. print("lua coroutine over! callback done!")
  10. end
  11. local function co_function()
  12. print("lua coroutine start")
  13. local wt = CS.UnityEngine.WaitForSeconds(3)
  14. yield_return(wt, coroutine_callback)
  15. end
  16. -- local co = coroutine.create(co_function)
  17. function Start()
  18. -- coroutine.resume(co)
  19. util.coroutine_call(co_function)()
  20. end
  21. --[===[ lua coroutine 语法
  22. --[[ 协同案例1 (基本语法)
  23. fun1 = function()
  24. print("hello")
  25. end
  26. -- 创建一个协同程序 co
  27. co = coroutine.create(fun1)
  28. -- 协同程序的4种状态 suspendedrunningdeadnormal
  29. -- 创建完协同程序以后,处于suspended状态
  30. print("status : ", coroutine.status(co))
  31. -- 启动协同程序(第一次唤醒)
  32. coroutine.resume(co)
  33. -- 协同程序运行完以后,处于dead状态,再次执行没效果
  34. print("status : ", coroutine.status(co))
  35. -- 再次唤醒已经dead的协同程序,无反应,说明不会再次执行了
  36. coroutine.resume(co)
  37. print("status : ", coroutine.status(co))
  38. -- 协同程序处理dead状态,再次唤醒,返回false及一条错误信息
  39. print(coroutine.resume(co))
  40. ]]
  41. --[[ 协同案例2 yield方法)
  42. -- 协同的强大之处 coroutine.yield()
  43. -- 方法中有yield语句
  44. -- 作用:让一个运行中的程序挂起,而之后可以恢复它的运行
  45. co = coroutine.create(function()
  46. print("start coroutine function")
  47. for i=1, 3 do
  48. print("co :", i)
  49. coroutine.yield()
  50. end
  51. end)
  52. -- 处于suspended状态
  53. print(coroutine.status(co))
  54. -- 第一次唤醒,运行到yield方法时返回,挂起发生在yield调用中
  55. coroutine.resume(co) -- 打印1
  56. print("1", coroutine.status(co))
  57. -- 第二次唤醒,从上一次的yield的调用中返回,继续执行,碰到yield再挂起
  58. coroutine.resume(co) -- 打印2
  59. print("2", coroutine.status(co))
  60. -- 第三次唤醒
  61. coroutine.resume(co) -- 打印3
  62. print("3", coroutine.status(co))
  63. print("3-4", coroutine.status(co)) -- suspended状态
  64. -- 第四次唤醒
  65. coroutine.resume(co) -- 什么都不打印
  66. print("4", coroutine.status(co))
  67. --]]
  68. -- 当一个协同程序A唤醒一个协同程序B时,协同程序A就处于一个特殊状态,
  69. -- 既不是挂起状态(无法继续A的执行),也不是运行状态(是B在运行)。
  70. -- 所以将这时的状态称为“正常”状态。
  71. -- Lua的协同程序还具有一项有用的机制,就是可以通过一对resume-yield来交换数据。
  72. --[[ 协同案例3 (带参数协同)
  73. -- 创建一个带参数的协同程序
  74. co = coroutine.create(function(a, b)
  75. for i=1,3 do
  76. print("co", a, b, i)
  77. coroutine.yield()
  78. end
  79. end)
  80. -- 第一次唤醒 参数12传给function
  81. coroutine.resume(co, 10, 20) -- 缺少参数使用nil,多余的参数舍弃
  82. -- 第二次唤醒
  83. coroutine.resume(co, 100, 200) -- 传入100200无效,有其他用途
  84. --]]
  85. --[[ 协同案例4 resume的返回值)
  86. co = coroutine.create(function(a, b)
  87. coroutine.yield(a + b, a - b)
  88. return 6, 7
  89. end)
  90. -- 第一次唤醒
  91. -- resume的返回值中,第一个返回值为true表示没有错误
  92. -- 2个返回值以及之后的,都对应yield传入的参数
  93. print(coroutine.resume(co, 10, 3)) -- true 13 7
  94. -- 当一个协同程序结束时,它的所有返回值都作为resume的返回值。
  95. print(coroutine.resume(co)) -- true 6 7
  96. --]]
  97. --[[ 协同案例5 yield的返回值
  98. co = coroutine.create(function()
  99. print("co", coroutine.yield("yield"))
  100. end)
  101. -- 第一次唤醒,传入的参数“a”是传给方法的,由于方法没有参数,所以舍弃“a
  102. print("1", coroutine.resume(co, "a")) -- "1" true yield
  103. -- 第二次唤醒,传入的参数12,作为yield的额外返回值使用(yield返回的额外值就是对应resume传入的参数)
  104. print("2", coroutine.resume(co, 1, 2)) -- "co" 1 2 -- "2" true
  105. print("3", coroutine.resume(co, 100, 200)) -- "3" false cannot resume dead coroutine
  106. --]]
  107. --[[ *协同案例6* 协同程序的嵌套使用(管道与过滤器)
  108. -- 唤醒传入的迭代器
  109. function receive(prod)
  110. local status, value = coroutine.resume(prod);
  111. return value;
  112. end
  113. funcition send(x)
  114. coroutine.yield(x)
  115. end
  116. -- 返回一个挂起的协同程序 协同程序中需要有yield
  117. function producer()
  118. return coroutine.create(function()
  119. while true do
  120. local x = io.read
  121. send(x) -- 产生新值
  122. end
  123. end)
  124. end
  125. function filter(prod)
  126. return coroutine.create(function()
  127. for line = 1, math.huge do
  128. local x = receive(prod) -- 接收producer产生的值
  129. x = string.format("%5d %s", line, x)
  130. send(x) -- 把新值发送给消费者
  131. end
  132. end)
  133. end
  134. function consumer(prod)
  135. while true do
  136. local x = receive(prod) -- 获取新值
  137. io.write(x, "\n") -- 消费新值
  138. end
  139. end
  140. -- 运行代码
  141. consumer(filter(producer))
  142. --]]
  143. ]===]

LuaCoroutine.cs

  1. /*
  2. * created by shenjun
  3. */
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using XLua;
  8. namespace shenjun
  9. {
  10. [LuaCallCSharp]
  11. public class Coroutine : MonoBehaviour {
  12. LuaEnv luaEnv = new LuaEnv();
  13. void Start () {
  14. luaEnv.DoString("require 'LuaCoroutine'");
  15. System.Action luaStart = luaEnv.Global.Get<System.Action>("Start");
  16. if (null != luaStart)
  17. luaStart();
  18. }
  19. void Update () {
  20. }
  21. private void OnDestroy()
  22. {
  23. luaEnv.Dispose();
  24. }
  25. public void InvokeSpawn(object yield_return, System.Action callback)
  26. {
  27. StartCoroutine(SpawnObj(yield_return, callback));
  28. }
  29. IEnumerator SpawnObj(object yield_return, System.Action callback)
  30. {
  31. for (int i = 0; i < 10; i++)
  32. {
  33. GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  34. go.transform.position = Random.insideUnitSphere * 5;
  35. if(yield_return is IEnumerator)
  36. {
  37. yield return StartCoroutine(yield_return as IEnumerator);
  38. }
  39. else
  40. {
  41. yield return yield_return;
  42. }
  43. }
  44. callback();
  45. }
  46. }
  47. [LuaCallCSharp]
  48. public static class CoroutineConfig
  49. {
  50. public static List<System.Type> LuaCallCSharp
  51. {
  52. get{
  53. return new List<System.Type>()
  54. {
  55. typeof(WaitForSeconds)
  56. };
  57. }
  58. }
  59. }
  60. }

?