Tolua使用笔记六:在lua中操作C#的委托事件与在lua中对Unity的GameObject的操作

原文地址:http://blog.csdn.net/qq_30168505/article/details/70555511

案例十一:

该案例主要讲解的是再Unity中对于C#中的委托的一些操作的方法

相比之前的一些例子,如果细心完整的看下来,会发现较开始的例子,这个例子算是比较复杂的了

核心代码就不贴了,太长了,如果没有经验,直接看这个例子,可能你已经晕在这里了,现在我就开始为大家细细的解析这样一篇代码

先从类TestEventListener开始说起,这是一个例子作者自己封装的一个类,里面包含了2种类型的委托和一些委托事件的变量和一些基础的方法

public class TestEventListener : MonoBehaviour
{
    public delegate void VoidDelegate(GameObject go);
    public delegate void OnClick(GameObject go);    
    public OnClick onClick = delegate { };

    public event OnClick onClickEvent = delegate { };    

    public void SetOnFinished(OnClick click)
    {
        Debugger.Log("SetOnFinished OnClick");
    }

    public void SetOnFinished(VoidDelegate click)
    {
        Debugger.Log("SetOnFinished VoidDelegate");
    }

    [NoToLuaAttribute]
    public void OnClickEvent(GameObject go)
    {
        onClickEvent(go);
    }
}
这里大家先留下一个概念,后面会用到这个类,然后大家回到脚本TestDelegate这边来,这便是这个例子的入口类

按照惯例,作者一如既往的在Awake里面就几乎做完了所有的基本加载操作,我们都的时候也都是从这里开始:

    void Awake()
    {               
        state = new LuaState();
        state.Start();
        LuaBinder.Bind(state);   //加载基本的Warp文件
        Bind(state);

        state.LogGC = true;
        state.DoString(script);
        GameObject go = new GameObject("TestGo");
        listener = (TestEventListener)go.AddComponent(typeof(TestEventListener));

        SetClick1 = state.GetFunction("SetClick1");
        AddClick1 = state.GetFunction("AddClick1");
        AddClick2 = state.GetFunction("AddClick2");
        RemoveClick1 = state.GetFunction("RemoveClick1");
        RemoveClick2 = state.GetFunction("RemoveClick2");
        TestOverride = state.GetFunction("TestOverride");
        AddEvent = state.GetFunction("AddEvent");
        RemoveEvent = state.GetFunction("RemoveEvent");        
    }
首先自然是创建lua虚拟机,然后调用 state.Start() 为虚拟机加载一些标准库。

然后则是使用LuaBinder.Bind(LuaState  state) 为该虚拟机中加载一些基本的class类型,就是之前在CustomSetting中添加并Warp的类型

之后的Bind()函数则是为lua虚拟机加载一些该例子特有的类型,平时我们完全可以不通过该方法添加,直接在CustomSetting中添加即可。

然后就是编译读取下面的lua脚本

            function DoClick1(go)                
                print('click1 gameObject is '..go.name)                    
            end

            function DoClick2(go)                
                print('click2 gameObject is '..go.name)                              
            end                       

            function AddClick1(listener)       --添加点击事件DoClick1
                if listener.onClick then
                    listener.onClick = listener.onClick + DoClick1                                                    
                else
                    listener.onClick = DoClick1    
                end                
            end

            function AddClick2(listener)       --添加点击事件DoClick2
                if listener.onClick then
                    listener.onClick = listener.onClick + DoClick2                      
                else
                    listener.onClick = DoClick2
                end                
            end

            function SetClick1(listener)       --设置点击事件
                if listener.onClick then
                    listener.onClick:Destroy()
                end

                listener.onClick = DoClick1         
            end

            function RemoveClick1(listener)    --移除点击事件DoClick1
                if listener.onClick then
                    listener.onClick = listener.onClick - DoClick1      
                else
                    print('empty delegate')
                end
            end

            function RemoveClick2(listener)    --移除点击事件DoClick2
                if listener.onClick then
                    listener.onClick = listener.onClick - DoClick2    
                else
                    print('empty delegate')                                
                end
            end

            --测试重载问题
            function TestOverride(listener)
                listener:SetOnFinished(TestEventListener.OnClick(DoClick1))
                listener:SetOnFinished(TestEventListener.VoidDelegate(DoClick2))
            end

            function TestEvent()     --测试事件
                print('this is a event')
            end

            function AddEvent(listener)    --添加事件
                listener.onClickEvent = listener.onClickEvent + TestEvent
            end

            function RemoveEvent(listener)   --移除事件
                listener.onClickEvent = listener.onClickEvent - TestEvent
            end
然后创建了一个游戏物体,并为其绑定了一个最开始说到的那个TestEventListener组件;

在之后就是用Tolua#提供的luaFunction将之前读取脚本中的lua方法取出。。。。方法的含义我已经在旁边给出了注释

接下来就看看OnGUI中的代码,看看这里是如何调用这些方法的

 //UI面板绘制方法
    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 120, 40), " = OnClick1"))
        {
            CallLuaFunction(SetClick1);
        }
        else if (GUI.Button(new Rect(10, 60, 120, 40), " + Click1"))
        {
            CallLuaFunction(AddClick1);
        }
        else if (GUI.Button(new Rect(10, 110, 120, 40), " + Click2"))
        {
            CallLuaFunction(AddClick2);
        }
        else if (GUI.Button(new Rect(10, 160, 120, 40), " - Click1"))
        {
            CallLuaFunction(RemoveClick1);
        }
        else if (GUI.Button(new Rect(10, 210, 120, 40), " - Click2"))
        {
            CallLuaFunction(RemoveClick2);
        }
        else if (GUI.Button(new Rect(10, 260, 120, 40), "+ Click1 in C#"))
        {
            LuaFunction func = state.GetFunction("DoClick1");
            TestEventListener.OnClick onClick = (TestEventListener.OnClick)DelegateFactory.CreateDelegate(typeof(TestEventListener.OnClick), func);
            listener.onClick += onClick;
        }        
        else if (GUI.Button(new Rect(10, 310, 120, 40), " - Click1 in C#"))
        {
            LuaFunction func = state.GetFunction("DoClick1");
            listener.onClick = (TestEventListener.OnClick)DelegateFactory.RemoveDelegate(listener.onClick, func);
            func.Dispose();
            func = null;
        }
        else if (GUI.Button(new Rect(10, 360, 120, 40), "OnClick"))
        {
            if (listener.onClick != null)
            {
                listener.onClick(gameObject);
            }
            else
            {
                Debug.Log("empty delegate!!");
            }
        }
        else if (GUI.Button(new Rect(10, 410, 120, 40), "Override"))
        {
            CallLuaFunction(TestOverride);
        }
        else if (GUI.Button(new Rect(10, 460, 120, 40), "Force GC"))
        {
            //自动gc log: collect lua reference name , id xxx in thread 
            state.LuaGC(LuaGCOptions.LUA_GCCOLLECT, 0);
            GC.Collect();
        }
        else if (GUI.Button(new Rect(10, 510, 120, 40), "event +"))
        {
            CallLuaFunction(AddEvent);
        }
        else if (GUI.Button(new Rect(10, 560, 120, 40), "event -"))
        {
            CallLuaFunction(RemoveEvent);
        }
        else if (GUI.Button(new Rect(10, 610, 120, 40), "event call"))
        {
            listener.OnClickEvent(gameObject);
        }
    }
这里涉及到该例子中的一个方法CallLuaFunction()

void CallLuaFunction(LuaFunction func)
    {        
        func.BeginPCall();
        func.Push(listener);
        func.PCall();
        func.EndPCall();                
    }
其实就是对luaFunction的调用的一种封装,使得其默认总是以之前的那个TestEventListener组件为参数来调用LuaFunction

·有了这些之后,我们就可以来很轻松的这些按钮的作用了!!!

首先是按钮” = OnClick1” ,该放啊对应的代码其实就是直接以TestEventListener组件为参数来调用lua的方法 SetClick1(listener)

该lua方法的代码如下:

            function SetClick1(listener)       --设置点击事件
                if listener.onClick then
                    listener.onClick:Destroy()
                end

                listener.onClick = DoClick1         
            end
1:在这段代码中我们可以看到 C#中的委托可以直接使用 if 语句判空 ,并且可以使用 Delegate:Destory()来销毁该委托

2:对于C#中的委托的赋值可以直接使用 lua中的方法以赋值运算符赋值 例如 : listener.onClick = DoClick1


然后是按钮 ” + Click1” 和 按钮 ” + Click2 ” 这里讲解了如何为委托绑定额外的方法,相当于C#中的对于委托的+=操作

该部分lua方法的代码如下:

           function AddClick1(listener)       --添加点击事件DoClick1
                if listener.onClick then
                    listener.onClick = listener.onClick + DoClick1                                                    
                else
                    listener.onClick = DoClick1    
                end                
            end

            function AddClick2(listener)       --添加点击事件DoClick2
                if listener.onClick then
                    listener.onClick = listener.onClick + DoClick2                      
                else
                    listener.onClick = DoClick2
                end                
            end
由于lua中不支持+=运算符,所以,在这里采用了后面的写法替代: Delegate = Delegate + 方法


相对应的有绑定也自然有取消绑定功能,体现该功能的按钮是分别是 ” - Click1” 和 ” - Click2 ” ,

lua代码如下:

            function RemoveClick1(listener)    --移除点击事件DoClick1
                if listener.onClick then
                    listener.onClick = listener.onClick - DoClick1      
                else
                    print('empty delegate')
                end
            end

            function RemoveClick2(listener)    --移除点击事件DoClick2
                if listener.onClick then
                    listener.onClick = listener.onClick - DoClick2    
                else
                    print('empty delegate')                                
                end
            end
同样的,lua之中也不支持-=运算符,所以使用这样的写法 : Delegate = Delegate - 方法

按钮”OnClick” 就不用看了哈 ,就是最基本的C#的委托调用

然后是 按钮 “Override” ,该按钮主要是为了向大家证实在lua中重载函数的正常使用

Tolua#是完全兼容重载函数的,同时还向大家展示了在lua中创建委托的写法

直接 委托类型(参数列表) 即可在lua中创建一个新的委托变量~~~,是不是很方便

对应的代码如下:

function TestOverride(listener)
                listener:SetOnFinished(TestEventListener.OnClick(DoClick1))
                listener:SetOnFinished(TestEventListener.VoidDelegate(DoClick2))
            end

剩下的按钮 ” + Click in C# ” 和 ” - Click in C#” 则是展示了如何在C#中删除绑定的lua方法

        if (GUI.Button(new Rect(10, 260, 120, 40), "+ Click1 in C#"))
        {
            LuaFunction func = state.GetFunction("DoClick1");
            TestEventListener.OnClick onClick = (TestEventListener.OnClick)DelegateFactory.CreateDelegate(typeof(TestEventListener.OnClick), func);
            listener.onClick += onClick;
        }        
        else if (GUI.Button(new Rect(10, 310, 120, 40), " - Click1 in C#"))
        {
            LuaFunction func = state.GetFunction("DoClick1");
            listener.onClick = (TestEventListener.OnClick)DelegateFactory.RemoveDelegate(listener.onClick, func);
            func.Dispose();
            func = null;
        }
其实就是将lua方法取出到C#中,然后转成LuaFunction ,然后直接使用
DelegateFactory.CreateDelegate 和 DelegateFactory.RemoveDelegate
进行添加和删除,顺便友情提示, LuaFunction使用法之后要记得手动释放哟,否则会有GC

最后是对于在lua中操作C#的事件,其操作手法和委托极其相似,大家其实看一看就可以学会了,,基本上就是这些了

最后这个例子中需要用到的委托类型也都是要单独导出Warp的,操作手法其实就是将需要的委托类型添加到CustomSetting.cscustomDelegateList

样例写法如下:

    public static DelegateType[] customDelegateList =
    {        
        _DT(typeof(Action)),
        //_DT(typeof(Action)).SetAbrName("ActionGo"),
        _DT(typeof(UnityEngine.Events.UnityAction)),      

        _DT(typeof(TestEventListener.OnClick)),
        _DT(typeof(TestEventListener.VoidDelegate)),
    }; 

效果截图比较长且和操作顺序有关,这一部分就不截图了嘎嘎嘎


案例12

这个例子相比之前的那个,看起来就舒服多了

核心代码如下:

    private string script =
        @"                                    
            local GameObject = UnityEngine.GameObject          
            local ParticleSystem = UnityEngine.ParticleSystem            

            local go = GameObject('go')
            go:AddComponent(typeof(ParticleSystem))
            local node = go.transform
            node.position = Vector3.one      
            print('gameObject is: '..tostring(go))    
            GameObject.Destroy(go, 2)                        
        ";

    LuaState lua = null;

    void Start()
    {        
        lua = new LuaState();
        lua.LogGC = true;
        lua.Start();
        LuaBinder.Bind(lua);
        lua.DoString(script);            
    }
主要的方法就是

GameObject:AddComponent(typeof(Component))  在lua中给游戏物体添加组件

GameObject(“游戏物体名”)  在lua中创建新的游戏物体

GameObject.Destroy(游戏对象, 延迟时间)  延时销毁的指定的游戏物体

非常简单,大家随便看看就好了

效果截图如下:


好了,今天就到这里吧!大家下回再见

你可能感兴趣的:(unity学习,游戏开发相关,Lua学习,tolua学习)