• Unity3D开发入门教程(四)——用Lua实现组件


    五邑隐侠,本名关健昌,12年游戏生涯。 本教程以 Unity 3D + VS Code + C# + tolua 为例。

    一、Lua组件基类

    1、在 Assets/Lua 目录下新建com目录用于存放Lua组件

    2、在Assets/Lua/com 目录新建Component.lua文件,添加Lua组件基类Component,实现Unity3D组件的生命周期

    Assets/Lua/com/Component.lua

     1 ---@class Component @Component class
     2 local Component = {}
     3 
     4 --- Awake
     5 function Component:Awake()
     6 end
     7 
     8 --- OnEnable
     9 function Component:OnEnable()
    10 end
    11 
    12 --- Start
    13 function Component:Start()
    14 end
    15 
    16 --- Update
    17 function Component:Update()
    18 end
    19 
    20 --- FixedUpdate
    21 function Component:FixedUpdate()
    22 end
    23 
    24 --- LateUpdate
    25 function Component:LateUpdate()
    26 end
    27 
    28 --- OnGUI
    29 function Component:OnGUI()
    30 end
    31 
    32 --- OnDisable
    33 function Component:OnDisable()
    34 end
    35 
    36 --- OnDestroy
    37 function Component:OnDestroy()
    38 end
    39 
    40 --- ExtendComponent
    41 ---@return Component
    42 function ExtendComponent()
    43     return CreateComponent(Component)
    44 end
    45 
    46 --- CreateComponent
    47 ---@param componentClass Component
    48 ---@return Component
    49 function CreateComponent(componentClass)
    50     local o = {}
    51     
    52     for k, v in pairs(componentClass) do
    53         o[k] = v
    54     end
    55 
    56     return o
    57 end
    58 
    59 local com = {
    60     ExtendComponent = ExtendComponent,
    61     CreateComponent = CreateComponent,
    62 }
    63 
    64 return com
    
    

    3、基类 Component 只是实现了空的生命周期方法,子类只需要实现所需的生命周期方法,子类没有实现的生命周期方法会有默认的空实现。

    4、由于通过C#调用Lua的方法时,以元表方式继承的方法会报空。这里通过拷贝key方式继承基类,调用com.ExtendComponent()方法返回一个继承Component的子类table。

    5、子类通过 com.CreateComponent 方法创建对象。

    6、下面给出一个简单的样例组件 TestComponent

    Assets/Lua/com/TestComponent.lua
     1 local com = require("Assets.Lua.com.Component")
     2 
     3 ---@class TestComponent @TestComponent class
     4 TestComponent = com.ExtendComponent()
     5 
     6 function TestComponent.new(paramList)
     7     local o = com.CreateComponent(TestComponent)
     8 
     9     -- member fields
    10     o.num = paramList[0] -- Array by C#, index begin from 0
    11     return o
    12 end
    13 
    14 function TestComponent:Awake()
    15     print(self.num)
    16     print("TestComponent:Awake")
    17 end
    18 
    19 function TestComponent:Start()
    20     print("TestComponent:Start")
    21 end
    22 
    23 function TestComponent:OnDestroy()
    24     print("TestComponent:OnDestroy")
    25 end

    注意:

    1) 这里 TestComponent 是全局的变量,因为C#直接访问的是全局变量,局部变量无法直接访问。

    2)C#传过来的数组参数 paramList,下标从0开始

    二、通用C#组件脚本

     1 using UnityEngine;
     2 using LuaInterface;
     3 
     4 public class LuaComponent : MonoBehaviour
     5 {
     6     public string luaClassName = "";
     7     public string[] paramList = null;
     8 
     9     private LuaState luaState = null;
    10     private LuaTable luaObj = null;
    11 
    12     void Awake()
    13     {
    14         LuaClient luaClient = LuaClient.Instance;
    15         this.luaState = luaClient.GetLooper().luaState;
    16         this.luaState.DoFile(this.luaClassName + ".lua");
    17         this.luaObj = callLuaNew();
    18 
    19         callLuaFunc("Awake");
    20     }
    21 
    22     void OnEnable()
    23     {
    24         callLuaFunc("OnEnable");
    25     }
    26 
    27     // Start is called before the first frame update
    28     void Start()
    29     {
    30         callLuaFunc("Start");
    31     }
    32 
    33     // Update is called once per frame
    34     void Update()
    35     {
    36         callLuaFunc("Update");
    37     }
    38 
    39     void FixedUpdate()
    40     {
    41         callLuaFunc("FixedUpdate");
    42     }
    43 
    44     void LateUpdate()
    45     {
    46         callLuaFunc("LateUpdate");
    47     }
    48 
    49     void OnGUI()
    50     {
    51         callLuaFunc("OnGUI");
    52     }
    53 
    54     void OnDisable()
    55     {
    56         if (LuaClient.Instance != null)
    57         {
    58             callLuaFunc("OnDisable");
    59         }
    60     }
    61 
    62     void OnDestroy()
    63     {
    64         if (LuaClient.Instance != null)
    65         {
    66             callLuaFunc("OnDestroy");
    67         }
    68 
    69         this.luaState = null;
    70         this.luaObj = null;
    71     }
    72 
    73     public LuaTable callLuaNew()
    74     {
    75         LuaFunction luaFunc = luaState.GetFunction(this.luaClassName + "." + "new");
    76         luaFunc.BeginPCall();
    77         luaFunc.Push(this.paramList);
    78         luaFunc.PCall();
    79         LuaTable table = luaFunc.CheckLuaTable();
    80         luaFunc.EndPCall();
    81         luaFunc.Dispose();
    82         luaFunc = null;
    83         return table;
    84     }
    85 
    86     private void callLuaFunc(string funcName)
    87     {
    88         LuaFunction luaFunc = luaState.GetFunction(this.luaClassName + "." + funcName);
    89         luaFunc.BeginPCall();
    90         luaFunc.Push(this.luaObj);
    91         luaFunc.PCall();
    92         luaFunc.EndPCall();
    93         luaFunc.Dispose();
    94         luaFunc = null;
    95     }
    96 }

    1、这个组件给 Unity3D暴露两个字段:luaClassName、paramList。可以在Unity3D中设置Lua类名、初始化参数列表(参数个数可在Unity3D调整)

    2、在 Awake 生命周期加载跟 luaClassName 同名的 .lua 文件,调用 Lua的 luaClassName 类的 new 方法,把 paramList 当作参数传过去,得到 Lua对象。

    3、其他生命周期方法都是调用 Lua 类的同名方法,从而可以在 Lua 实现具体的生命周期逻辑。

    三、添加 Lua 组件搜索路径

    为了让 Lua虚拟机知道组件的路径,在Main.cs重写父类的 Awake 生命周期方法,添加搜索路径 Lua/com

    Assets/CSharp/Main.cs

    1 new void Awake()
    2 {
    3     base.Awake();
    4 
    5     // search path
    6     string fullPath = Application.dataPath + "/Lua/com";
    7     luaState.AddSearchPath(fullPath);
    8 }

    四、测试效果

    1、在GameObject菜单,选择Create Empty,添加一个空GameObject

    2、在属性面板给这个空GameObject添加Lua Component组件,设置 Lua Class Name 为 TestComponent,下标0的参数为 12

    3、运行效果日志

  • 相关阅读:
    《数字图像处理原理与实践(MATLAB版)》一书之代码Part5
    编程算法
    SVM 输出分类概率(python)
    mysql 数据库通过拷贝文件恢复方法
    ubuntu取消自动登录
    迁移mysql数据位置
    No module named 'lsb_release'
    python3 ssl导入失败
    Linux tar: Cannot change ownership to [..]: Permission denied
    树莓派蓝牙
  • 原文地址:https://www.cnblogs.com/niudanshui/p/15797735.html
Copyright © 2020-2023  润新知