• Unity之热更新:(三)XLua


    1. XLua是什么?

      Xlua是Lua在C#环境(.net)下的Lua解决方案,包括C#环境下的Lua代码解释器(Lua虚拟机)。

    2. 基于XLua的纯Lua开发环境的基本原则? 

    • Unity场景里不放任务物体,通过代码创建和释放物体。这样避免冲突,方便维护(比如程序和美术都往场景里放了同一物体),可以通过搜索代码查看创建了哪些物体以及结构关系。
    • 运行时只有一个场景,没有场景切换。地图、角色、特效、粒子...都被做成资源或预制体给代码使用。(这一步实现美术与程序分离)
    • 不手动往节点上面挂脚本,而是通过代码AddComponent挂载。(方便维护,直接搜索组件名称就能找到哪里挂载了脚本)
    • 纯AssetsBundle来做资源管理,代替Resources。这样方便更新,方便打空包。
    • 制定一个纯Lua的组件化开发框架。方便写业务逻辑,减少Lua与C#相互调用。
    • 调试模式加载Lua代码、资源。AssetDataBase来加载资源。发布模式,打AB包,更新。

    3. 在Unity中使用XLUA

     1)https://github.com/Tencent/xlua 下载xlua

     2)复制Assets文件夹下四个文件到工程Assets文件夹

     

     3)打开宏

     4)任何代码的修改都要执行以下两个步骤才能运行:

      5)下面开始写C#调用Lua的代码

    写一个lua文件,命名后缀 .lua.txt

    注意lua文件要放在C#脚本的同级Resources目录下。

     下面是C#脚本,演示C#脚本里调用lua。

     1 using System.Collections;
     2 using System.Collections.Generic;
     3 using UnityEngine;
     4 using XLua;
     5 
     6 public class textCSharp : MonoBehaviour 
     7 {
     8     LuaEnv env = new LuaEnv();
     9 
    10     private void OnGUI()
    11     {
    12         if (GUILayout.Button("C#调用Lua语句"))
    13             env.DoString("print 'testlua'");
    14 
    15         if (GUILayout.Button("C#调用Lua文件"))
    16             CSharpCallLuaFile();    
    17     }
    18     void CSharpCallLuaFile()
    19     {
    20         env.DoString("require 'luatest'");
    21         //调用lua全局变量
    22         Debug.Log(env.Global.Get<string>("name"));
    23         Debug.Log(env.Global.Get<int>("age"));
    24         //调用lua表中数据
    25         LuaTable table = env.Global.Get<LuaTable>("config");
    26         Debug.Log(table.Get<string>("name"));
    27         Debug.Log(table.Get<string>("age"));
    28     }
    29 }

    也可以直接映射成类

     1 public class textCSharp : MonoBehaviour 
     2 {
     3     LuaEnv env = new LuaEnv();
     4 
     5     private void OnGUI()
     6     {
     7         if (GUILayout.Button("C#调用Lua文件"))
     8             CSharpCallLuaFile();    
     9     }
    10     void CSharpCallLuaFile()
    11     {
    12         env.DoString("require 'luatest'");
    13 
    14         Config config = env.Global.Get<Config>("config");
    15         Debug.Log(config.name);
    16         Debug.Log(config.age);
    17     }
    18     public class Config
    19     {
    20         public string name;
    21         public int age;
    22     }
    23 }
    1 void CSharpCallLuaFile()
    2     {
    3         env.DoString("require 'luatest'");
    4         //调用lua函数并接收返回值
    5         LuaFunction fun = env.Global.Get<LuaFunction>("printInfo");
    6         object[] objs = fun.Call();  //lua函数可以有1个或多个返回值
    7         Debug.Log(objs[0]);
    8     }

    结果是:第一行输出的是Call()里面的内容

    也可以使用委托来调用lua函数

     1 public class textCSharp : MonoBehaviour 
     2 {
     3     LuaEnv env = new LuaEnv();
     4 
     5     delegate int Fun(int num);
     6     private void OnGUI()
     7     {
     8         if (GUILayout.Button("C#调用Lua文件"))
     9             CSharpCallLuaFile();    
    10     }
    11     void CSharpCallLuaFile()
    12     {
    13         env.DoString("require 'luatest'");
    14         //调用lua函数并接收返回值
    15         Fun f = env.Global.Get<Fun>("printInfo");
    16         Debug.Log(f(0));
    17     }
    18 }

    输出:

     6)下面演示Lua调用C#

    先写一个C#类

     1 public class Hero 
     2 {
     3     private int Hp;
     4     private string Name;
     5 
     6     public Hero(string name, int hp)
     7     {
     8         this.Name = name;
     9         this.Hp = hp;
    10     }
    11     public void PrintInfo()
    12     {
    13         Debug.Log(Name + "的血量是:" + Hp);
    14     }
    15     public int AddHp(int _hp)
    16     {
    17         Debug.Log("lua传递来的参数:" + _hp);
    18         Hp += _hp;
    19         return Hp;
    20     }
    21 }

    lua脚本

     注意:Lua调用C#类,要加CS

    Lua调用 MonoBehaviour 类要加 CS.UnityEngine

     别忘了在C#里执行一下

     1 public class textCSharp:MonoBehaviour
     2 {
     3     LuaEnv env = new LuaEnv();
     4     void OnGUI()
     5     {
     6         if (GUILayout.Button("Lua调用C#"))
     7         {
     8             LuaCallCSharp();
     9         }
    10     }
    11     void LuaCallCSharp()
    12     {
    13         env.DoString("require 'luatest'");
    14     }
    15 }

    结果如下:

    --------------------------------------------------------------------------------------------------------------------------------------------------------------

    XLUA配置三步:

    1.打标签 :XLUA会自动生成适配代码,注意子类打了标签,父类也要打。

    [LuaCallCSharp]   Lua里适配的委托、接口也要在C#定义里打标签。 

    [CSharpCallLua] 

    [Hotfix]

    2.静态列表

    3.动态列表

     加 static List<Type> 修饰

    详细参考:https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/configure.md

     ===================================================================================

    下面我们来搭一个XLUA使用框架

      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using XLua;
      5 using System;
      6 
      7 [LuaCallCSharp]
      8 public class LuaEnvMgr
      9 {
     10     //单例
     11     private static LuaEnvMgr instance;
     12     public static LuaEnvMgr Instance
     13     {
     14         get {
     15             if (instance == null)
     16                 instance = new LuaEnvMgr();
     17             return instance;
     18         }
     19     }
     20     //封装Lua虚拟机
     21     private LuaEnv env;
     22     public LuaEnv Env
     23     {
     24         get { return env; }
     25     }
     26     //构造函数初始化Lua虚拟机
     27     public LuaEnvMgr()
     28     {
     29         env = new LuaEnv();
     30     }
     31     //获取Lua table
     32     public LuaTable GetGlobalTable()
     33     {
     34         return env.Global;
     35     }
     36     //创建Lua table
     37     public LuaTable CreateTable()
     38     {
     39         return env.NewTable();
     40     }
     41     //释放
     42     public void Dispose()
     43     {
     44         env.Dispose();
     45     }
     46 }
     47 
     48 [CSharpCallLua]
     49 public delegate void OnCollisionDel(Collision2D collision);
     50 
     51 [CSharpCallLua]
     52 public delegate void OnTriggerDel(Collider2D collision);
     53 /// <summary>
     54 /// 方便Lua调用C#生命周期函数
     55 /// </summary>
     56 [LuaCallCSharp]
     57 public class LuaCallBase : MonoBehaviour {
     58 
     59     public TextAsset textAsset;//lua文件
     60 
     61     protected LuaTable table;//存储lua文件数据的表
     62 
     63     //常用更新生命周期
     64     protected Action luaAwake;
     65     protected Action luaStart;
     66     protected Action luaUpdate;
     67     protected Action luaDestory;
     68     protected Action luaOnGUI;
     69 
     70     //自定义委托生命周期
     71     protected OnCollisionDel luaCollisionEnter;
     72     protected OnTriggerDel luaTriggerEnter;
     73 
     74 
     75     protected virtual void Awake()
     76     {
     77         table = LuaEnvMgr.Instance.CreateTable();
     78         LuaTable meta = LuaEnvMgr.Instance.CreateTable();
     79         meta.Set("__index", LuaEnvMgr.Instance.GetGlobalTable());
     80         table.SetMetaTable(meta);
     81         meta.Dispose();
     82 
     83         LuaEnvMgr.Instance.Env.DoString(textAsset.text, this.GetType().Name, table);
     84         
     85         
     86         SetLuaData();
     87         GetLuaData();
     88         if (luaAwake != null)
     89             luaAwake();
     90     }
     91 
     92     public object GetLuaData(string dataName)
     93     {
     94         object obj;
     95         table.Get(dataName,out obj);
     96         return obj;
     97     }
     98 
     99     protected virtual void SetLuaData()
    100     {
    101         table.Set("self", this);
    102     }
    103 
    104     protected virtual void GetLuaData()
    105     {
    106         table.Get("awake", out luaAwake);
    107         table.Get("start", out luaStart);
    108         table.Get("update", out luaUpdate);
    109         table.Get("destroy", out luaDestory);
    110         table.Get("ongui", out luaOnGUI);
    111 
    112         table.Get("onCollisionEnter", out luaCollisionEnter);
    113         table.Get("onTriggerEnter", out luaTriggerEnter);
    114     }
    115 
    116     private void Start()
    117     {
    118         if (luaStart != null)
    119             luaStart();
    120     }
    121     private void Update()
    122     {
    123         if (luaUpdate != null)
    124             luaUpdate();
    125     }
    126     private void OnGUI()
    127     {
    128         if (luaOnGUI != null)
    129             luaOnGUI();
    130     }
    131     private void OnDestroy()
    132     {
    133         if (luaDestory != null)
    134             luaDestory();
    135     }
    136 
    137     private void OnCollisionEnter2D(Collision2D collision)
    138     {
    139         if (luaCollisionEnter != null)
    140             luaCollisionEnter(collision);
    141     }
    142     private void OnTriggerEnter2D(Collider2D collision)
    143     {
    144         if (luaTriggerEnter != null)
    145             luaTriggerEnter(collision);
    146     }
    147 }
    View Code

    只需要继承这个框架类,把lua脚本拖上去,就会执行啦!跟C#在Unity里的操作一样,只是挂载的C#脚本里的功能都由Lua脚本来实现了。

    如果嫌Lua每次调用C#方法都要加前缀麻烦。可以写一个Lua公共脚本,把这些前缀重新赋值,其他脚本只要 require "公共脚本名",就可以像写C#一样调用Unity方法啦!

    System=CS.System
    Int=System.Int32
    String=System.String
    
    Unity=CS.UnityEngine
    Debug=Unity.Debug
    GameObject=Unity.GameObject
    Transform=Unity.Transform
    Renderer=Unity.Renderer
    Color=Unity.Color
    Vector3=Unity.Vector3
    Vector2=Unity.Vector2
    Input=Unity.Input
    Resources=Unity.Resources
    Camera=Unity.Camera
    LineRenderer=Unity.LineRenderer
    EdgeCollider2D=Unity.EdgeCollider2D
    Time=Unity.Time
    
    Vector3List=CS.System.Collections.Generic.List(Vector3)
    Vector2List=CS.System.Collections.Generic.List(Vector2)
    
    function getLuaData(obj,script,data)
        local instance=obj:GetComponent(script)
        return instance:GetLuaData(data)
    end

      

    参考:Unity3D架构师进阶系列: 基于xLua的热更框架

  • 相关阅读:
    leetcode-hard-array-239. Sliding Window Maximum
    leetcode-hard-array- 227. Basic Calculator II
    leetcode-hard-array-287. Find the Duplicate Number
    leetcode-hard-array-128. Longest Consecutive Sequence
    leetcode-hard-array-41. First Missing Positive-NO
    基于深度学习的自然图像和医学图像分割:损失函数设计(1)
    对于自己,2020年应该思考的问题和要完成的任务
    查看两张相似图形的差异
    几种模型评价指标实现代码
    实验二涉及的步骤记录
  • 原文地址:https://www.cnblogs.com/tomatokely/p/15679735.html
Copyright © 2020-2023  润新知