调用协同程序

LuaCoroutine.lua.txt

    local util = require "xlua.util" -- 加载 Resources/xlua/util.lua.txt

    local coroutineInstance = CS.UnityEngine.GameObject.FindObjectOfType(typeof(CS.shenjun.Coroutine))

    local function async_yield_return(to_yield, cb)
        coroutineInstance:InvokeSpawn(to_yield, cb)
    end

    -- 将调用C#协同的方法 转换为可以在lua协同中调用的方法 yield_return需要在lua协同中执行
    local yield_return = util.async_to_sync(async_yield_return)

    local function coroutine_callback()
        print("lua coroutine over! callback done!")
    end

    local function co_function()
        print("lua coroutine start")
        local wt = CS.UnityEngine.WaitForSeconds(3)
        yield_return(wt, coroutine_callback)
    end

    -- local co = coroutine.create(co_function)

    function Start()
        -- coroutine.resume(co)
        util.coroutine_call(co_function)()
    end














    --[===[  lua coroutine 语法

    --[[ 协同案例1 (基本语法)

    fun1 = function()
        print("hello")
    end

    -- 创建一个协同程序 co
    co = coroutine.create(fun1)

    -- 协同程序的4种状态 suspended、running、dead、normal
    -- 创建完协同程序以后,处于suspended状态
    print("status : ", coroutine.status(co))    

    -- 启动协同程序(第一次唤醒)
    coroutine.resume(co)
    -- 协同程序运行完以后,处于dead状态,再次执行没效果
    print("status : ", coroutine.status(co))

    -- 再次唤醒已经dead的协同程序,无反应,说明不会再次执行了
    coroutine.resume(co)
    print("status : ", coroutine.status(co))

    -- 协同程序处理dead状态,再次唤醒,返回false及一条错误信息
    print(coroutine.resume(co))

    ]]


    --[[ 协同案例2 (yield方法)

    -- 协同的强大之处 coroutine.yield()
    -- 方法中有yield语句
    -- 作用:让一个运行中的程序挂起,而之后可以恢复它的运行

    co = coroutine.create(function() 
            print("start coroutine function")
            for i=1, 3 do
                print("co :", i)
                coroutine.yield()
            end
         end)

    -- 处于suspended状态
    print(coroutine.status(co))

    -- 第一次唤醒,运行到yield方法时返回,挂起发生在yield调用中
    coroutine.resume(co)  -- 打印1
    print("1", coroutine.status(co))

    -- 第二次唤醒,从上一次的yield的调用中返回,继续执行,碰到yield再挂起
    coroutine.resume(co)  -- 打印2
    print("2", coroutine.status(co))

    -- 第三次唤醒
    coroutine.resume(co)  -- 打印3
    print("3", coroutine.status(co))

    print("3-4", coroutine.status(co))  -- suspended状态

    -- 第四次唤醒
    coroutine.resume(co)  -- 什么都不打印
    print("4", coroutine.status(co))

    --]]




    -- 当一个协同程序A唤醒一个协同程序B时,协同程序A就处于一个特殊状态,
    -- 既不是挂起状态(无法继续A的执行),也不是运行状态(是B在运行)。
    -- 所以将这时的状态称为“正常”状态。

    -- Lua的协同程序还具有一项有用的机制,就是可以通过一对resume-yield来交换数据。




    --[[ 协同案例3 (带参数协同)

    -- 创建一个带参数的协同程序
    co = coroutine.create(function(a, b)
            for i=1,3 do
                print("co", a, b, i)
                coroutine.yield()
            end

         end)

    -- 第一次唤醒 参数1,2传给function
    coroutine.resume(co, 10, 20)   -- 缺少参数使用nil,多余的参数舍弃

    -- 第二次唤醒
    coroutine.resume(co, 100, 200) -- 传入100,200无效,有其他用途

    --]]


    --[[ 协同案例4 (resume的返回值)

    co = coroutine.create(function(a, b) 
            coroutine.yield(a + b, a - b)
            return 6, 7
         end)

    -- 第一次唤醒
    -- 在resume的返回值中,第一个返回值为true表示没有错误
    -- 第2个返回值以及之后的,都对应yield传入的参数
    print(coroutine.resume(co, 10, 3))  -- true  13  7
    -- 当一个协同程序结束时,它的所有返回值都作为resume的返回值。
    print(coroutine.resume(co))         -- true  6   7
    --]]


    --[[ 协同案例5 yield的返回值

    co = coroutine.create(function()
            print("co", coroutine.yield("yield"))
         end)

    -- 第一次唤醒,传入的参数“a”是传给方法的,由于方法没有参数,所以舍弃“a”
    print("1", coroutine.resume(co, "a"))   -- "1"  true  yield

    -- 第二次唤醒,传入的参数1,2,作为yield的额外返回值使用(yield返回的额外值就是对应resume传入的参数)
    print("2", coroutine.resume(co, 1, 2))  -- "co"  1  2  -- "2"  true

    print("3", coroutine.resume(co, 100, 200)) -- "3"  false  cannot resume dead coroutine
    --]]


    --[[ *协同案例6* 协同程序的嵌套使用(管道与过滤器)

    -- 唤醒传入的迭代器
    function receive(prod)
        local status, value = coroutine.resume(prod);
        return value;
    end

    funcition send(x)
        coroutine.yield(x)
    end

    -- 返回一个挂起的协同程序 协同程序中需要有yield
    function producer()
        return coroutine.create(function()
            while true do
                local x = io.read
                send(x)                 -- 产生新值
            end
        end)
    end

    function filter(prod)
        return coroutine.create(function() 
            for line = 1, math.huge do
                local x = receive(prod) -- 接收producer产生的值
                x = string.format("%5d %s", line, x)
                send(x)                 -- 把新值发送给消费者
            end
        end)
    end

    function consumer(prod)
        while true do
            local x = receive(prod)     -- 获取新值
            io.write(x, "\n")           -- 消费新值
        end
    end

    -- 运行代码
    consumer(filter(producer))

    --]]

    ]===]

LuaCoroutine.cs

    /*
     *  created by shenjun
     */

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

    namespace shenjun
    {
        [LuaCallCSharp]
        public class Coroutine : MonoBehaviour {

            LuaEnv luaEnv = new LuaEnv();

            void Start () {
                luaEnv.DoString("require 'LuaCoroutine'");
                System.Action luaStart = luaEnv.Global.Get<System.Action>("Start");

                if (null != luaStart)
                    luaStart();
            }

            void Update () {

            }

            private void OnDestroy()
            {
                luaEnv.Dispose();
            }

            public void InvokeSpawn(object yield_return, System.Action callback)
            {
                StartCoroutine(SpawnObj(yield_return, callback));
            }

            IEnumerator SpawnObj(object yield_return, System.Action callback)
            {
                for (int i = 0; i < 10; i++)
                {
                    GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    go.transform.position = Random.insideUnitSphere * 5;
                    if(yield_return is IEnumerator)
                    {
                        yield return StartCoroutine(yield_return as IEnumerator);
                    }
                    else
                    {
                        yield return yield_return;
                    }
                }
                callback();
            }
        }

        [LuaCallCSharp]
        public static class CoroutineConfig
        {
            public static List<System.Type> LuaCallCSharp
            {
                get{
                    return new List<System.Type>() 
                    { 
                        typeof(WaitForSeconds)
                    };
                }
            }
        }
    }

🔚

results matching ""

    No results matching ""