ILRuntime to realize the advantages and disadvantages of hot update!

Hot update

Q1: How feasible is it to use ILRuntime to implement hot updates? Have you shared any experience?

Generally hot updates are divided into two parts, code + resources, and resource hots are almost all done through AssetBundle. Code hots can be done with some kind of interpreter + interpreter execution language. The choices are Lua, as3, python, js, C#, etc. As far as I know, the mainstream is Lua, and the sub-mainstream is C#.

In terms of hot update selection, all the code of our project was written in C# initially, and hot update was not considered. Because no one on the team knows Unity3D, it's all learning while doing, and "making it out" is the first priority. After going online, it is naturally unable to withstand the pressure of operation: in the case of many Android channels in China, this demand for operation is reasonable, otherwise it will be very difficult for each channel to review and synchronize the time of the launch every time the version is updated.

Then we first use XLua to patch and fix the bug: the cost is the lowest. Later, the operation requires that it can be more functional through heat, rather than just changing the bug. Then, either use Lua to write all the code that may be hot updated, which requires a large amount of existing C# code is translated; or find a way to make C# hot update. So it is natural to choose the latter + ILRuntime.

The final technical solution is this:

1. Basic restrictions.
Some of the codes don’t inherit MonoBehaviour, that is, they don’t have scripts. Non-hot parts are free: Regent supports MonoBehaviour and other special things. It’s very troublesome. Either you don’t need it, or it’s just a no-brainer. Hot message forwarding layer; either hang the script during development and use a special way to turn it into a dynamic AddComponent in the code during packaging.

2. Android
does not need any third-party hot change program, uses C# reflection to execute DLL, performance and code writing are basically the same as pure C#.
Google Pay mandates that all apps support 64-bit before August 2019. Unity’s solution is Android IL2cpp, and there is no plan to support mono backend 64-bit for the time being. Therefore, it can only be IL2CPP + ILRuntime, and the performance will be a lot worse, mainly due to ILRuntime.

3.
Interpretation and execution of iOS ILRuntime + DLL, of course, under IL2CPP.

4. Advantages The
language (C#)\development environment\tool chain is unified, and it can become a form that does not support hot update at any time, if Apple does not allow any way of interpretation and execution in the future.

After the framework is built, some restrictions are met (non-hard restrictions, mainly to avoid trouble, the restriction is mainly one, the hot-changeable part of the code should not inherit the non-hot-changeable code, and the non-inheriting MonoBehaviour is a subset of this restriction), The development method of students who write logic is exactly the same as that of native C# development, including debugging.

Third-party plug-ins are directly available (most plug-ins are written based on C#).

5. Disadvantages
There are still some pitfalls in stability: usually occur in some relatively high-level language feature combinations, especially various reflection codes. In addition, the current version supported by .net4.6's async\wait should not be stable enough. The pure computing performance is weaker than Lua, and the computationally intensive code should be placed in the non-hot update part.

The history is short, Git contributors are few, and project tests are few (as far as I know, commercial projects on the line are between x-1x, and specific projects include MMO, SLG, leisure, and chess and cards). In principle, there is no big room for optimization. There is still some small optimization space; in addition, there are few frameworks that integrate various common features.


Make

Q2: We know that the Cube built by Unity has 24 vertices instead of 8. We built a Cube in Max and converted it to Polygon without any UV processing. We hope that the number of vertices exported can be controlled (can be 8), but we found that the number of FBX vertices exported by default must be 24. Why? How to precisely control its number?

UWA: This question mainly depends on whether the vertices of adjacent faces can share normal lines in the model. If it can, then only one vertex is needed to represent it; if not, it needs to be divided into two vertices (the position is the same but the normal is different). And "whether normal lines can be shared" can be controlled by the smoothing group in Max, and by Smoothing Angle in Unity (similar to the common rule when the angle between adjacent faces is less than how much).

Therefore, the subject can try to add a smoothing group to Max and export it; or after importing into Unity, set the Normal item to Calculate and control it through the Smoothing Angle. In order to better illustrate the influence of whether to merge normals on the lighting effect, the left picture shows the Smoothing Angle is 0 (basically no normals are merged, the number of vertices is the most, 7676), the right picture is 1 (the maximum merged normals, the number of vertices The minimum is 3260).


Make

Q3: How do you realize the alternate day and night method in mobile games? I considered loading the Lightmap dynamically, but the transition of the gradual changes would appear abrupt. If it is real-time light, the performance pressure is relatively high. What ideas do you have for the implementation of day and night on the mobile terminal? Many thanks!

Art bake two or more Lightmaps, then dynamically blend the two Lightmaps through RenderToTexture when the game is running, and then use the result. After the blending is completed, switch to the official Lightmap, and the transitional Lightmap can be lost.

It may be necessary to note that the encoding format of Lightmap needs to be decoded before mixing, and then encoded back after mixing. In short, there are some errors after the compression format is mixed under the mobile platform, but it is acceptable.

There is a copycat approach, that is, the art has to bake two sets of day and night (if there are multiple natural environments, you can bake multiple sets).

1) Dynamically load the light map used in the next natural environment as a global map;

2) Use time to make a coefficient. When the light map is decoded, just interpolate the current light map and the light map loaded in Part 1. (Convert from day to night), the place of decoding is in the function UnityGlobalIllumination;

3) Use time to make a coefficient, and adjust the ambient light appropriately.

The premise of this is that the number of lightmaps in your scene is relatively small, otherwise it will be more embarrassing.

Our project also did a day and night system, which was not done by me. I invited the corresponding colleagues to answer. I don’t know if I have time. Let me start with a few thoughts.

We did not adopt the idea of ​​two sets of light maps. The advantages and disadvantages are obvious: the advantage is that multiple sets of light maps can do better results. Point light sources, GI, and AO are all possible, but the disadvantage is that the package body will occupy a larger amount and excessive The gradient is a bit troublesome. If it’s an ARPG, it’s more appropriate to switch scenes. If players in the big world have been in the same scene, it may be a little more troublesome.

Most of the scenes we originally designed were field scenes, and the demand for changes in point light sources was very small. Therefore, the idea of ​​the day and night system did not choose multiple sets of Lightmap solutions, but used the solution of modifying the material parameters.

1) The first version uses lut, and the gradient is made with the transition difference between the two lut textures. The consumption is basically OK, but because it is a full-screen post-processing, there is no HDR, and the special effects will also be darkened. , The art is not satisfied after a period of trial;

2) The second version is based on the idea of ​​material parameters. The art baking is the effect of the day, and the result obtained in the PS at night is multiplied by a color value. The shader of the scene and the character must be processed, and the material of the special effect Without processing, the overall darkening effect can be achieved. The basic effect is not good, but it can meet the needs of basic mobile devices, and the performance is acceptable.

3) The sky box, directional light brightness, ambient light, and character reflection Cube are switched to follow day and night, which mainly affects the character.

4) At night, adjust the intensity of the self-luminous parts of building windows and lanterns, which can show a better effect of night lights.

The idea is different from the idea of ​​switching lightmaps. For your reference, the runtime consumption is a bit larger than the idea of ​​switching lightmaps. The advantage is that it saves art work and enough, saves some packages, and it is easier to do too much, which is convenient for dusk, This kind of effect in the morning, but the effect is not the best, basically enough for mobile games. There may be many details that I don’t understand. Looking back, colleagues have time to add.


Resource management

Q4: Is the AssetBundle Diff Patch solution feasible? My original update plan was to compare the hash value of the AssetBundle file and directly replace the entire AssetBundle and manifest to achieve the update effect. I don’t know if there is any other plan similar to Diff patch, which can reduce the update package body. If you can do Diff patch, resources Whether the granularity can be ignored.

There are currently no mature solutions for direct Diff update based on AssetBundle, but only some of the resources in the complete Resources library have been selected and updated. Two projects have been made. The idea is actually very simple:

1) When the whole package is released, use ScriptableObject to record the MD5 codes of all released resources in the AssetsDataBase (unity's own hash code can not be used);

2) Use the tool to call up which assets are dynamically loaded in the code and divide them into a Resource package; find out the dependent resources of these resources, divide them into a Share package, and record the AssetBundle package to which each asset belongs;

3) When the patch is released, compare which dynamic Load resources in the current AssetsDataBase have been added and changed (deleted can be ignored), including the resources they depend on. Still put the resources of the dynamic Load in the code into ResPatch, and put the dependencies into SharePatch. For resources that have not changed, the original AssetBundle name is still maintained;

4) After recording the patch, update the AssetBundle package to which each Asset belongs;

5) The Resource and Share of the next patch may depend on the Share of the previous patch;

6) At runtime, a dictionary index is established for all the Res entered by the patch. When loading, firstly determine whether the Asset is in the Res package of the patch. If it is, read the AssetBundle package of the patch and process the dependent packages according to the routine. Otherwise, use the built-in binary package.

The advantages of this approach are:
1) Use the released resources in the version to reduce the size of the patch package;

2) The packaging rules of the patch package can almost ignore the sub-package rules of the complete package, which is convenient for subsequent toss.

Of course the disadvantages are also obvious:
1) Is the big bag in the complete bag really good? If all resources are grouped into one AssetBundle, it is no different from using the Resources directory. This is officially prevented by Unity. After the actual measurement, a 300MB Res package was opened, and iOS allocated nearly 40MB of memory... (In fact, this problem is not contradictory to the Diff update. Now the resources in our binary package are also relatively small, but the patch can still use the above rules ).

2) Tools, tools, development and maintenance resources MD5 database, patch generation rule packager, it took 5 days and 5 nights to get it right;

3) It is also the most deadly problem. For Assets that are dependent on a lot of resources, once they change, a bunch of resources that lie guns will be found in the update package, such as UIAtlas-related things, Shader family, fonts, etc...

For question 3, it is almost necessary to use the idea of ​​replacing the entire package, pick out these changeable Assets, and package them separately. All subsequent Res and Shared all rely on them. If one of them changes, the entire base AssetBundle package will be overwritten and updated, and the Res that depend on them will not be considered as changed.

In fact, I have been entangled as to which one is better, the difference update or the whole package replacement. At the beginning, the main reason for the difference update was that the code in the project was not processed properly with asynchronous processing, and the AssetBundle package of small frequently loaded was very stuck, so I made a large package and was forced to use the Diff solution.

In addition, regardless of the packaging scheme, you must control the amount of redundant resources in the AssetBundle package [no matter whether it is a large package or a Diff package, it can be resolved], my bottom line is within 2% of the actual capacity. At this point, UWA's online AssetBundle package detection tool can help a lot, thank you!

I'm here to persuade you to retire. The whole package of Diff, Flashyiyi wrote a scheme based on bsdiff
https://zhuanlan.zhihu.com/p/31810166

I used bsdiff to update the CPP in the Cocos2d era. It is really effective to reduce the size of the so, but why should I dissuade it?

1. Difficult to maintain.
Diff is to accurately generate the difference between two files, which requires that every patch must accurately match the previous version and the next version, and in the case of multiple versions, there is a strict linear relationship: it must be patched one by one. Install and merge in order. And this strictly linear relationship is a fatal flaw.

When there are many versions, if one version in the middle is missing, or there is a problem with a patch in the middle, there will be a problem in the entire update chain. Reliable systems still need to consider error conditions.

2.
The routine of merging patches requires careful replacement of files. It seems that the patch will be large, but it is natural that the repeated changes of multiple versions of the patch are automatically merged, so the total number of downloads is not seen when the old players or the apk is updated to the latest version It would be very exaggerated.

But the Diff solution is very troublesome. Although Diff merge can be performed, first of all, you cannot easily delete the patch before the merge if you merge it, otherwise players who update to the intermediate version will not have the patch available. You have to make a very rigorous judgment to skip merged patches. A reliable production process is also needed to prevent problems with merged patches.

3. Playing a large AssetBundle will result in slow
merging. This is because you have to merge them one by one in order. In contrast, Yunfeng has written a solution (Blog, not source code) that unpacks the Bundle and then assembles it at runtime. Zulong’s Six Dragons Contend for Hegemony is also this plan. And they are not playing a big Bundle, but a precise replacement in a small Bundle. This is not so dependent on the exact consistency of the version, and the update package can also be very small.

But it brings a new problem: once the official format is changed, the code must also be changed. The official format is not open source, but cracked by itself (you can refer to open source solutions such as Unity Extractor), and the difficulty you follow is obvious.

So, if you don’t really care about the size of the update, it’s actually a good idea to replace the file... Anyway, we are using it. Nowadays, the games of major manufacturers are often dozens of MB patches.


other

Q5: The latest product launched by our team is Unity 4.6, and the latest project is being planned, and it is still an MMO product. I would like to ask how much it is necessary to upgrade to Unity 5. Because after the Demo cut to 5, there were some time-consuming problems to solve, we are worried that there will be more pitfalls in the follow-up. I think the main new features of Unity 5 that I know about are: the optimization of AssetBundle packaging, the separation of particles from the main thread, the PBR rendering method, etc., but these things don't have much impact on us for the time being.

UWA: If it is a new project, then it is necessary to upgrade Unity 5. In terms of new features, it is recommended to go directly to the introduction of Unity 5, there are many online. Talk about several important aspects of performance improvement:

1) Higher loading efficiency. Even with the same LZMA compression and packaging, the loading of AssetBundles with the same content before Unity 5.3 is also faster (5%~15%). In addition, for the new LZ4 AB after Unity 5.3, the loading speed is faster than before. Of course, Unity 2017 loads ms faster. We will summarize and share on UWA Day 2018;

2) AssetBundle loading memory occupies smaller. After Unity 5.3 there is no Webstream, a great blessing. But you need to pay attention to the "pit" of 0.5MB SerializedFile before version 5.4.5 and 5.5.4;

3) In addition to the particle system mentioned in the subject, the animation module is also multi-threaded for processing, and the efficiency is significantly improved (although sometimes the troublesome problem of the main thread waiting for the sub-threads occurs, in general, the advantages outweigh the disadvantages);

4) UGUI tends to be improved after Unity 5.2 version, and multi-threaded processing has been added. In our trend analysis, UGUI has a very clear trend of catching up with NGUI in terms of performance and maturity;

5) After the Unity 5.4 version, the physics can be stripped according to the physical usage of the project, so as to avoid the embarrassing problem of constantly idling before.

In addition to the above, there are many performance improvements. It can be said that the performance improvement of Unity 5 is still in many aspects. It is recommended to upgrade. Finally, Unity 4 is no longer maintained. What if there is a compatibility problem with a device or system in the future?

Guess you like

Origin blog.csdn.net/mango9126/article/details/114131829