经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
Unity3D开发入门教程(四)——用Lua实现组件
来源:cnblogs  作者:五邑隐侠  时间:2022/1/17 10:46:30  对本文有异议

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

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

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

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

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

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

注意:

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

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

 

二、通用C#组件脚本

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

 

四、测试效果

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

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

3、运行效果日志

 

原文链接:http://www.cnblogs.com/niudanshui/p/15797735.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号