0/ 39/ /0

This time we will share several technical topics which are related to Program development. It is recommended to read for 15 minutes. Any unique insights or discoveries, please feel free to contact us or discuss.



Q1: The bloom effect of PostProcessing V2 is displayed abnormally on the phone.

There are illegal values here, it is recommended to use the built-in NaN function to check it, most of them are caused by special effects or GBR and Spec in PBR divided by 0.


PS: The NaN function means that on the layer script of Porcine parvovirus 2 (PPV2), there is an option to view NaN pixels. In fact, it’s possible that Spec values are too large. You can limit it yourself and use max function.

Thanks to Pang Chihai for providing the answer above.

We meet the same problem in the project, we use HDR and then some shaders will have this problem.


The solution is to first set the clamp of bloom to a relatively small value, 2 or less is recommended. If there is still a problem, check which shader has the specific problem, and change both fix and half to float, which can solve most problems.

Thanks to BQ哥 for providing the answer above.

I check the NaN and find that there are black spots. Later I know that it is the problem of Shader in PBR.

Thanks to lyd for providing the answer above.


Q2: We use xLua in the project, then I find a problem: a UI is opened, destroyed, reopened, then destroyed …, so many times, Mono will continue to grow, and it cannot be completely GC with C # GC.


Then there is a phenomenon where Mono will decrease:


Lua carry out GC, then C # carry out GC, Mono will drop back a little (but not back to the original). The problem should be that both of them use reference counting to recycle, and the two are not synchronized. Although the object is destroyed, GC is not performed in Lua, then some of the objects referenced by Lua are still being referenced.


Then perform GC several times on both sides, it can basically return to the original Mono value.


I see some similar problems about ToLua:


There are several proposals in the article, and then I make two adjustments:


A. Try increasing the Lua GC frequency slightly,


B. xLua itself also provides the LuaEnv.Tick () function to delete the reference (slowly traversal detection to see if the referenced C # object is destroyed, set it to null if it has been destroyed, the reference can be removed, then it can perform GC completely later) , and to increase the number of each traversal.


But there is still growth. I don’t know how to solve this kind of problem?

(Is it better to use the UI as a buffer pool? But there is still a certain probability that there will be problems and Mono will increase.)


PS: There is still a problem. It is difficult to know what caused the leakage in Lua and C #. Some simple operations must be repeated in a short period of time to guess where is the cause, and then find the problem in the corresponding place. Is there any bette way to locate C # is applied to which Lua? Or which is referred by C # in Lua?


For example, there are some two-way references and they cannot perform GC, so I can only guess where the references are.

Your understanding of Lua and C # memory is very deep, and we have similar problems. But we only did the first processing:


Adjust two parameters of Lua GC to make Lua garbage collection more active. The reason for this problem is that Lua cannot perceive the weight of what a User data represents in the C #. Since the basics are wrong, it can only accelerate the frequency. This is a simple but effective method, the cost is not great as long as the parameters are reasonable.


We should also have the problem of the increase of Mono, but we haven’t carefully understood this. At present, the peak value of Mono is 20MB, which is acceptable under normal operation.


Regarding the reference of C # by Lua, Lua only takes an index. The real holding of objects is achieved through ObjectPool. Next, there are two steps for ObjectPool:


1. Record the call stack


The C # stack can be obtained through StackTraceUtility.ExtractStackTrace ();

The Lua stack can be obtained through DoString (“return debug.traceback ()”);


You can record these two strings together with obj in ObjectPool, so that as long as you know which obj has leakage, you will also know where it is introduced.


2. Record the allocation number


In order to check which obj has leakage, we can give obj an allocation number when it enters the pool. This allocation number increases automatically, and then we can manage diff.


For example, when you make point A at a certain moment, the allocation number at this time is 100, and at another moment, you make point B and the allocation number is 150, then release a variety of GCs to traverse the pool to find obj between 100 and 150. Analyze whether the survival of this part of obj is as expected, and print the two stacks if it is not as expected. The method is clear.


Regarding C # being referenced by Lua, this part does not seem to be the hardest area. We encapsulate LuaBehaviour for external use and control it when it should be destroyed. In addition, Delegate should also be well controlled.

Thanks to littlesome for providing the answer above.


Q3: As shown in the picture, the current memory usage is 843MB, but the memory usage will drop to 150MB after a period of inactivity. The only function is browsing, and the fluency when occupying 800MB is exactly the same as that when occupying 150MB. Why?

I have been doing WebGL for a while, but I don’t meet the problem you mentioned. At that time, the main debugging browser we used was Chrome.


Browsers generally carry developer tools and can have performance analysis to view memory usage. Take Chrome as an example:

You can check the memory occupied by the games we released, and you can also view the proportion of each part of the memory allocation. I haven’t met this problem, so I can only briefly talk about my idea, but I’m not sure if it is useful for you.


First of all, I think that you need to publish it on other browsers to see if it is a common problem.


If it is a common problem, you should find a browser with the most complete analysis tool to see where the memory is allocated and what memory is released when the memory drops, so that the problem can be located.


If it only appears in the Firefox browser, you must first check whether it is a support problem of the browser, or the game itself has problems (some browsers do not directly support it, some browsers have support problems), here you should check whether the game step on the trap of this browser, you can publish a simple game to see if it also has a problem. If it exists, change the Unity version and then publish the test; if in a simple scene, such as an empty project, this problem still exists, then basically it’s a problem of the browser support. If not, use a tool to analyze the memory and locate the problem, try bypassing this trap.

Thanks to 赵林_JS for providing the answer above.


Q4: In FPS games, besides using Rigidbody for bullets, is there any other more efficient solution to simulate the trajectory under gravity? For example, using Raycast, what are the main points of implementation?

I am very interested in FPS. I have a little understanding of bullet implementation, so I provide a pseudo-code based on Raycast for your reference.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
    public float Speed;   // speed of bullet
    public Vector3 Gravity; // Gravity vector
    Vector3 _PrePos;  // Keep old position to calculate ray direction
    Vector3 _NewPos;  // new location of bullet

    void FixedUpdated(){

        _NewPos += Speed * transform.forward * Time.deltaTime;  // 速度对坐标的修改
        _NewPos += Gravity;  // Modification of coordinates by gravity

        var direction = _NewPos - _PrePos;
        var distance = direction.magnitude;

        if( Physics.Raycast(_PrePos, direction, distance) ) {
            // dosomething();
        else {
            _PrePos = transform.position;
            transform.position = _NewPos;  // If no target is detected, move the bullet to a new location

Thanks to Zhang Rui for providing the answer above.


Q5: I want to optimize UGUI rendering, but here is a problem. For example, the Scrollview of an interface has many items. When the Z of the root node of UI is 0, it will be batched. When Z is not 0, Item will be drawn one by one without batch processing. I hope that you can tell me what should be done to deal with this situation?

“When the Z value of Position of the UI element is not 0, it will be regarded as 3D UI which will not participate in the batch. The parent node Z! = 0, then the following elements cannot be batched.”

Thanks to Jia Weihao for providing the answer above.

This is the 61th UWA Technology Sharing for Unity Development. As we all know, Our life has a limit but knowledge has none. These problems are only the tip of the iceberg and there are more technical problems during our program development which deserve to discuss. Welcome to join UWA Q&A community, let‘s explore and share knowledge together!




Post a Reply