circle-loader
0
by
0/ 90/ /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.

UWA Q&A Community:answer.uwa4d.com


DrawCall

Q1: I am making a Voxel game. Currently, in the game: all models share the same Material, each model part (monster) is a separate Mesh, the animation made by Animator has no skeletons, it is the key frame animation, and the GPU Instance has been turned on.

 

I have this problem:

 

For example, if a character has more than 10 parts, and 10 types of monsters appear on the map at the same time, the DrawCall of the model part will rise to 100+. Due to the fact that there are not many special effects added, there is no lag when testing on the real machine (Mi8 Lite), and the GPU Instance is opened, and it work well in the case of a small number of types but a large quantity.

 

But I still want to ask you about the increase of DrawCall. Is there any good optimization method? Or is it necessary to optimize? 

Doing Culling + manually calling DrawMeshInstanced by yourself (if direct material check instance, it will not be combined) can reduce many DrawCalls of parts.

 

If the accuracy of animation is not high and you are willing to change time in space, bake out the entire model according to frame animation. With DrawMeshInstanced, several DrawCalls can be reduced of some parts.

 

Using LWRP/HDRP has an advantage. Turn on SRP batcher. Do not check “enable instance” for the material. If you use the built-in Shader, you can directly see the DrawCall decrease. Besides, it is not difficult to rewrite the customized Shader.

Thanks to Nil for providing the answer above.


Animation

Q2: Is there any good way to optimize the memory usage of animation? In addition to common operations such as reducing accuracy, compression, and removing Scale, is it feasible to reduce the frame Rate?

I can add something about frame Rate:

 

After importing the animation to Unity, change the frame Rate during playback (by controlling the speed of animation, the frame rate of animation clip cannot be changed after importing Unity actually), then the change of frame Rate will not affect the memory;

 

However, if you mean that modify the frame rate in animation software (such as 3ds Max, Maya), then the memory will indeed be affected after it is imported into Unity. At this time, if two animations are consistent, but just the simple frame rate is different:

 

1. When animation compression is not turned on, the clips with a large number of key frames (usually the frame rate is high) will have a larger memory, and there are several influencing factors:

a. Turn on resample curves during import (this option decides whether Unity automatically inserts frames when importing, which will make all curves full during the playback time), then the memory with a high frame rate will be much higher;

b. If you do not open resample, the memory with a high frame rate will be a bit higher.

 

2. When animation compression is turned on, such as Keyframe Reduction, the memory of different frame rates becomes similar again (because the animation is consistent, the actual animation curve is also similar, then some duplicate data will also be compressed during compression).

 

The conclusion is that when the animation compression option is turned on, the frame Rate when making animations has little effect on memory, so there is no need to specifically optimize the frame Rate.

This answer is provided by UWA

We can simulate some linear animations to reduce the amount of data of animation key frames, such as the commonly used iTween, DOTween plug-in, and XTween recommended by UWA.

Thanks to Zheng Xiao for providing the answer above.


Rendering

Q3: Using the Metal API on iPhone, and turning on MSAA, inserting any CommandBuffer after rendering opaque objects but before transparent objects (such as AfterForwardOpaque) , it will make objects at the front of rendering in the transparent queue appear to have no ZTest.

 

Note: There is no problem on OpenGL ES3.0, and no problem on Android platform.

 

I write a reproducible demo and built it to run on iPhone. Open MSAA and CommandBuffer at the same time and you will find that two red cubes are always in front of the tree. But It will be no problem to close one of them.

 

Attach this Demo: MASSDemo.zip

Insert CommandBuffer after rendering transparent objects and before opaque objects. Write the depth mapping of Unity into DepthBuffer of the current FrameBuffer in this Cube, then this problem can be solved.

Thanks to 贤 for providing the answer above.


Script

Q4: I want to know if Unity has any callbacks when errors occur in compiling script? Or is there any Trick can be used?

Try this:

public class CompilePostProcesser : AssetPostprocessor
{
static CompilePostProcesser() { EditorApplication.update += Update; }
// Callback after all compilations[Be careful to cause recursion, that is, operations in callbacks cause recompilation]
// If compilation error occurs, this callback will not be executed
[UnityEditor.Callbacks.DidReloadScripts]
private static void OnCompiled()
{
// Debug.ClearDeveloperConsole();
Debug.LogError(“successful compilation!”);
SuccsccAction?.Invoke();
}
private static void Update()
{
if (EditorUtility.scriptCompilationFailed)
{
EditorApplication.update -= Update;
Debug.LogError(“Compilation failed!”);
FailAction?.Invoke();
}
}
}

Thanks to kaclok for providing the answer above.

There is a Trick available, but it is relatively old. The idea is to try clearing the log. Compilation errors cannot be cleared, so you can distinguish whether there is a compilation error.

static void ClearLog()
     {
         Assembly assembly = Assembly.GetAssembly(typeof(SceneView));
         Type logEntries = assembly.GetType("UnityEditorInternal.LogEntries");
         logEntries.GetMethod("Clear").Invoke (new object (), null);

         int count = (int)logEntries.GetMethod("GetCount").Invoke(new object (), null);

         if (count > 0)
             throw new Exception("Cannot build because you have compile errors!");
     }

Thanks to Zhang Rui for providing the answer above.


UI

Q5: In Unity 5.6.6 version, we use UGUI to pack atlas, there is enough space for pictures of 512×512 size, the size of each picture is 101×101, bu 17 pictures are made into an atlas with the size of 512×1024.

The picture for testing:

There is Padding, one pixel on each side, so the size of 101 will become 103, then 512 is insufficient.

Thanks to lopezycj for providing the answer above.

Sprite atlas has an attribute “Padding”, the minimum is 2 pixels, the default is 4 pixels.

 

Taking 2 pixels as an example, the atlas above has a height of 512, and the height of the four textures is: 2 + 101 + 2 + 101 + 2 + 101 + 2 + 101 = 412, with 100 pixels left, but it can’t fit the texture of the vertical fifth line (not to mention 2 pixels of padding between the fifth and fourth lines).

 

So for a 512×512 atlas, if you want to put in it the texture of 5 rows x 5 columns, each texture can only be a maximum of 100×100 pixels, and then remember to set the Padding attribute of atlas to 2 pixels.

Thanks to 厅级码农 for providing the answer above.


This is the 65th 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!

UWA website:en.uwa4d.com

UWA Blog:blog.en.uwa4d.com

UWA Q&A community:answer.uwa4d.com

Post a Reply