当前位置:网站首页>Summary of knowledge points of xlua hot update solution

Summary of knowledge points of xlua hot update solution

2022-07-07 15:44:00 Listen to the rain outside the window

XLua Hot update solution knowledge points summary

Preface

​ Hot update is to realize the installation without repacking , A common scheme for updating clients online . It is generally divided into resource hot update and code hot update , There are many schemes for hot update of code , Which is provided by Tencent xLua At present Lua A commonly used solution in hot update , This article is only for xLua Summarize knowledge points , Readers who are interested in various hot updates can refer to my blog which specializes in explaining the basic functions and principles of various hot updates .

The essence of hot renewal

  • by Unity Provide Lua The ability to program
  • Give Way C# and Lua You can call each other to access

unity Native languages are based on C# Implementation related API, but C# The code needs to be compiled before it can be used , Use it directly C# There are many limitations . therefore , Use a scripting language that does not require compilation Lua The solution of has become a common solution for hot update .Lua Call is not supported by itself C# and U3D Correlation API,xLua The essence of the scheme is to make Lua To be able to call U3D Provided C# Correlation API, Thus, when the code is hot updated , Conduct Lua Code replacement and update can be achieved .

C# Call Lua Related knowledge

Lua Parser :LuaEnv

  • xLua The package provided C# object , Be able to use the relevant API Realization C# Call in Lua

  • The essence : stay C# In the running environment, a system that can run Lua Virtual environment for , In the virtual environment Lua Various types to C# Conversion of type , And then for C# Provide call access Lua The ability of .

  • Related to the offer API And explanation of usage

    //xLua Namespace references 
    using XLua;
    //Lua Parser LuaEnv Acquisition 
    LuaEnv env = new LuaEnv();
    
    // perform Lua command 
    env.DoString("Lua command "); // Generally used to load Lua Main entry script 
    
    // eliminate Lua Garbage collection for objects not manually released in 
    env.Tick(); // It is generally used for timing execution in frame update   perhaps   Execute when switching scenes 
    
    // Destruction and release Lua Parser 
    env.Dispose();
    
    //======== Key points : Redirect  Loader=======
    //xLua Default in Resources Download the script   In other places Lua Can't load to , Custom loading is required 
    //xLua Provided path redirection method , When executed Lua In language require when , It will automatically callback API Delegate method as a parameter in 
    env.AddLoader(LuaEnv.CustomLoader func);
    
    // Form of entrustment   Pass in require Parameter reference , Return what needs to be loaded Lua Byte array of script file 
    public delegate byte[] CustomLoader(ref string filepath);
    

    API Points for attention :

    Lua The parser defaults from Resources Download ,u3d Under the Resources The directory is not recognized Lua Script suffix , therefore It has to be for .lua Add scripts such as .txt Can access and call . AB There is also this special case in the bag , But you can load directly under the custom folder without adding an additional suffix . At the same time, the redirection provided by the parser supports multiple times

    Because of these circumstances , To facilitate development , You can choose to load from the custom folder under the daily compiler without adding a suffix every time , After packaging and launching, it must be AB Package loading can achieve hotter . Then you can realize the small functions under the editor , One click will all the customized folders Lua The script is typed AB Package and add suffix , Later, the author will implement .

  • LuaManager.cs encapsulation API, Realization Lua Manager ( Singleton mode and AB Package manager stay AB Bao's blog explained in detail , If you need to know something, you can check )

    using System.IO;
    using UnityEngine;
    using XLua;
    
    namespace Common
    {
          
        /// <summary>
        /// Lua  Manager 
        ///  External provision  Lua A simple call to the parser   Guarantee uniqueness 
        /// </summary>
        public class LuaManager : SingletonLazy<LuaManager>
        {
          
            // perform Lua Functions of language   Release the garbage   The destruction   Redirect 
            private LuaEnv luaEnv;
    
            // return Lua The big of the middle G surface _G  Provide find Lua Methods of global variables 
            //T obj = Global.Get<T>(" Variable name ");
            public LuaTable Global
            {
          
                get
                {
          
                    //LuaEnv Properties of 
                    return luaEnv.Global;
                }
            }
            protected override void Init()
            {
          
                base.Init();
                luaEnv = new LuaEnv();
                // Load under custom path  Assets/Lua Next   Convenient for daily development and use 
                luaEnv.AddLoader(MyCustomLoader);
                //Lua Script redirection   stay AB Load in the package   Use when packaging and launching 
                //luaEnv.AddLoader(CustomABLoader);
            }
    
    
    
            //Lua The script will be placed in AB In bag , Then load the Lua Script resources to execute it 
            //AB The package should also be loaded with text ( The suffix is .lua If you can't recognize, you need to add .txt)
            private byte[] CustomABLoader(ref string filepath)
            {
          
                // from AB Load in the package Lua file 
                // load AB Under bag Lua file -- adopt AB Package manager 
                TextAsset text = ABManager.Instance.LoadResource<TextAsset>("lua", filepath +".lua");
                if(text == null)
                {
          
                    Debug.Log(" Redirection failed   The file named " + filepath);
                    return null;
                }
                    
                // load byte Array 
                return text.bytes;
            }
    
            // Redirect : Custom path delegate method 
            private byte[] MyCustomLoader(ref string filepath)
            {
          
                // Through the logic in the function   Go to   load Lua file 
                //filepath Namely require File name in 
                // Splice one Lua The path of the file 
                string path = Application.dataPath + "/Lua/" + filepath + ".lua";
    
                // utilize File  Read the file 
                // Judge whether the file exists 
                if (File.Exists(path))
                {
          
                    return File.ReadAllBytes(path);
                }
                else
                {
          
                    Debug.Log(" Redirection failed   The file named :" + filepath);
                }
                return null;
            }
    
            /// <summary>
            ///  perform Lua Language 
            /// </summary>
            /// <param name="str">Lua sentence </param>
            public void DoString(string str)
            {
          
                if(luaEnv == null)
                {
          
                    Debug.Log(" Parser is empty , Please check ");
                    return;
                }
                luaEnv.DoString(str);
            }
    
            public void DoLuaFile(string fileName)
            {
          
                if (luaEnv == null)
                {
          
                    Debug.Log(" Parser is empty , Please check ");
                    return;
                }
                string path = string.Format("require('{0}')", fileName);
                luaEnv.DoString(path);
            }
            /// <summary>
            ///  Release the garbage 
            /// </summary>
            public void Tick()
            {
          
                if (luaEnv == null)
                {
          
                    Debug.Log(" Parser is empty , Please check ");
                    return;
                }
                luaEnv.Tick();
            }
            /// <summary>
            ///  The destruction Lua Parser 
            /// </summary>
            public void Dispose()
            {
          
                if (luaEnv == null)
                {
          
                    Debug.Log(" Parser is empty , Please check ");
                    return;
                }
                luaEnv.Dispose();
                luaEnv = null;
            }
    
        }
    }
    

C# obtain Lua The type of Foundation

utilize LuaEnv Provided Global Property to get and set global variables , Note that it cannot be obtained Local The local variable

Global Correlation API And how to use it ( notes : Use the above Lua Manager provides Global Property to call )

// Set up Lua The value of the basic variable in   utilize Set function 
//Set<Tkey,Tvalue>(" Variable name ", value )  Generally, the first generic type is string Type represents variable name   The second is value, Can be used to create / modify Lua Is the value of the variable 
LuaManager.Instance.Global.Set<string,int>("testNumber", 100);
// obtain Lua The value of the basic variable in  Get<T>(" Variable name ");  The generic type is consistent with the return value type 
int testNumber = LuaManager.Instance.Global.Get<int>("testNumber");
bool testBool = LuaManager.Instance.Global.Get<bool>("testBool");
float testFloat = LuaManager.Instance.Global.Get<float>("testFloat");
string testString = LuaManager.Instance.Global.Get<string>("testString");
// Pay attention to getting Lua When the number type of , According to Lua The specific value in is determined by int float  still double For storage 

C# obtain Lua Global function of function

obtain Lua Two main ways of function

  1. Use delegation to obtain
  2. utilize xLua Provided LuaTable To get ( Low efficiency The first one is recommended )
  • Get a function with no parameters and no return value

    // No parameter, no return value Lua Function acquisition 
    // Custom no parameter no return delegate acquisition Lua function 
    public delegate void CustomCall(); 
    CustomCall call = LuaManager.Instance.Global.Get<CustomCall>("testFun"); // obtain Lua There is no parameter and no return function in testFun
    call(); // The delegate 
    // utilize C# Provided   entrust Action To get  --Action No parameter no return 
    Action action = LuaManager.Instance.Global.Get<Action>("testFun");
    action();
    //Unity  Commission provided 
    UnityAction unityAction = LuaManager.Instance.Global.Get<UnityAction>("testFun");
    unityAction();
    //Xlua Provides a way to get functions  --- To use less , Low efficiency 
    LuaFunction luaF = LuaManager.Instance.Global.Get<LuaFunction>("testFun");
    luaF.Call();
    
  • Get the function with parameters and return values

    [CSharpCallLua]
    // Delegate with parameters and return values  --  Note that when the custom delegate is not recognized   Be sure to add features and regenerate code 
    public delegate int CustomCall2(int a);
    // Get the function with parameters and returns  ======
    CustomCall2 call2 = LuaManager.Instance.Global.Get<CustomCall2>("testFun2");
    print(" The return value of the function with parameters and return value is  : " + call2(10));
    //C#  Provided with a return value delegate 
    Func<int, int> func = LuaManager.Instance.Global.Get<Func<int, int>>("testFun2");
    print(" The return value of the function with parameters and return value is  : " + func(10));
    //XLua  Provided LuaFunction  because Lua The characteristics of multiple return values of functions   It's an array 
    LuaFunction luaF2 = LuaManager.Instance.Global.Get<LuaFunction>("testFun2");
    print(" The return value of the function with parameters and return value is  : " + luaF2.Call(10)[0]); // The returned array takes the first 
    
  • Acquisition of multi return function ( Note that custom delegates may not be predefined , You need to add features and regenerate the code )

    // Delegate definition with multiple return values   utilize ref out Construct return value parameters 
    [CSharpCallLua] // if XLua Delegate type is not recognized   Need to add this feature   And the editor is regenerated XLua Code 
    // Multiple return values  --  The first return value is return Of   For subsequent return values out/ref receive   First define parameters 
    public delegate int CustomCall3(int a,out int var2,out bool var3,ref string var4,out int var5);
    
    // Multiple return value function get   Entrust with out ref LuaFunction The return value of the call is array   Just go through it 
    //C#  in   Use  out ref obtain 
    CustomCall3 call3 = LuaManager.Instance.Global.Get<CustomCall3>("testFun3");
    //out  There is no need to initialize outside  out Only don't come in   Initialization will not be passed in 
    int var2; bool var3; string var4 = ""; int var5; //ref It needs to be initialized   Because it goes in and out   You cannot enter uninitialized values 
    int var1 = call3(10,out var2,out var3,ref var4,out var5);
    print(string.Format(" The return value of a multi return function {0} {1} {2} {3} {4}",var1,var2,var3,var4,var5));
    //XLua Provide  LuaFunction
    LuaFunction luaF3 = LuaManager.Instance.Global.Get<LuaFunction>("testFun3");
    // When the parameter types are inconsistent, use obejct Otherwise, it depends on the parameter type 
    object[] objs = luaF3.Call(1000);
    for (int i = 0; i < objs.Length; i++) 
         print(string.Format(" The first {0} The return values are {1}", i, objs[i]));
    
  • Acquisition of variable length parameter function

    // Definition of variable parameter delegate  Lua The function prototype  function(a,...)
    public delegate void CustomCall4(string a, params int[] args); // Type of variable length parameter   It is decided according to the actual situation   If the type is inconsistent, use Object
    // Acquisition of variable length parameter function 
    CustomCall4 call4 = LuaManager.Instance.Global.Get<CustomCall4>("testFun4");
    //Lua Pay attention to the use of arrays when traversing in 
    call4("123", 1, 3, 11, 566);
    
    //XLua Provide 
    LuaFunction luaF4 = LuaManager.Instance.Global.Get<LuaFunction>("testFun4");
                luaF4.Call("123", 1, 3, 11, 566);
    

C# obtain Lua Table of Table

Lua The table in is very powerful , Can store any data type , You can customize the index or automatically fill the index . commonly C# obtain Lua The tables in can be converted into the following forms .

  • utilize List List access Lua Of table

    //Lua in table The acquisition of is a shallow copy ( Value copy )
    //Lua in table Element types are unified 
    List<int> list = LuaManager.Instance.Global.Get<List<int>>("testList");
    for (int i = 0; i < list.Count; i++)
    	Debug.Log(list[i]);
    //Lua If the type of the table in is uncertain, use Object save 
    List<object> list2 = LuaManager.Instance.Global.Get<List<object>>("testList2");
    for (int i = 0; i < list2.Count; i++)
    	Debug.Log(list2[i]);
    
  • utilize Dictionary Dictionary access Lua Of table

    Dictionary<string, int> dic = LuaManager.Instance.Global.Get<Dictionary<string,int>>("testDic");
    foreach(var item in dic)
    {
          
    	Debug.Log(item.Key+"_"+item.Value);
    }
    // Value copy 
    Dictionary<object, object> dic2 = LuaManager.Instance.Global.Get<Dictionary<object, object>>("testDic2");
    foreach(var item in dic2)
    {
          
    	Debug.Log(item.Key + "_" + item.Value);
    }
    
  • utilize Class Class gets Lua Of table

    table When acting as a class What you need to pay attention to when defining classes

    1. The name of the member variable and Lua The names of the elements in the table must be consistent
    2. The type must correspond to , Basic types , The function type is delegate or LuaFunction, And it must be public Variable
    3. When the number of parameters does not match ,Lua Redundant variables will be discarded ,C# Redundant variables are not assigned .
    4. table Zhongxu deposit table Variable , Class definitions can also be nested
    --lua Provided in table surface 
    testClass = {
          
    	testInt = 2,
    	testBool = true,
    	testFloat = 1.2,
    	testString = "123",
    	testFunc = function()
    		print("123123")
    	end,
    	testInClass ={
          
    		testInInt = 10
    	}
    }
    
    [CSharpCallLua] // The custom type is not recognized , You must add features and regenerate the code 
    public class CallLuaClass
    {
          
        // Declare member variables in this class 
        // The name must be with Lua It's the same over there 
        // It must be public   Private and protected cannot be assigned 
        public int testInt;
        public bool testBool;
        public float testFloat;
        public float testString;
        public UnityAction testFunc;
        // Variables in customization can be more or less  ,  If the variable ratio Lua Few of them ignore and discard it 
        // If the variable ratio Lua Many of them , No assignment 
        public void Test()
        {
          
            Debug.Log(" test ");
        }
    
        public CallLuaInClass testInClass;
    }
    
    // Nested class 
    public class CallLuaInClass
    {
          
        public int testInInt;
    }
    
    // Get still through Get function , It is still a value copy 
    CallLuaClass obj = LuaManager.Instance.Global.Get<CallLuaClass>("testClass");
    
  • Using interfaces Interface obtain Lua Of table

    namespace ns
    {
          
        // The interface must have features 
        [CSharpCallLua] // Every time the interface is changed, the code needs to be rebuilt after deletion 
        public interface ICharpCallInterface
        {
          
            // Fields are not allowed in the interface   Delegation, etc. , Receive with attributes Lua The variables in the 
            int testInt {
           get; set; }
            bool testBool {
           get; set; }
            float testFloat {
           get; set; }
            string testString {
           get; set; }
            UnityAction testFunc {
           get; set; }
        }
        public class CallInterface : MonoBehaviour
        {
          
            private void Start()
            {
          
                LuaManager.Instance.DoLuaFile("Main");
                ICharpCallInterface obj = LuaManager.Instance.Global.Get<ICharpCallInterface>("testInterface");
                print(obj.testInt);
                obj.testInt = 100000;
                obj.testFunc();
                //================ Interface copy is a deep copy   Reference copy   Changed the value  lua The median value changes accordingly ==================
                ICharpCallInterface obj2 = LuaManager.Instance.Global.Get<ICharpCallInterface>("testInterface");
                print(obj2.testInt);
            }
        }
    }
    

    Be careful : The interface is a deep copy ! It's a deep copy ! It's a deep copy !

  • utilize xLua Provided LuaTable obtain Lua Of table

     // Not recommended LuaTable and LuaFunction  Low efficiency   There is also the possibility of memory leaks 
    // Reference object   Deep copy ( Reference copy )
    LuaTable table = LuaManager.Instance.Global.Get<LuaTable>("testLuaTable");
    Debug.Log(table.Get<int>("testInt"));
    Debug.Log(table.Get<bool>("testBool"));
    Debug.Log(table.Get<float>("testFloat"));
    Debug.Log(table.Get<string>("testString"));
    table.Get<LuaFunction>("testFunc").Call();
    // It will change when modifying Lua The value in 
    table.Set("testInt", 55);
    Debug.Log(table.Get<int>("testInt"));
    table.Dispose(); // Be sure to destroy it after use .
    

    Be careful :LuaTable It's a deep copy !

C# Call Lua There are only interfaces and LuaTable It's a deep copy , The rest are all shallow copies

Lua Call C# Related knowledge

​ Usually, when developing related logic that needs hot update , It's usually used Lua To call C# and U3D Develop related classes of , relative C# call Lua, Lua call C# More important .

The main entry of the program

​ Unity Cannot start directly in Lua Script , Need to pass through C# call Lua In order to start Lua. Generally, a startup will be set Lua Main entrance of Main.lua Generally used to define some aliases , Start other scripts

--Main.lua Lua The main entry of the program   This starts calling other scripts 
-- Be careful   from Lua In the script require Redirection will still occur , Generally all Lua The scripts are placed in the custom folder 
require("Test") -- start-up Test.lua Script 

Lua call C# Class

xLua Provided Lua Use in C# The fixed routine of class : CS. Namespace . Class name

Instantiation C# Class ( Not mono Script ),Lua No middle new Method , You can use it directly CS. Namespace . Class name ()

Scripts generally cannot be used directly new To instantiate , Need to use GameObject Object supplied AddComponent Method

Generally, global variables are used to store the C# The type of , Call variables directly when calling again ( Equivalent to taking an alias )

--Lua call C# Fixed routine  CS. Namespace . Class name 
local obj1 = CS.UnityEngine.GameObject()  -- Instantiate a GameObejct object 
GameObject = CS.UnityEngine.GameObject    -- Define global variable storage classes , Alias 
local obj2 = GameObject("mrLiu")          -- Use alias to instantiate and pass parameters 

-- For static objects in classes , You can use it directly . To call 
local obj3 = GameObject.Find("mrLiu");
-- Get the member variables in the instance object   direct . call 
print(obj3.transform.position)

Vector3 = CS.UnityEngine.Vector3          -- Storage class , names 
-- Use member methods in the instance object   Be sure to use colons : call !  Otherwise, the report will be wrong 
obj3.tranform:Translate(Vector3(5,2,1))

-- Use custom C# class   Note that the namespace should match ( The name... Has been defined Test Of C# class   No namespace )
local test = CS.Test()
-- A special case , Inherited MonoBehaviour Script class for 
local obj4 = GameObject(" Add script test ")
--Lua Generics are not supported , utilize AddComponent overloaded , Provide the type in the parameter  typeof yes xLua Access provided C# Method of type 
obj4:AddComponent(typeof(CS.Test)) -- Note that member methods are called with colons 

Be careful : Calls to member methods must use colons !

Lua call C# enumeration

Enumeration calls are similar to classes :CS. Namespace . Enum name

Enumeration does not require instantiation , Enumeration name does not exist () Usage of There is still the use of aliasing

-- Enumeration call 

-- call Unity Enumeration in 
-- The calling rules of enumeration and class are the same 
--CS. Namespace . Enum name   There is no small difference in instantiation 

--U3D Some of its own enumeration types  PrimitiveType  Some types of geometry 
-- Create geometry of a specific shape ,GameObject.CreatePrimitive(PrimitiveType type)
-- Alias is also supported 
PrimitiveType = CS.UnityEngine.PrimitiveType
GameObject = CS.UnityEngine.GameObject
-- Static member functions are available . call 
local obj = GameObject.CreatePrimitive(PrimitiveType.Cube)
-- Custom enumeration   Pay attention to namespaces as you use methods 
MyEnum = CS.MyEnum
-- Enumeration conversion 

-- Numerical value to enumeration 
local a = MyEnum.__CastFrom(1)
print(a)
-- String to enumeration 
local b = MyEnum.__CastFrom("Attack")
print(b)

Lua call C# Array of

Important nature :Lua Call in C# Related data structures , It still uses its original data structure properties and methods

reason :xLua call C# when , The essence is to use custom data types userdata And meta table to achieve storage C# Instance members of various objects in , The purpose of static members and various types of information contained in type objects

--Lua Use C# Array related knowledge points 
--Lua Calling it in does not change the structure of the original language   Still use the original language method 
local obj = CS.LuaCallArray() -- Test use C# class , The related array has been declared inside 

-- length   Out of commission #  It should be provided by the original array object Length attribute 
print(obj.arr.Length)

-- Access elements   The index is still from 0 Start 
print(obj.arr[0])
-- Traversal requires attention from 0 Start ,Lua Ergodic variable range double closure , So the length needs to be reduced by one 
for i = 0,obj.arr.Length-1 do
	print(obj.arr[i])
end

--Lua Can't go through C# Keywords of define relevant data structures , But it can be achieved by using more general related methods 
--Lua Create a C# Array of   utilize Array class 
--Array.CreateInstance(Type elementType,int length)  Static methods 
local arr2 = CS.System.Array.CreateInstance(typeof(CS.System.Int32),10)
print(arr2.Length)
print(arr2[0])
print(arr2)

Note the loop traversal time and Lua Table differences

Lua Call two-dimensional array problem ( pit )

Lua Unsupported use [x,y] or [x][y] To access a two-dimensional array

You have to use Array Access the relevant methods implemented under

  • arr.GetValue(x,y); Access elements
  • arr.GetLength(0); Get the number of lines
  • arr.GetLength(1); Get the number of columns

Other traversal and other related operations are based on these API It can be realized normally

Lua call C# Of List

The nature of the acquisition rule is basically the same as that of the array The relevant methods provided are different

The creation is quite different , The relevant methods of the old version and the new version will be introduced

-- The rules follow C#
obj.list:Add(1)
obj.list:Add(2)
print(obj.list.Count) -- utilize Count To obtain the length of the 
-- Traverse 
for i=0,obj.list.Count-1 do
	print("list",obj.list[i])
end
print(obj.list)
-- stay Lua Created in List object 
-- The old version xLua
local list2 = CS.System.Collections.Generic["List`1[System.String]"]()
list2:Add("123")
print(list2[0])
-- The new version xLua > v2.1.12
-- Equivalent to one List Generic classes   You also need to instantiate 
local List_String = CS.System.Collections.Generic.List(CS.System.String)
local list3 = List_String() -- Create objects 
list3:Add("55555")
print(list3[0])

Lua call C# Of Dictionary

Dictionary calls are different from list arrays Unable to get [] Brackets call directly , You need to use the relevant methods provided by the dictionary object

obj.dic:Add(1,"1234")
print(obj.dic[1])

-- Traverse 
for k,v in pairs(obj.dic) do
	print(k,v)
end
-- stay Lua Create a dictionary object in 
-- Get alias   You need to instantiate 
local Dic_String_Vector3 = CS.System.Collections.Generic.Dictionary(CS.System.String,CS.UnityEngine.Vector3)
local dic2 = Dic_String_Vector3()
dic2:Add("123",CS.UnityEngine.Vector3.right)
-- Dictionary traversal must use pairs  Otherwise, the string index cannot be recognized 
for k,v in pairs(dic2) do
	print(k,v)
end
-- stay Lua The dictionary created in is directly through [] Get cannot get 
print(dic2["123"]) -- I won't support it 
--C# The function prototype TryGetValue utilize out receive value, return bool
--Lua Call in TryGetValue Not at the time out keyword , Use multiple return values 
-- Two return values  bool Does the key exist  value The value of the key 
print(dic2:TryGetValue("123"))
--xLua by Dictionary The expansion method provided  get_Item and set_Item  Find and modify the value according to the key 
-- utilize get_Item  Through this fixed method 
print(dic2:get_Item("123")) -- Find dictionary elements 
-- For change set_Item
dic2:set_Item("123",nil)
print(dic2:get_Item("123")) --vector3 Can't be empty   By default (0,0,0)

Pay attention to the special calling method of the dictionary and You must use pairs

Lua call C# Extension method of

When using the extension method , Be sure to add LuaCallCSharp Feature and regenerate the code

Suggest Lua This feature is added to all custom classes used in , Will significantly improve performance

Without this feature, the reflection mechanism is used , inefficiency

// Want to be in Lua When using the expansion method in   Be sure to add features in front of tool classes 
// Suggest  Lua Classes to be used in   Add this feature   Can improve performance 
// Do not add this feature   May not report an error  xLua Using a reflection mechanism   Low efficiency 
[LuaCallCSharp]
public static class Tools
{
    
    // When the specified object calls this method   It is equivalent to passing itself into 
    public static void Move(this Test obj)
    {
    
        Debug.Log(obj.name + " Move ");
    }
}
public class Test
{
    
    public void Speak(string str)
    {
    
        print(str);
    }
}
-- The extension class does not need to be in lua Load in   Just add features 
obj = Test()
obj:Speak("mrLiu")
-- Using the expansion method is consistent with using the member method   Pass yourself into 
-- call C# The expansion method of a class in , Be sure to add features to the classes of extension methods 
obj:Move()

Lua Call with ref and out Function of parameter

For the use of multiple return values of functions :Lua Function returns multiple values directly and C# You can only return one , The rest passed ref and out Pass on references , Receive values outside the function , Pay attention to the sequence one by one .

public class Test
{
    
    public int RefFunc(int a, int b ,ref int c, ref int d )
    {
    
        c = a + b;
        d = a - b;
        return 100;
    }

    public int OutFunc(int a, int b, out int c, out int d)
    {
    
        c = a;
        d = b;
        return 200;
    }

    public int RefOutFunc(int a , out int b, ref int c)
    {
    
        b = a * 10;
        c = a * 20;
        return 300;
    }
}
print("*******Lua call C# ref Method related knowledge points **********")
Lesson5 = CS.Test

local obj = Test()

--ref Parameters   It will be returned to... In the form of multiple return values lua
-- If the function has a return value, it is the first   rest ref One to one correspondence from left to right 
local raw,ref1,ref2 = obj:RefFunc(1,1,0,0)
--RefFunc(1,1)  Do not give ref The default value of the current type will be passed in by value transfer. The number is 0
-- Be careful :  here ref The parameter is at the end and can be omitted , When it is in the middle, it is necessary to occupy the space, which must not be omitted 
print(raw,ref1,ref2)


print("*******Lua call C#out Method related knowledge points **********")
--out Parameters   It will be returned to... In the form of multiple return values lua
--out Parameters do not need to be transferred  out It can be omitted   And there is no need to occupy space 
local raw,out1,out2 = obj:OutFunc(1,1)
print(raw , out1 , out2)

print("*******Lua call C#ref out Method related knowledge points **********")
-- When mixed   The above two rules need to be combined  ref Space required  out No need to occupy space 
local raw,out1,out2 = obj:RefOutFunc(20,30) --out Omit  30 Direct to ref
print(raw , out1 , out2)

Lua Call overloaded functions

public class Test
{
    
    public int Calc()
    {
    
        return 100;
    }

    public int Calc(int a , int b)
    {
    
        return a + b;
    }
    public int Calc(int a)
    {
    
        return a;
    }
    public float Calc(float a)
    {
    
        return a;
    }
}
local obj = CS.Test()
--Lua Defining overloaded functions is not supported by itself 
--Lua Support calling C# Overloaded functions in 
print(obj:Calc())
print(obj:Calc(10,5))

--Lua There are only Number
--C# There are overloaded functions of various precision in   Unable to distinguish 
-- Overloading data types   There may be problems when using 
print(obj:Calc(10))
print(obj:Calc(10.2))

-- Solve the ambiguity of overloaded functions 
--XLua Provide reflection mechanism to solve 
-- Just to understand   As far as possible need not   inefficiency 
--Type Is the key class of reflection 
-- Get the information about the specified function 
local fun_int = typeof(CS.Lesson6):GetMethod("Calc",{
    typeof(CS.System.Int32)})
local fun_float = typeof(CS.Lesson6):GetMethod("Calc",{
    typeof(CS.System.Single)})
-- adopt xlua A method is provided   Turn into lua Function USES 
-- Usually only turn once   And then reuse it   Declare functions 
local f1 = xlua.tofunction(fun_int)
local f2 = xlua.tofunction(fun_float)

-- Member method   The first parameter is passed to the object 
-- Static methods   There is no need to pass the first parameter 
print(f1(obj,10))
print(f2(obj,10.2))

Lua Invoke delegates and events

public class Test
{
    
    // Declare delegates and events 
    public UnityAction del; //delagate
    // event 
    public event UnityAction eventAction;
    // Triggering event 
    public void DoEvent()
    {
    
        if (eventAction != null)
            eventAction();
    }
    // Events do not allow direct external operations , Need packaging method 
    public void ClearEvent()
    {
    
        eventAction = null;
    }
}
local obj = CS.Test()
-- Delegates are used to encapsulate functions 
-- Use C# Entrustment   Can be used to hold Lua function 
local fun = function()
	print("Lua function fun")
end
--lua There is no matching operator in   You can't += Add a delegate 
-- If you add a function to a delegate for the first time   Should use the  =  follow-up +=
obj.del = fun
obj.del = obj.del + fun
obj.del()
obj.del = obj.del - fun
print(" Start subtracting function ")
obj.del()
-- Empty all stored functions   Delegate support  =
obj.del = nil


print("*******Lua call C# Event related knowledge points **********")
local fun2 = function()
	print(" Event plus function ")
end
-- Event addition and subtraction function   and   Delegation is very different 
--lua When using events in   use lua The fixing method provided 
-- object : Event name ("+", The function variables )
obj:eventAction("+",fun2)
obj:eventAction("+",fun2)
obj:DoEvent()
-- The cancellation of the event 
obj:eventAction("-",fun2)
obj:DoEvent()
-- Know the event   It is not allowed to carry out directly outside the event = Wait for the operation   Can only += -=
-- Need to be in C# Encapsulate a function to perform this operation 
obj:ClearEvent()
obj:DoEvent()

Pay attention to the registration and cancellation of events C# The events in are very different

Lua Call a special system type

​ When using some special types of the system for example Unity Provided UnityAction<float> Entrust, etc ,xLua The commonly used ones have been prepared in advance , But if generic parameters are complex , Not prepared in advance , Must be in xLua Register in , Traditional types can add features directly , However, the delegation provided by the system cannot modify the source code and add features directly , Other methods are needed .

  • C# Call Lua Where you must register
    1. There are no predefined delegates ( Custom features can be added , The delegation of the system can only be registered )
    2. The interface must have features ( Custom interface plus features , System interfaces can only be registered )
// Must be a static class   Class names and variable names in classes are not required 
public static class Test
{
    
    // by C# call Lua When the system type ( entrust , Interface )
    [CSharpCallLua]
    public static List<Type> cSharpCallLuaList = new List<Type>()
    {
    
      typeof(UnityAction<float>),
    };
    // by Lua call C# System type ( Development method )  To improve performance, it is recommended to register or add features to everything you use 
    [LuaCallCSharp]
    public static List<Type> luaCallCSharpList = new List<Type>()
    {
    
        typeof(GameObject),
        typeof(Rigibody),
    }
}

Advantages of registration : It will not be constrained by the fact that the system type cannot add features , Put all the features together , No weight, no leakage , Than adding features to classes alone , Structure is clearer .

Lua Of nil and C# Of null

​ Lua Of nil and C# Of null Unequivalence , If you directly judge a C# object obj == nil if obj by null It is false, prove null == nil It's wrong. . Here are three solutions :

  1. utilize C# Object supplied Equals Method obj:Equals(nil) -- The most direct , But there are risks , if Lua The data type of does not provide this method , Will report a mistake

  2. stay Lua Encapsulate a global method to judge null

    function IsNull(obj)
        if obj == nil or obj:Equals(nil) then
            return true
        end
        return false
    end
    
  3. by Object Type expands a method

    // Remember to add features to the expansion method 
    [LuaCallCSharp]
    public static class ExtendFunc
    {
          
        // Expand one for Object Method of judging empty space   For giving lua Use  lua No use null and nil Compare 
        public static bool IsNull(this Object obj)
        {
          
            return obj == null;
        }
    }
    

Lua call C# Cooperation of

​ Lua It provides the related calls of the coroutine , But in xLua What we hope to achieve in is to use Lua Language call C# Correlation API, So what we need to open here is Unity Script coordination , You can't use your own , the Lua Function passed in to Mono In the process of providing assistance .

--xlua A tool list provided 
-- Be sure to pass require Only after calling 
util = require("xlua.util")

--C#  Zhongxie Cheng starts through inheritance Mono Class 
-- Through the startup function inside StartCoroutine Start the process 
GameObject = CS.UnityEngine.GameObject
WaitForSeconds = CS.UnityEngine.WaitForSeconds

-- Create a new empty object in the scene , Then hang up a script , The script only inherits mono
local obj = GameObject("Coroutine")
local mono = obj:AddComponent(typeof(CS.Test))

-- Hope to start with the collaboration process Lua Middle function 
fun = function()
	local a = 1
	while true do
		--lua You can't use C# Medium yield keyword 
		-- Just use Lua The coroutine in returns 
		coroutine.yield(WaitForSeconds(1))
		print(a)
		a = a + 1
		if a > 10 then
			mono:StopCoroutine(running)
		end
	end
end
-- We can't just put  lua Function is passed into the open coroutine !!
--mono:StartCoroutine(fun)
-- utilize util Solutions provided in the tool table 
-- If you want to put the Lua Function as C# The covariance function uses 
-- Must call xlua.util Medium cs_generator(lua function )
running = mono:StartCoroutine(util.cs_generator(fun))

-- Close the coroutines 

Lua call C# Generic functions of

Lua Only call constraints are supported Class With parameters c# function

Even so, there are still certain restrictions It is different under different packaging methods Be careful with

  • Support Mono Pack and use
  • if IL2Cpp pack , Only if the generic type is a reference type can it be used . If it's a value type , Unless C# The same generic parameter has been called ,Lua Can only be used in .
public class Test
{
    
    public interface ITest
    {
    

    }
    public class TestFather
    {
    

    }
    public class TestChild : TestFather,ITest
    {
    

    }
    public void TestFun1<T>(T a, T b) where T:TestFather
    {
    
        Debug.Log(" Generic methods with parameters and constraints ");
    }

    public void TestFun2<T>(T a)
    {
    
        Debug.Log(" Generic methods with parameter unconstrained ");
    }

    public void TestFun3<T>() where T:TestFather
    {
    
        Debug.Log(" Constrained parameterless generic methods ");
    }

    public void TestFun4<T>(T a)where T:ITest
    {
    
        Debug.Log(" There are constraints and parameters , Constraints are interfaces ");
    }
}
local obj = CS.Test()
local child = CS.Lesson12.TestChild()
local father = CS.Lesson12.TestFather()

--Lua  Support generic functions with constraints and parameters 
obj:TestFun1(child,father)
obj:TestFun1(father,child)
--Lua  Generic functions without constraints are not supported 
--obj:TestFun2(child)
--Lua  Generic functions with constraints and no parameters are not supported 
--obj:TestFun3()
--Lua  Constraints of non Class Function of 
--obj:TestFun4(child)

-- summary ,Lua Only constraints of Class Functions with parameters 

-- There are certain use restrictions 
-- If you use Mono Packaging supports the use of 
-- If it is IL2Cpp  Only if the generic type is a reference type can it be used 
-- If it's a value type , Unless C# The same generic parameter has been called over there ,lua Can only be used in 

It can be seen that there are many inconveniences when using generics directly , but xLua Provides the method of general function to realize the call of generic function

-- Get the general function 
-- Set generic types for reuse 
--xlua.get_generic_method( class ," Function name ")
local testFun2 = xlua.get_generic_method(CS.Lesson12,"TestFun2")
testFun2_R = testFun2(CS.System.Int32) -- Set generic type 
-- Function call 
-- Member method   The first parameter is passed to the object that calls the function 
-- Static methods do not need to be passed 
-- The second parameter is the value of the generic 
testFun2_R(obj,1)
原网站

版权声明
本文为[Listen to the rain outside the window]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130610501202.html