uLua热更新知识

一、使用UGUI SimpleFramework来使用uLua

首先,上https://github.com/jarjin/SimpleFramework_UGUI/下载它,它是一个工程文件,里面包含了许多uLua需要用的东西,Editor、Lua、Script、Source文件都十分的重要,确保它们的存在,我们就能正常使用该框架。

注意:Unity 2017系列不可以用该框架,必须要用Unity5.0左右的版本。

二、基本使用方法(围绕自带的案例进行说明)

前提工作:

    在Unity打开上面我们下载的工程后,会看到菜单栏上多了2个菜单,Lua和Game,接下来我们会用这2个菜单去布置我们Lua框架的环境。

    1.点击Lua->Gen Lua Wrap Files  ,做完这一步后会在uLua文件夹的Source文件夹生成一个LuaWarp文件夹,它存放了很多脚本,都是用于预先注册Unity封装的类进入Lua环境的,与luanet.import_type()方法和LuaScriptMgr有关。

   2.点击Game->Build Window Resources,做完这一步后会在工程下生成一个StreamingAssets文件夹,它包含了AssetBundles资源和lua文件,这个StreamingAssets文件夹是非常关键的,因为我们会用到它来处理热更新,我们写的lua文件都要放在这个文件夹里面。

    然后,我们点击Examples文件夹里面的Scenes文件夹的login场景,进入login场景,进行运行,这一步必须要做,因为login场景会对工程的一些文件进行操作的,这样我们才可以运行其他自带案例。

    如果,不出意料,运行成功,会出现一个UI。

案例分析:

1、uLua->Examples->HelloWorld案例:(下面uLua->Examples->省略)

    

using UnityEngine;
using System.Collections;
using LuaInterface;

public class HelloWorld : MonoBehaviour {

	// Use this for initialization
	void Start () {
        LuaState l = new LuaState();
        string str = "print('hello world 世界')";
        l.DoString(str);
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

在HelloWorld案例里面,我们可以看到有一个物体挂载了HelloWorld脚本(上面),在Start方法中创建了一个LuaState对象,该对象是类似于我们的luainterface.dll的Lua类,它就是在Lua类的再一层封装成为了LuaState类。


2、CreateGameObject01案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class CreateGameObject01 : MonoBehaviour {
    
    private string script = @"
            luanet.load_assembly('UnityEngine')
            GameObject = luanet.import_type('UnityEngine.GameObject')        
	        ParticleSystem = luanet.import_type('UnityEngine.ParticleSystem')         
   
            local newGameObj = GameObject('NewObj')
            newGameObj:AddComponent(luanet.ctype(ParticleSystem))
        ";

	//反射调用
	void Start () {
        LuaState lua = new LuaState();
        lua.DoString(script);
	}
	
}

该案例和上面一样,一个物体挂着CreateGameObject01脚本,可发现script里的字符串就是lua代码,为什么在前面没有require 'luanet',却可以直接用luanet的方法?是因为这个框架的作用!即LuaState已经封装好了luanet,直接调用也OK了。其他也没什么好说的,导入UnityEngine的dll,然后加载UnityEngine.GameObject类和ParticleSystem类,使用它们创建一个物体,名叫NewObj,在该物体上调用AddComponent方法加上一个ParticleSystem组件。注意 参数不是直接写ParticleSystem那么简单,而是luanet.ctype(ParticleSystem).


3、CreateGameObject02案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class CreateGameObject02 : MonoBehaviour {

    private string script = @"
            luanet.load_assembly('UnityEngine')
            GameObject = UnityEngine.GameObject
            ParticleSystem = UnityEngine.ParticleSystem
            local newGameObj = GameObject('NewObj')
            newGameObj:AddComponent(ParticleSystem.GetClassType())
        ";

	//非反射调用
	void Start () {
        LuaScriptMgr lua = new LuaScriptMgr();
        lua.Start();
        lua.DoString(script);
	}
	
}

可以发现这个案例与上面案例相差无几,只不过把LuaState换成了LuaScriptMgr类,这个类就是我上面所说的与Wrap文件有关的类,使用这个类的DoString()之前必须使用Start进行一些初始化操作。那么与LuaState区别的哪呢?

区别:使用LuaScriptMgr来执行的lua代码中,如果有需要加载类,无须用luanet.import_type()来导入了。直接在导入了UnityEngine的dll后,使用(UnityEngine.)的形式来导入里面的类,像案例那样UnityEngline.GameObject就可以了,而且添加组件的参数也可以不用luanet.ctype(xxx)了,直接用xxx.GetClassType()来。

说明:LuaState是在LuaInterface下的类,它在uLua文件夹的Core文件夹的Lua脚本中;LuaScriptMgr是在LuaState的再一封装,对LuaState进行管理的,它放在uLua->Source->Base文件夹下。


4、AccessingLuaVariables_01案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class AccessingLuaVariables01 : MonoBehaviour {

    private string script = @"
            luanet.load_assembly('UnityEngine')
            GameObject = luanet.import_type('UnityEngine.GameObject')
            ParticleSystem = luanet.import_type('UnityEngine.ParticleSystem')

            particles = {} --定义一个表
            -- Objs2Spawn是C#定义的lua变量,值是5
            for i = 1, Objs2Spawn, 1 do
                local newGameObj = GameObject('NewObj' .. tostring(i))
                local ps = newGameObj:AddComponent(luanet.ctype(ParticleSystem))
                --local ps = newGameObj:AddComponent('ParticleSystem') PS:Unity5.x已经废弃这种方式,Unity4.x可用--
                ps:Stop() --粒子播放停止

                table.insert(particles, ps) --粒子组件放入表
            end

            var2read = 42 --定义一个变量
        ";

	// Use this for initialization
	void Start () {
        LuaState l = new LuaState();
        // Assign to global scope variables as if they're keys in a dictionary (they are really)
        l["Objs2Spawn"] = 5; //首先C#这边给lua环境定义一个变量
        l.DoString(script);

        // Read from the global scope the same way
        print("Read from lua: " + l["var2read"].ToString());// 访问lua的var2read变量即42

        // Get the lua table as LuaTable object
        LuaTable particles = (LuaTable)l["particles"]; //获取lua的particles表 ,放入LuaTable类型变量

        // Typical foreach over values in table
        foreach( ParticleSystem ps in particles.Values ) //遍历表的值
        {
            ps.Play();//播放
        }
	}
	
}

5、AccessingLuaVariables_02案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class AccessingLuaVariables02 : MonoBehaviour 
{
    //cstolua要求必须要先定义变量才能使用
    private string var = @"Objs2Spawn = 0";
    private string script = @"      
            luanet.load_assembly('UnityEngine') --这句代码其实可以省去,在不同版本的uLua框架有些许不同吧.
            ParticleSystem = UnityEngine.ParticleSystem --因为用的是LuaScriptMgr故获取方式,直接这样也可以.
            particles = {}

            for i = 1, Objs2Spawn, 1 do
                local newGameObj = GameObject('NewObj' .. tostring(i))
                local ps = newGameObj:AddComponent(ParticleSystem.GetClassType())
                ps:Stop()

                table.insert(particles, ps)
            end

            var2read = 42
        ";

	// Use this for initialization
	void Start () {        
        LuaScriptMgr mgr = new LuaScriptMgr();
        mgr.Start();
        // Assign to global scope variables as if they're keys in a dictionary (they are really)
        LuaState l = mgr.lua; //获取mgr的LuaState脚本
        l.DoString(var);   //类似于l["Objs2Spawn"]=0,定义变量Objs2Spawn
        l["Objs2Spawn"] = 5;  //修改为5
        l.DoString(script);  

        // Read from the global scope the same way
        print("Read from lua: " + l["var2read"].ToString());

        // Get the lua table as LuaTable object
        LuaTable particles = (LuaTable)l["particles"];

        // Typical foreach over values in table
        foreach( ParticleSystem ps in particles.Values )
        {
            ps.Play();
        }
	}
	
}

6、ScriptsFromFile_01案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class ScriptsFromFile_01 : MonoBehaviour
{

    public TextAsset scriptFile; //TextAsset是文本类型

    void Start()
    {
        LuaState l = new LuaState();
        l.DoString(scriptFile.text); //执行外部传递的文本 ,该文本就写了一句print()
    }
}

7、ScriptsFromFile_02案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class ScriptsFromFile_02 : MonoBehaviour
{  
    void Start()
    {
        //只是展示如何加载文件。不是推荐这么做
        LuaState l = new LuaState();
        string path = Application.dataPath + "/uLua/Examples/04_ScriptsFromFile/ScriptsFromFile02.lua";
        l.DoFile(path); //使用DoFile来执行文件的lua代码
    }
}

 Application.dataPath是工程的Assets目录。

8、CallLuaFunction_01案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class CallLuaFunction_01 : MonoBehaviour {

    private string script = @"
            function luaFunc(message)
                print(message)
                return 42
            end
        ";

	// Use this for initialization
	void Start () {
        LuaState l = new LuaState();

        // First run the script so the function is created
        l.DoString(script);

        // Get the function object
        LuaFunction f = l.GetFunction("luaFunc");//上面的不解释了,应该都会,这里LuaFunction是获取luaFunc这个lua方法

        // Call it, takes a variable number of object parameters and attempts to interpet them appropriately
        object[] r = f.Call("I called a lua function!");//执行f方法的方式是f.Call(参数),用object[]接收返回值

        // Lua functions can have variable returns, so we again store those as a C# object array, and in this case print the first one
        print(r[0]); --输出第一个值,因为lua的luaFunc方法只有一个返回值42
	}
	
}

9、CallLuaFunction_02案例(暂且看不懂)

using UnityEngine;
using System.Collections;
using LuaInterface;
using System;

public class CallLuaFunction_02 : MonoBehaviour {

    private string script = @"
            function luaFunc(num)                
                return num
            end
        ";

    LuaFunction func = null;

	// Use this for initialization
	void Start () {
        LuaScriptMgr mgr = new LuaScriptMgr();
        
        mgr.DoString(script);

        // Get the function object
        func = mgr.GetLuaFunction("luaFunc");

        //有gc alloc
        object[] r = func.Call(123456);        
        print(r[0]);

        // no gc alloc
        int num = CallFunc();
        print(num);
	}

    void OnDestroy()
    {
        if (func != null)
        {
            func.Release();
        }
    }

    int CallFunc() //无法理解下面
    {
        int top = func.BeginPCall();
        IntPtr L = func.GetLuaState();
        LuaScriptMgr.Push(L, 123456);
        func.PCall(top, 1);
        int num = (int)LuaScriptMgr.GetNumber(L, -1);
        func.EndPCall(top);
        return num;
    }

}

10、06_LuaCoroutines案例:

using UnityEngine;
using System.Collections;
using LuaInterface;

public class LuaCoroutines : MonoBehaviour 
{
    private string script = @"                                   
            function fib(n)
                local a, b = 0, 1
                while n > 0 do
                    a, b = b, a + b
                    n = n - 1
                end

                return a
            end

            function CoFunc()
                print('Coroutine started')
                local i = 0
                for i = 0, 10, 1 do
                    print(fib(i))      --输出前i个数的斐波数列之和           
                    coroutine.wait(1)  --相当于yield return new WaitForSeconds(1)
                end
                print('Coroutine ended')
            end

            function myFunc()
                coroutine.start(CoFunc) --相当于StartCoroutine()方法
            end
        ";

    private LuaScriptMgr lua = null;

	void Awake () 
    {
        lua  = new LuaScriptMgr();
        lua.Start();
        lua.DoString(script);        
        LuaFunction f = lua.GetLuaFunction("myFunc");
        f.Call();
        f.Release();
	}
	
	//Lua环境模拟Unity的更新,这样做是为了让协程有计时的效果,这lua.Update、LateUpdate、FixedUpdate都是已经封装好的方法
	void Update ()    
        {        
        lua.Update();
	}

    void LateUpdate()
    {
        lua.LateUpate();
    }

    void FixedUpdate()
    {
        lua.FixedUpdate();
    }
}
 其他案例不说明了,自己看看就OK了




猜你喜欢

转载自blog.csdn.net/qq_39574690/article/details/80773837
今日推荐