Basic knowledge of hot update in Unity, basic knowledge of Xlua and ILRuntime

1. What is hot update

Hot update refers to updating some non-core code and resources in the game online without recompiling and packaging the game, such as event operation and patching. Hot update is divided into resource hot update and code hot update. Code hot update is actually a hot update that treats code as a resource, but what is usually called hot update generally refers to code hot update. Resource hot update is mainly realized through AssetBundle. In the Unity editor, specify the name and suffix of the AB package for the resources used in the game, then package it and upload it to the server, and dynamically load the AB resource package on the server when the game is running. Code hot update mainly includes Lua hot update, ILRuntime hot update, and C# direct reflection hot update. Since the ILRuntime hot update is immature and there may be some pitfalls, and C# directly reflects the hot update and does not support the IOS platform, so most of the current Lua hot update solutions that are more mature and have no platform restrictions are used.


2. Why there is a hot update

Hot updates can shorten the process for users to obtain new versions of clients and improve user experience.

No hot update:

PC users: download client -> wait for download -> install client -> wait for installation -> start -> wait for loading -> play

Mobile phone users: download the APP in the mall->wait for download->wait for installation->start->wait for loading->play

With hot update:

PC users: start -> wait for hot update -> wait for loading -> play

PC users with an independent loader: start the loader->wait for hot update->start the game->wait for loading->play

Mobile phone users: start -> wait for hot update -> wait for loading -> play

It can be seen from the comparison that whether there is a hot update has a great impact on the user experience, mainly because the user does not need to update the client by himself.


3. How to use hot update, and compare different solutions for using hot update

3.1. LUA hot update (LUA is bound to C#, the solution is mature)

The Lua hot update solution is to provide a Lua running environment and interact with C# through a Lua hot update plug-in (such as ulua, slua, tolua, xlua, etc.). xLua is an open-source hot update plug-in by Tencent. It is endorsed by a major manufacturer and maintained by full-time personnel. The stability and sustainability of the plug-in are strong. 

Since Lua does not need to be compiled, Lua code can be run directly in the Lua virtual machine, and scripting languages ​​such as Python and JavaScript are the same. The xLua hot update plug-in is to provide a Lua virtual machine for C# environments such as Unity, .Net, Mono, etc., so that Lua code can also be run in these environments, thereby increasing the ability of Lua scripting for them. With xLua, these Lua codes can easily call each other with C#. In this way, C# is usually used for development, and Lua is used when a hot update is required, and the previous Lua code is converted into C# code when the next version is updated, so as to ensure the normal operation of the game.

Among them, XLua will be discussed below.

Lua hot update principle: logic code is converted into scripts, scripts are converted into text resources, and programs are updated in the form of resource updates

 Xlua performance test done by an older brother:

XLua performance test_tian2kong's column-CSDN blog_xlua performance optimization This piece of code, the running performance analysis is like this This code is written by me in lua, other environments are the same, this is the code difference, one is written in lua, An analysis diagram written in C# and running is like this. From these two analysis diagrams, we can see that for the api function Translate, one is called in C# and the other is called in xlua. If there are many orders of magnitude, there is still a big difference in performance. So I personally think that if the UI is implemented with xlua, there is no big problem. If it is in battle, try not to take the implementation function from the update of Xlua... https://blog.csdn.net/tian2kong/article/details /79423848 This old man uses the same function, the one written in C# runs in 10.68ms, and the one written in Xlua runs in 37.29ms. It can be seen that the performance of Xlua is still very different. The following article will continue to study why Xlua performs worse.

3.2 .ILRuntime hot update

The ILRuntime project is an open-source hot update project of Palm Fun. It provides a pure C#, fast, convenient and reliable IL runtime for C#-based platforms (such as Unity), enabling it to run on hardware environments that do not support JIT (such as iOS) ) can realize code hot update. The principle of the ILRuntime project is actually to first use VS to package the C# code that needs to be hot-updated into a DLL (Dynamic Link Library) file, and then read the DLL information through the Mono.Cecil library and get the corresponding IL intermediate code (IL is the .NET platform The intermediate code generated after compiling C#, F# and other high-level languages ​​on the Internet, the specific form of IL is the .dll dynamic link library file or .exe executable file obtained after compiling on the .NET platform), and finally interpreted and executed by the built-in IL A virtual machine to execute the IL code in the DLL file.

Since the ILRuntime project uses C# to complete hot updates, reflection is often used to achieve certain functions. Reflection is an important mechanism for the .NET platform to obtain type information (including classes, interfaces, structures, delegates, and enumerations) at runtime, that is, to obtain internal information from outside the object, including fields, properties, methods, and constructors. and features etc. We can use reflection to dynamically obtain type information, and use this information to dynamically create objects of the corresponding type. However, there are two types of reflection in ILRuntime: one is to directly use C# reflection to obtain the System.Type class object in the hot update DLL; the other is to obtain the object inherited from System.Type through appdomain.LoadedTypes in the main Unity project. The IType class object of the class, because the class in the hot update DLL cannot be obtained directly through the System.Type class in the main Unity project.

ILRuntime will also be discussed below.

The ILRuntime project provides a C#-based platform (such as Unity) 纯C#实现, 快速and 方便the 可靠IL runtime (detailed later) , enabling the implementation of code in a hardware environment that does not support JIT (such as iOS) (detailed later) hot update.

3.3. Update dll directly (IOS cannot be used)

Because Android supports JIT (Just In Time) just-in-time compilation (dynamic compilation) mode, that is, it can compile while running, and supports dynamic generation of code and types at runtime. Starting from Android N, a hybrid compilation mode that uses both JIT and AOT is introduced. The advantage of JIT is that it supports dynamic generation of code and types at runtime, fast APP installation, and does not take up too much memory. The disadvantage is that runtime resources are occupied during compilation, and the execution speed is slower than AOT. For example, virtual functions and reflections in C# determine the corresponding overloaded methods and classes when the program is running. Therefore, the Android platform can directly use C# reflection to execute the DLL file without any third-party hot update solution. During the actual development, the assembly DLL file is loaded through the System.Reflection.Assembly class, and then the System.Type class is used to obtain the information of a certain class in the assembly, and the instance object can also be dynamically created through the Activator class.

The IOS platform adopts the AOT (Ahead Of Time) pre-compilation (static compilation) mode, and does not support the JIT compilation mode, that is, the code is compiled into machine code and stored locally before the program runs, and then it can be executed directly at runtime, so AOT Code and types cannot be dynamically generated at runtime. The advantage of AOT is fast execution speed and higher security. The disadvantage is that because AOT needs to be compiled in advance, the installation time of APP is long and takes up memory. Mono runs in Full AOT mode on the IOS platform . If you directly use C# reflection to execute the DLL file, it will trigger Mono's JIT compiler. However, JIT is not allowed in Full AOT mode, so Mono will report an error. Therefore, it is not allowed to directly use C# reflection to execute DLL files to realize hot update on the IOS platform.

Precompile the execution code into assembly dll. Package the code into an Assetbundle as a TextAsset. At runtime, use the Reflection mechanism to realize the functions of the code. Hot update can be realized by updating the corresponding Assetbundle. (Specific technical details, discussed later)


4.Xlua source code implementation

4.0 Features of Xlua

xLua adds the ability of Lua script programming to the C# environment . With xLua, these Lua codes can be easily called with C# .

Xlua can: 

  • 1. The C# implementation (method, operator, property, event, etc.) can be replaced by the Lua implementation at runtime;
  • 2. Excellent GC optimization, custom struct, enumeration transfer between Lua and C# without C# gc alloc;
  • 3. There is no need to generate code under the editor, and the development is lighter;
  • 4. Hotpatch for many C# implementations

4.1 Use of Xlua

4.1.1 Lua file loading

luaenv = new LuaEnv();
luaenv.DoString("print('hello world')");

4.1.2 Load Lua file

            luaenv = new LuaEnv();
            luaenv.DoString("require 'byfile'");

require actually calls the native loaders one by one to load. If one succeeds, it will not try again. If all fail, it will report that the file cannot be found. At present , in addition to the original loader, xLua also adds a loader loaded from Resource (a feature of Xlua, a custom loader) . It should be noted that because Resource only supports limited suffixes, the lua file under Resources must be added with a txt suffix .

The recommended way to load Lua scripts is: the whole program is just one DoString("require 'main'"), and then load other scripts in main.lua (command line execution similar to lua scripts: lua main.lua).

 4.1.3 Custom Loader

When the Loader is running, it will retrieve all the loaders . Here, add a Loader to the Loader list . When all other loaders cannot find "InMemory", this custom loader will work. Detect filename name and return something accordingly.

            luaenv = new LuaEnv();
            luaenv.AddLoader((ref string filename) =>
            {
                if (filename == "InMemory")
                {
                    string script = "return {ccc = 9999}";
                    return System.Text.Encoding.UTF8.GetBytes(script);
                }
                return null;
            });
            luaenv.DoString("print('InMemory.ccc=', require('InMemory').ccc)");

 4.1.4 C# access Lua

This refers to C# actively initiating access to Lua data structures.

1. Global basic data types: (call LuaEnv. Global)

 luaenv.Global.Get<int>("a")
 luaenv.Global.Get<string>("b")
 luaenv.Global.Get<bool>("c")

2. Access a global table:

The above Get method is also used, and the type needs special treatment.

2.1 Mapping to ordinary class or struct: (in fact, the parameters in Get<> fill in XXXClass)

            DClass d = luaenv.Global.Get<DClass>("d");//映射到有对应字段的class,by value
            Debug.Log("_G.d = {f1=" + d.f1 + ", f2=" + d.f2 + "}");

For {f1 = 100, f2 = 100}, a class containing public int f1; public int f2; can be defined. In this way, xLua will help you create a new instance and assign the corresponding fields to it. This process is value copying , and if the class is more complex, the cost will be higher . Moreover, modifying the field value of the class will not be synchronized to the table, and vice versa.

2.2 Mapping to an interface:

This method depends on the generated code (if no code is generated, an InvalidCastException will be thrown), the code generator will generate an instance of this interface , if you get a property, the generated code will get the corresponding table field, if you set the property, it will also set the corresponding field. You can even access lua functions through the interface method. ( This requires the interface to be added to the generated list, otherwise it will return null )

Originally, the interface cannot directly generate an instance, so here it is directly generated.

            ItfD d3 = luaenv.Global.Get<ItfD>("d"); //映射到interface实例,by ref,这个要求interface加到生成列表,否则会返回null,建议用法
            d3.f2 = 1000;
            Debug.Log("_G.d = {f1=" + d3.f1 + ", f2=" + d3.f2 + "}");
            Debug.Log("_G.d:add(1, 2)=" + d3.add(1, 2));

2.3 A more lightweight by value method: mapping to Dictionary<>, List<>

If you don’t want to define class or interface, you can consider using this, provided that the types of key and value in the table are consistent .

            Dictionary<string, double> d1 = luaenv.Global.Get<Dictionary<string, double>>("d");//映射到Dictionary<string, double>,by value
            Debug.Log("_G.d = {f1=" + d1["f1"] + ", f2=" + d1["f2"] + "}, d.Count=" + d1.Count);

2.4 Another by ref method: mapping to LuaTable class

The advantage of this method is that it does not need to generate code, but there are also some problems, such as slowness, which is an order of magnitude slower than method 2, such as no type checking.

            LuaTable d4 = luaenv.Global.Get<LuaTable>("d");//映射到LuaTable,by ref
            Debug.Log("_G.d = {f1=" + d4.Get<int>("f1") + ", f2=" + d4.Get<int>("f2") + "}");

3. Access a global function:

3.1. Mapping to delegate:

This is the recommended way, with much better performance and type safety. The disadvantage is to generate code (if no code is generated, InvalidCastException will be thrown).

        [CSharpCallLua]
        public delegate int FDelegate(int a, string b, out DClass c);
            Action e = luaenv.Global.Get<Action>("e");//映射到一个delgate,要求delegate加到生成列表,否则返回null,建议用法
            e();

            FDelegate f = luaenv.Global.Get<FDelegate>("f");
            DClass d_ret;
            int f_ret = f(100, "John", out d_ret);//lua的多返回值映射:从左往右映射到c#的输出参数,输出参数包括返回值,out参数,ref参数
            Debug.Log("ret.d = {f1=" + d_ret.f1 + ", f2=" + d_ret.f2 + "}, ret=" + f_ret);

 or:

        [CSharpCallLua]
        public delegate Action GetE();
            GetE ret_e = luaenv.Global.Get<GetE>("ret_e");//delegate可以返回更复杂的类型,甚至是另外一个delegate
            e = ret_e();
            e();

 3.2. Mapping to LuaFunction

The advantages and disadvantages of this method are just the opposite of the first one. Poor performance Type unsafe, but no generated code. It is also easy to use. There is a call function with variable parameters on LuaFunction, which can pass any type and any number of parameters, and the return value is an array of objects, corresponding to the multiple return values ​​of lua.

            LuaFunction d_e = luaenv.Global.Get<LuaFunction>("e");
            d_e.Call();

A list of [object, object, object] will be returned, corresponding to the lua function returning multiple values

4. Precautions

4.1 Accessing lua global data, especially table and function, is expensive . It is recommended to do as little as possible. For example, after initializing the lua function to be called once (mapped to the delegate), save it , and then directly call the delegate. . The table is also similar.

4.2 If the implementation part of the lua side is provided in the form of delegate and interface, the user can completely decouple from xLua: a special module is responsible for the initialization of xlua and the mapping of delegate and interface, and then set these delegate and interface to Where to use them.

4.1.5 Lua calls C#

1. new C# object

local newGameObj = CS.UnityEngine.GameObject()

 2. Access C# static properties and methods

Read and write static properties

CS.UnityEngine.Time.deltaTime
CS.UnityEngine.Time.timeScale = 0.5

call static method

CS.UnityEngine.GameObject.Find('helloworld')
//小技巧:如果需要经常访问的类,可以先用局部变量引用后访问,除了减少敲代码的时间,还能提高性能:
local GameObject = CS.UnityEngine.GameObject
GameObject.Find('helloworld')

3. Access C# member properties and methods

Read and write member properties

testobj.DMF
testobj.DMF = 1024

call member method

Note: To call a member method, the object needs to be passed as the first parameter. It is recommended to use colon syntax sugar, as follows

testobj:DMFunc()
//等同于
testobj.DMFunc(testobj)

Input and output attributes of parameters (out, ref)

Parameter processing rules on the Lua call side: C# common parameters count as an input parameter, ref-modified ones count as an input parameter, out does not count, and then correspond to the actual parameter list on the lua call side from left to right;

The return value processing rules on the Lua call side: the return value of the C# function (if any) counts as a return value, out counts as a return value, ref counts as a return value, and then corresponds to lua’s multiple return values ​​from left to right.

		
	public struct Param1
	{
		public int x;
		public string y;
	}

        public double ComplexFunc(Param1 p1, ref int p2, out string p3, Action luafunc, out Action csfunc)
		{
			Debug.Log("P1 = {x=" + p1.x + ",y=" + p1.y + "},p2 = " + p2);
			luafunc();
			p2 = p2 * p1.x;
			p3 = "hello " + p1.y;
			csfunc = () =>
			{
				Debug.Log("csharp callback invoked!");
			};
			return 1.23;
		}
            --复杂方法调用
            local ret, p2, p3, csfunc = testobj:ComplexFunc({x=3, y = 'john'}, 100, function()
               print('i am lua callback')
            end)
            print('ComplexFunc ret:', ret, p2, p3, csfunc)
            csfunc()

4. Automatic conversion of C# complex types and tables

For a C# complex type with no parameter constructor, it can be directly replaced by a table on the Lua side . The table corresponds to the public field of the complex type with corresponding fields, and supports function parameter passing, attribute assignment, etc., for example: Under C# The B structure (class is also supported) is defined as follows:

public struct A
{
    public int a;
}

public struct B
{
    public A b;
    public double c;
}

A class has member functions as follows:

void Foo(B b)

You can call it like this in lua

obj:Foo({b = {a = 100}, c = 200})

5. Get the type (equivalent to typeof in C#)

typeof(CS.UnityEngine.ParticleSystem)

6. "Strong" turn

Lua has no type, so there will be no "forced conversion" of a strongly typed language, but there is something similar: tell xlua to use specified generated code to call an object , under what circumstances can this be used? Sometimes the third-party library exposes an interface or abstract class, and the implementation class is hidden, so we cannot generate code for the implementation class. The implementation class will be recognized by xlua as non-generated code and accessed by reflection . If this call is very frequent, it will still affect performance . At this time, we can add this interface or abstract class to the generated code, and then specify the use This generates code to access:

cast(calc, typeof(CS.Tutorial.Calc))

The above is to use the generated code of CS.Tutorial.Calc to access the calc object.

            //通过反射来调用函数
            local calc = testobj:GetCalc()
            print('assess instance of InnerCalc via reflection', calc:add(1, 2))
            assert(calc.id == 100)

            //把这个interface或者抽象类加到生成代码,然后指定用该生成代码来访问
            cast(calc, typeof(CS.Tutorial.ICalc))
            print('cast to interface ICalc', calc:add(1, 2))
            assert(calc.id == nil)

4.2 Implementation and Principle of Xlua Specific Code

4.2.1 The principle of lua calling c# in Xlua  :

If a C# type is added with the [LuaCallCSharp] tag , xLua will generate the XXXXXWrap.cs adaptation code of this type (including constructing an instance of this type, accessing its member properties, methods, static properties, and methods), and put it on the lua stack with luaAPI in. If the adaptation code is not generated in advance, when the program is running, when lua calls c#, it will use the reflection method with low performance to access, traverse all the c# classes with reflection, and then put them into the lua stack. (reflection is 10000 times slower than normal methods)

And under IL2CPP, it may be inaccessible due to code clipping. IL2CPP is a compiler introduced by Unity to replace the Mono VM.

Initialization process:

( DelegatesGensBridge.cs : Xlua generates this file, which is used to point to the "hotfix hot update, lua replaces the method function of c#."  EnumWrap.cs: traverse all the enumerations, save them in EnumWrap.cs, and then put them in In the lua stack. XXXXXWrap.cs adaptation code : save the method that lua needs to call into the adaptation code, and then put it into the Lua stack.)

The process of lua calling C#: 

 4.2.2 The principle of c# calling lua in Xlua

If C# wants to access functions or tables in Lua, it is necessary to add  the [CSharpCallLua] tag to the corresponding Delegate or Interface in C# . Xlua will generate the corresponding XXXXXBridge.cs file, map the corresponding function method in lua to the corresponding Delegate or Interface in c#, and then call it through luaenv.Global. Although there are other mapping methods, it is best to map functions in Lua through Delegate, and map Table in Lua through Interface.

 4.2.3 Principle of Hotfix in Xlua

After generating the XXXXXWrap.cs adapter code and executing XLua/Hotfix inject in Editor, xLua will use the Mono.Cecil library to inject IL into the Assembly-CSharp.dll assembly under the current project . Since the mobile platform cannot compile C# code into IL intermediate code, most of the hot update solutions will involve IL injection (what do you mean? I can’t understand this sentence, just skip it.), only in this way can the built-in VM of Unity support the hot update code for processing. When xLua performs IL injection, it will create a DelegateBridge variable for all functions of the class marked with the [Hotfix] tag, and add corresponding judgment conditions at the same time. If there is a hotfix code, the Lua hotfix code will be executed, and if there is no hotfix code, the original c# code will be executed.

4.3 Other issues in Xlua

1. What is the principle of luaenv?

luaenv is a Lua virtual machine class in Xlua, which is used to execute lua code or manage Lua stack.

Lua Beginners (4)--Lua call principle display (lua stack ) The usage situation, and the final figure dynamically shows the whole process. Hope to help you. https://blog.csdn.net/zhuzhuyule/article/details/41086745?utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&depth_1-utm_source=distribute.pc_relev ant_t0.none - task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control

2. What is the principle of DoStrnig?

Let the luaenv virtual machine in Xlua execute the code in DoString.

3. What is the principle of custom Loader?

Register the callback of require through LuaEnv.AddLoader and LuaAPI. When calling require in lua code, the parameter will be transparently passed to the callback, and the specified file can be loaded according to this parameter in the callback.

4. What is the class principle of Lua mapping to C#?

By generating the corresponding XXXXXBridge.cs file for each CShapeCallLua, and then operating the specific part of the corresponding lua function through LuaAPI, let the functions in C# correspond to the functions in lua.

5. What is the concept of a code generator?

The Generator.cs class in Xlua can generate specific .cs or .lua or .xml files according to templates, such as LuaClassWrap.tpl.txt.

6. Why is Lua mapped to C#'s LuaTable class an order of magnitude slower than mapping to an interface code generator?

This kind of general and comprehensive LuaTable class must perform reflection operations on Lua methods in order to map Lua, and reflection is very time-consuming. It is better to use the code generator directly to generate XXXXBridge.cs in advance, and fill in the data with LuaAPI directly according to the structure in Bridge.cs, which is much faster.

7 What is the mapping by ref method?

By ref is by reference, which means passing by reference. In the Xlua official source code case, you can directly search by ref to see the case.

8. Why is it expensive to access lua global data, especially table and function?

There are different opinions on the answer to this question on the Internet, and I can't find a good answer in the short term. The problem must be caused by the global and local data structures, and the different configuration methods in the stack. It may be that the global data needs to scan all the stacks, and the local data knows the entry and the size of the data, and only needs to scan a small local part.

9. What is the principle of lua calling CS in C#?

Generate XXXXBridge.cs, and then map it with luaAPI. There are specific instructions in the previous text.

10. Why use local variable reference first and then access, can improve performance?

Because access to global variables is slow, after using local references, access to locals is fast.

11. How is the syntactic sugar colon testobj:DMFunc() implemented?

The colon is a feature of Lua itself, not something unique to Xlua.

1. When defining: Class:test() is equivalent to Class.test(self). To achieve the effect of a colon (:), a period (.) needs to add a self parameter to the first parameter; 2.
Call When: object:test() is equivalent to object.test(object), the dot (.) should add the object itself to the first parameter.

Summary: You can treat the dot (.) as a static method, and the colon (:) as a member method.

12 What are generalization (template) methods? What is Extension methods function encapsulation?

Generalized programming, and templates are a programming concept. Generic programming: Writing generic code that has nothing to do with types is a means of code reuse. Templates are the foundation of generic programming.

Generalized programming and the use of templates_ice_九闻书世的博客-CSDN Blog_Programming generalization In the process of learning, when we write code, we will use some of the same form, the same parameters, but the parameter type and return Some functions with different value types. At the beginning we learned function overloading, but function overloading has the following disadvantages. - For example: the overloaded functions are only of different types, and the code reuse rate is relatively low. As long as a new type appears, the corresponding function needs to be added. The maintainability of the code is relatively low, and one error may cause errors in all overloads. Generic programming: Writing generic code that has nothing to do with types is a means of code reuse. The template is for generic programming... https://blog.csdn.net/weixin_42357849/article/details/105492332  uses the concept of generalized programming to encapsulate the extended functions of Extension methods, which simplifies the realization of extended functions .

13. What is il2cpp?

IL2CPP is a new script post-processing (Scripting Backend) method for Unity, which processes the IL (intermediate language) compiled and output by the .Net platform.

IL2CPP is mainly composed of two parts:

  1. AOT static compilation compiler (il2cpp.exe)
  2. Runtime library (libil2cpp)

Among them, AOT converts IL into C++ source code, and then submits it to the C++ compiler of each platform for compilation to achieve platform compatibility; the runtime library will provide functions such as garbage collection , thread/file acquisition , and internal calls to directly modify the managed data structure. Native generation services and abstractions .

IL2CPP of Unity - Zhihu Author: Luo Peng Background In Unity4.6.1 p5 and later versions, there are two options in PlayerSettings—>Other Settings—>Scripting Backend, mono and il2cpp, which are the two options of Unity script post-processing (Scripting Backend). way. The concept IL2CPP is Unity... https://zhuanlan.zhihu.com/p/141748334

16. c# tags

[CSharpCallLua] This kind of label is actually

An application of attribute in c#

C# Attribute (Attribute) | Cainiao Tutorial C# Attribute (Attribute) Attribute (Attribute) is a declarative label used to convey behavior information of various elements (such as classes, methods, structures, enumerations, components, etc.) in the program at runtime . You can add declarative information to your program by using attributes. A declarative tag is described by placing square brackets ([ ]) in front of the element it applies to. Attributes are used to add metadata such as compiler directives and comments, descriptions, methods, classes, and other information. The .Net framework provides two types of attributes: predefined attributes and custom attributes. Prescribed attributes (Att.. https://www.runoob.com/csharp/csharp-attribute.html

17. When Lua calls c# and uses the reflection method, there may be code clipping under l2cpp. What is this? How does link.xml prevent the code pruning of il2cpp?

What is code stripping?
Instructions on code stripping: Unity - Manual: Managed code stripping

Check the code clipping, and the Unity code clipping tool will analyze the assemblies in the project during construction, find and delete unused codes, and clip the unused codes. For example, a 2D game only uses Sprite, 2D physics components, You can cut out the unused 3D physics code. Using the cropping function can significantly reduce the package size, which is also an important part of Unity game package optimization.

It does seem to be a very powerful and practical function, but there are still many problems. Unity seems to be able to correctly crop the scripts that are automatically packaged into the prefabs and scenes of the apk when building. The scripts on the AssetBundle are not It will be processed, that is to say, if the Prefab is packaged into an AssetBundle, the code on this Prefab may be cut off, resulting in an error and a flashback when running, which is undoubtedly fatal. So Unity provides the setting of clipping level, and tells Unity which codes need to be kept by configuring link.xml.
Unity IL2CPP releases 64 bits, and code clipping Strip Engine Code_Empty as me-CSDN blog_unity code clipping About this aspect I am also I have just come into contact with the problem recently. If there is a misunderstanding, please pass by the judges to enlighten me. Google Play requires that the apk must support 64-bit CPU from August 1, 2019, otherwise it will be removed from the shelf or not allowed. Above. To make apk support ARM64, you need to switch the Scripting Backend from Mono to IL2CPP. Then the problem comes, the package printed through IL2CPP often cannot run normally (flashback, error). The reason is, BuildSettin... https:// blog .csdn.net/final5788/article/details/100183528

18. XLua.GCOptimize, C# enumeration value added this configuration. xLua will generate gc optimized code for this type. The effect is that the transfer of this value type between lua and c# will not generate (C#) gc alloc, and the array access of this type will not generate gc. What does this passage mean?

Passing reference types requires boxing and unboxing to generate gc, while passing value types does not need to generate gc, so xlua generates the XXXbridge.cs template, and copies each field in the struct to an unmanaged memory (Pack) (managed memory is collected by garbage GC) cleanup), and copy out the value of each field (UnPack) from the unmanaged memory, the value type is passed, so no gc is generated.

  XLua official demo5 - Avoid GC analysis of value types between c# and lua For a c# pure value type (the official website refers to a struct that only contains value types, and other structs that only contain value types can be nested) or a c# enumeration value with this configuration, it will make the type transfer between lua and c#. GC alloc is generated, and array access of this type will not generate GC. (In addition to enumerations, complex types that contain no-argument constructors will generate lua tables... https://blog.csdn.net/qq_31915745/article/details/79635076

20. What is luajit?

LuaJIT is an interpreter for Lua code written in C language.

LuaJIT is a Just-In-Time Compiler for the Lua* programming language.

21. How to reproduce the configuration of XLua

Create a new static list directly in /Editor and label it with LuaCallCSharp. The content of typeof(xxx) in it is the function that Lua calls Cs.

22. How to reproduce hot patch operation guide

24. How to reproduce XLua to add and delete third-party lua libraries

Refer to this article and follow suit.

xlua integrates rapidjson_dusty wings-CSDN blog_lua-rapidjson 1. Combine https://blog.csdn.net/wanzhihui0000/article/details/105603317

25. How to reproduce the secondary development guide of the generation engine

Generate link.xml file according to the template

directory Xlua/Src/Editor/LinkXmlGen/LinkXmlGen.cs (feature file) and

Xlua/Src/Editor/LinkXmlGen/LinkXmlGen.tpl.txt (template file)

The ForEachCsList function in the template file is an ordinary lua function written in the TemplateCommon.lua.txt file.

The lua code in the middle of <%XXXXX%> will be executed directly. The rest are directly printed

 

 

 

Click Generate link.xml. 

26. Due to the limitation of ios, our lua virtual machine cannot load the dynamic library, but compile it directly into the process. What is lua virtual machine? What is loading a dynamic library? What is compiled into the process header?

Virtual machine: A program used to simulate the operation of a computer. It is an intermediate layer, which is a program between the scripting language and the hardware.

 VM means virtual machine. luaenv is a Lua virtual machine class in Xlua.

Static library features (linux):

The name ends with *.o.
The static library is directly added to the executable file during the linking phase. During the execution process, there is no need for the static library to
generate files relative to the dynamic library. Use the files generated by the static library to link the generated executable Features of large
dynamic libraries with large execution files (linux)

In terms of naming, the *.so
object file only indicates the dynamic library to be linked in the linking phase, and the dynamic library and the object file remain independent. The dynamic library is needed during the execution process. The
target file generated by using the dynamic library is relatively small.
For common source code files in the project, such as multiple processes using the source code of the same module, it is best to make it into a dynamic library to save the system. space. At the same time, if there is a bug in the dynamic library, you only need to regenerate a dynamic library and replace the previous one. No need to recompile other modules.
Dynamic library_xiaoxiongxiongshi's blog-CSDN blog_Dynamic library summary one: Dynamic library preface We know that program compilation links often use dynamic, and we may also know that dynamic libraries are loaded when the program is running. But what is the function of the dynamic library, how to generate it, how to load it, etc., we rarely pay attention to it. Next, I will give you a brief introduction. 1.1 The difference between dynamic library and static library Static library features (linux): The name ends with *.o The static library is directly added to the executable file during the linking stage, and there is no need for the static library to be compared with the dynamic library during execution. The files generated by the library are generated using the static library... https://blog.csdn.net/xiaoxiongxiongshi/article/details/104520188 Directly compiled into the process: use the JIT instant compiler to compile directly into the process.

27. What is the difference between AOT and JIT?

At present, there are two main running modes of the program: static compilation and dynamic interpretation.

  • Statically compiled programs are all translated into machine code before execution. This type is usually called AOT (Ahead of time) or "compiled in advance". Typical representatives are applications developed with C/C++, which must be compiled before execution. into machine code
  • The interpretation and execution is executed sentence by sentence while translating and running. This type is usually called JIT (Just-in-time) or "just-in-time compilation", and there are many representatives, such as JavaScript, python

IOS does not allow JIT, so the DLL cannot be updated directly, so the Mono.Cecil library must be used to inject IL into the Assembly-CSharp.dll assembly under the current project. The intermediate code IL is then compiled into machine code by the CLR (similar to JVM) in the .NET platform to let the CPU execute related instructions.

28. What is Assembly-CSharp.dll assembly?

The cs code in the project will be typed into Assembly-CSharp.dll when it is packaged, and called by Mono.

29. What is the Mono.Cecil library for?

Mono.Cecil : A .NET framework that can load and browse existing assemblies and dynamically modify and save them

What is 30 IL?

The full name of IL is the abbreviation of Intermediate Language (IL), which converts .NET code into machine language. To a certain extent, we can understand it as a pseudo-assembly language. When we use C#, VB.NET, F# and other languages ​​in the .NET framework, the compilation process does not directly compile native code like C/C++, but compiles it into IL intermediate language. Through the way of IL intermediate language, many advantages such as cross-platform and improved program flexibility can be realized.

 31. What is the CLR, and what is the JVM?

The common language runtime (CLR) is the engine in the core of managed code execution. The runtime provides various services for managed code, such as cross-language integration, code access security , object lifetime management, debugging, and profiling support. It is the core of the entire .NET framework, which provides a managed code execution environment for .NET applications. It is actually a piece of proxy code that resides in memory and is responsible for the code management of the application throughout its execution.

Common Language Runtime_Baidu Encyclopedia The common language runtime (CLR) is the engine in the core of managed code execution. The runtime provides various services for managed code, such as cross-language integration, code access security, object lifetime management, debugging, and profiling support. It is the core of the entire .NET framework, which provides a managed code execution environment for .NET applications. It is actually a piece of proxy code that resides in memory and is responsible for the code management of the application throughout its execution. https://baike.baidu.com/item/%E5%85%AC%E5%85%B1%E8%AF%AD%E8%A8%80%E8%BF%90%E8%A1%8C%E5 %BA%93/2882128?fromtitle=CLR&fromid=10567215&fr=aladdin JVM isthe abbreviation of Java Virtual Machine ( Java Virtual Machine ) .

5. ILRuntime source code implementation

5.1 Principle of ILRuntime

( Runtime runtime refers to the state that a program is running (cc or being executed))

ILRuntime uses the Mono.Cecil library to read the PE information of the DLL (the Mono.Cecil library can also perform IL injection), and all the information of the type, and finally obtains the IL assembly code of the method, and then executes the virtual machine through the built-in IL interpretation to execute the code in the DLL.

 ILRuntime hot update process:

The main limitations of ILRuntime :

6. Key points, important nodes, and intractable disease scenarios of hot update

6.1 Why is Xlua performing worse?

Lua calls the CS code, and the code in XXXWrap.cs needs to be passed to the lua stack. If unity calls the native interface, there is no such step.

6.2 Several advantages of Xlua

1. The hot update solution corresponding to the lua hot update plug-in with the most users and the best performance.

2. xLua is an open-source hot-updating plug-in by Tencent. It is endorsed by a major manufacturer and maintained by full-time personnel. The stability and sustainability of the plug-in are strong

6.3 What does the DLL compiled by Net 4.6 mean?

How to compile and generate dll_Li Qingfeng's Column-CSDN Blog_Compiling dll dynamic link library is the cornerstone of Windows. All Win32 API functions are contained in the DLL. The 3 most important DLLs are KERNEL32.DLL, which consists of functions for managing memory, processes, and threads; USER32.DLL, which consists of functions for performing user interface tasks such as creating windows and sending messages; GDI32.DLL, It consists of functions for drawing and displaying text. Here, we mainly use the actual operation process to briefly explain how to create our own Win32 DLL. 1. Create a DLL project https://blog.csdn.net/qianchenglenger/article/details/21599235

6.4 What is the cross-domain call made by CLR binding?

This specifically refers to the cross-domain call problem between the main dll and the hot update dll in the ILRuntime solution.

Unity C# hot update program ILRuntime study notes (2) code cross-domain call https://segmentfault.com/a/1190000023290547

6.5 What is cross-domain inheritance?

Ditto for the answer above.

6.6  What is IL runtime?

6.7 The hardware environment that does not support JIT (such as iOS), why does IOS not support JIT?

IOS does not allow JIT, so the DLL cannot be updated directly, so the Mono.Cecil library must be used to inject IL into the Assembly-CSharp.dll assembly under the current project. The intermediate code IL is then compiled into machine code by the CLR (similar to JVM) in the .NET platform to let the CPU execute related instructions.

 I don't know why IOS doesn't support JIT. But the latest IOS14.2 supports JIT mode again, is it possible? In the future, DLL-based hot updates...can be used again? Wouldn't Xlua be eliminated?

6.8 How can my DLL get the reference of the UnityEngine namespace class?

Unity uses C# reflection to obtain the classes in the dll, call the fields and methods in the class Reflection is an important mechanism in .NET. Through reflection, members and member information of each type (including classes, structures, delegates, interfaces, and enumerations) in a program or assembly can be obtained at runtime. With reflection, you can know each type like the palm of your hand. In addition, I can create objects directly, even if the type of this object is not known at compile time. 2. The use of reflection Usually, our way of writing is to refer to the namespace (dll) first, and then create an object, and call the fields or methods in it through this object. Through reflection, we can achieve the effect without adding the dll. 1. First, we create a Testdll class packaged dll in C#, the content is as follows using Sy. https://blog.csdn.net/qq_42345116/article/details/121695595 to reflect the classes in assembly-csharp.dll.

6.9 How should my DLL be packaged into an AssetBundle?

How resources are packaged, it will be packaged.

6.10 How does the program download AssetBundle read the DLL inside?

Call the corresponding method of JIT. Reflect heat more down classes in the .dll.

6.11 How to test the performance of each hot update scheme

Unity Profiler performance analysis full analysis_Tokyo_2024 blog-CSDN blog_unityprofiler Profiler overview Open Unity Profiler1. Window->Analysis->Profiler. https://blog.csdn.net/Tokyo_2024/article/details/105388523

6. References

xlua extended third-party library records

How to evaluate Tencent's xLua (open source) hot update solution under Unity?

Unity game uses XLua's HotFix to realize the principle of hot update

Tencent open source mobile game hot update solution, Lua programming under Unity3D

[Unity] Lua patch solution based on IL code injection

Alternative Unity Hot Update Dafa: Code Injection Patch Hot Update

Unity dll realizes hot update_baidu_28955655's blog-CSDN blog_unity hot update

The realization principle of ILRuntime — ILRuntime

In-depth understanding of the principle of xLua thermal update-Steel and Iron- Blog Park

Guess you like

Origin blog.csdn.net/u013617851/article/details/122493881