Unity tips and common problems

Note: This article will be updated and revised for a long time.

find objects quickly

Select the object you need to find in the Hierarchy, and F in the Scene view, you can quickly find the object you need
Please add a picture description


Quickly align objects

After selecting the object in the Game view, press and hold V, and you can see that the center of the movement has changed to the position of the mouse. Now try moving the two Cubes together seamlessly.
Please add a picture description


BMFont uses

A big guy open plugin is used .
How to use : After exporting .fnt and .png using BMFont, create CustomFont and Material in Unity. Open the above plug-ins and replace the required files in turn.
Note : If the font information is lost after restarting Unity , you can add EditorUtility.SetDirty(targetFont); at the end of the BMFontEditor.cs script to solve it.


Rigidbody and Collider

The rigid body makes the gameObject have physical properties, and the collider makes the gameObject have collision properties.


abstract class

Abstract classes cannot be serialized. Virtual functions can be serialized without being defined in abstract classes.


ScreenToWorldPoint

If the position does not change after calling Camera.ScreenToWorldPoint conversion , you may need to pay attention to the z value of the down conversion position .
If the camera is in orthographic mode, then the transformed position does not care about the z value.
But the camera is in perspective mode, then the z value of the converted position needs to be modified as follows:

point = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, cam.nearClipPlane));

Animator

When playing an animation with a transition condition on a wire, you can toggle the flow between two actions .
When using animator.Play and animator.CrossFade to switch animations, there is no continuity between the two actions . Play is to cut the next action hard, and CrossFade is to slowly switch to the next action within the time specified by the parameters.


Adding Objects and Models to Cooperate with Actions

It should be noted that the added object cannot have a rigid body, otherwise unexpected things will happen.
For example, when a lighter is added to the model's hand, when it cooperates with the action. The lighter's rigidbody needs to be temporarily hidden.


Navigation

Bake column parameters:
Agent Radius defines how close the center of the Agent can be to a wall or ledge.
Agent Height defines how deep the Agent can descend.
Max Slope defines the slope of the steep slope that the Agent can walk on.
Step Height defines how high an obstacle the Agent can step on.
DropHeight: drop height
JumpDistance: jump height

Precautions:

  • NavMeshObstacle obstacles need to check Carve to be effective
  • Where the proxy cannot reach, it is useless even if Off Mesh Link is set.
  • When the moving object sets the Collider, if the width of the path that needs to pass is smaller than the size of the Collider, the moving object cannot pass through at this time . The solution is to modify the boundaries of the Collider, or remove the Collider (if you do not need to use the collision)

Input

Input.GetMouseButton: Called continuously while the mouse is pressed Input.GetMouseButtonDown: Called
only once when the mouse is pressed Input.GetMouseButtonUp: Called only once when the mouse is released .

The parameters are all the same: 0 for the left button, 1 for the right button, and 2 for the middle button.


Animator transition conditions

There are several types of transition conditions: Bool, Int, Float, and Tririger. Here we only talk about Bool and Triger.
If we use Bool as a transition condition , after setting it to true, if it is not set to false next time when switching to other actions, this condition will always be true.
With Triger , there is no such problem. All we need to do is ResetTrigger("Last Trigger") before SetTrriger. Otherwise, the character will twitch when switching.


Pause the program while running

Just add the following code where you need to stop. The editor will enter a paused state:

  Debug.Break();

Image Preserve Aspect

Enable the Preserve Aspect checkbox. This makes the image as large as possible within the Rect Transform without being compressed or stretched.

Unchecked:
Not Enabled
After checking:
insert image description here
Original image:
insert image description here


model display

As shown in the figure below, the model displayed in the hierarchy panel is the second one in the figure below. The model is read-only, and when we try to delete the content, a pop-up window will appear indicating that it cannot be deleted.
To edit, a prefab needs to be created. That is, the first one shown in the figure below, at which point deletion will become effective.
insert image description here


SkinnedMeshRenderer

A model consists of a mesh containing triangles that is "rendered" by a Mesh Renderer, which makes the mesh visible. A Skinned Mesh Renderer is a special type of Mesh Renderer that allows the mesh to change shape based on the position and rotation of all the bones of the model .
The way animations are formed is as follows: the Animator component on the character's parent game object will change the rotation of all skeletal game objects' Transform components, and these changes will happen together to animate the character.


The role of Has Exit Time

HasExitTime has two functions:
the first one is that after checking it, there is no need to add conditions to convert. After the animation is played, it will automatically transition to the next action.
The second is to use the condition to switch, if the option animation is not checked, it will immediately switch to another one. But if it is checked, it will switch after the animation is played, that is to say, using conditions to switch will not take effect immediately.


naming convention

Public member variable/local variable: myParam
Non-public member variable: m_MyParam


Canvas Group

Canvas Groups provide centralized control over certain aspects of an entire group of UI elements without having to deal with each element individually. The properties of a Canvas Group affect the game object it is on as well as all child objects.
Typical uses for canvas groups are:

  1. Fade in or out the entire window by adding a canvas group on the window's game object and controlling its alpha property.
  2. Make the entire group of controls non-interactive ("grayed out") by adding the canvas group to the parent game object and setting its Interactable property to false.
  3. Make one or more UI elements not block mouse events by placing a Canvas Group component on the UI element or one of its parent elements and setting its Block Raycasts property to false.

Mathf.Approximately

Compares two floating point values ​​and returns true if they are similar.
For example, (1.0 == 10.0 / 10.0) will not return true every time. Approximately() Compares two floating-point numbers and returns true if they are within the smaller range of each other.


Input.GetAxis

Unity has an input manager (Edit-ProjectSetting-InputManager) for defining various buttons and axes that can be found by name. For example, there is an axis called Horizontal, represented by the A and D keys, and the left and right keys. So with that check, the player's computer can decide whether the character should move left or right.
Input.GetAxis can only monitor keyboard and gamepad input, which is meaningless for mobile platforms.

   float horizontal = Input.GetAxis("Horizontal");
   float vertival = Input.GetAxis("Vertical");

Animation state add StateMachineBehaviour

In the Animator interface, select the animation that needs to add a script, and select AddBehaviour in the Inspector to add the StateMachineBehaviour script.
The rigid body makes the gameObject have physical properties, and the collider makes the gameObject have collision properties.  If the gameObject has only rigid body and no collider, then the gameObject will keep falling.


Spine plugin download problem

If the file downloaded on the Spine official website is not .unitypackage , but a file ending in **.gz**. Try changing the browser to download. I can download the .unitypackage after changing the Google browser.
insert image description here

Spine resource import problem

Change the suffix of atlas to .txt, and drag it into Unity to automatically generate other related files.


The Spine animation is not finished playing, replay the problem

Both lines of code need to be added

   spine.Skeleton.SetToSetupPose();
   spine.AnimationState.ClearTracks();

Model animation repeat problem

Select the animation in the model, select Animation in the Inspector, and check LoopTime below. Finally, you need to click Apply to take effect.
insert image description here
insert image description here


Use of SpriteAtlas

Set Sprite Packer mode

Edit---->ProjectSetting------->Editor--------->Mode
insert image description here
Mode parameter meaning:
(1) disabled does not enable
(2) enabled for builds (legacy sprite packer): packaging (for the packaging method of sprite packer
) (3) always enabled (legacy sprite packer): always enabled (for the packaging method of sprite packer
) (4) enabled for builds: enabled for packaging (for the sprite Atlas Packaging method)
(5) always enabled (for the packaging method of sprite Atlas )

Sprite Atlas is the atlas packaging method after the 2017 version. Sprite Atlas has comprehensively improved the performance and usability of the old version of the atlas packaging system Sprite Packer .
So the author only uses spriteAtlas to demonstrate below.

Create sprite Atlas

Create the sprite Atlas as follows:
insert image description here

Join spriteAtlas

spriteAtlas supports adding through folders, so it is recommended to add through folders, so that you don't have to add them one by one. After adding, you can click PackPreview to view the effect.
insert image description here

View the effect

Here we can go back to setting the Sprite Packer mode above, modify SpritePacker back and forth to enabled for builds or always enabled , and then click Stats to view the effect

insert image description here


Model animation optimization

File compression method: select the .fbx file containing the action, then select Animation, and modify Anim.Compression.
insert image description here
Option description:
Off Turn off compression
Keyframe Reduction Reduce unnecessary keyframes
Optimal optimization compression, the official will choose the optimal compression method for compression, it is recommended to choose this


Reduce the impact of memory garbage collection (GC) on performance

String

  1. In C#, strings are reference types , not value types. We need to reduce unnecessary string creation or alteration operations . The method of modifying a string actually returns a new String object , and the original string remains in memory waiting to be recycled , so when the string is long or the operation is frequent, a lot of resources will be consumed . If you need to build strings at runtime, use the StringBuilder class.
  2. Try to avoid parsing data files composed of strings such as JSON and XML, store data in ScriptableObjects , or save in formats such as MessagePack or Protobuf .

Unity function calls

  1. Cache array references to avoid memory allocation of arrays during loops.
  2. Try to use functions that do not generate garbage collection. For example, use GameObject.CompareTag instead of manually comparing strings using GameObject.tag ( because returning a new string will generate garbage data ).

Boxing

Avoid passing in value type variables at reference type variables, because doing so will cause the system to create a temporary object and convert the value type to an object type behind the scenes (such as int i = 123; object o = i ), resulting in garbage collection demand. Try to use the correct type override to pass in the desired value type . Generics can also be used for type overriding.

Coroutines

While yield does not result in garbage collection, creating a WaitForSeconds object does . We can cache and reuse the WaitForSeconds object without having to create it again in yield.

    WaitForSeconds waitSec = new WaitForSeconds(0.01f);
    IEnumerator TestWaitSecond()
    {
    
    
        yield return waitSec;
    }

Reduce the amount of code per frame

There is a lot of code that is not meant to run on every frame, and this unnecessary logic can be completely removed in Update, LateUpdate, and FixedUpdate. These event functions can save the code that must be updated every frame, and any logic that does not need to be updated every frame does not have to be placed in it.
If you must use Update, consider making your code run every n frames.

private int interval = 3;
void Update()
{
    
    
    if (Time.frameCount % interval == 0)
    {
    
    
        ExampleExpensiveFunction();
    }
}

Avoid adding heavy logic in Start/Awake

When the first scene is loaded, each object will call the following functions: Awake, OnEnable, Start. We need to avoid running heavy logic in these functions
until the app has finished rendering the first frame . Otherwise, your app's load time will be unexpectedly long .


Avoid joining empty events

Even empty MonoBehaviours consume resources, so we should remove the empty Update and LateUpdate methods.
If you want to test with these methods, use a preprocessing directive:

#if UNITY_EDITOR
void Update()
{
    
    
}
#endif

This way, Update tests in the editor don't have a bad performance impact on builds.


Delete the Debug Log statement

Log statements (especially in Update, LateUpdate, and FixedUpdate) slow down performance, so we need to disable Log statements before building . You can easily disable the Debug Log by writing a Conditional attribute with a preprocessing directive. For example, a custom class like the following:

public static class Logging
{
    
    
    [System.Diagnostics.Conditional("ENABLE_LOG")]
    static public void Log(object message)
    {
    
    
        UnityEngine.Debug.Log(message);
    }
} 

Use hashes, avoid strings

The underlying Unity code does not use strings to access Animator, Material, and Shader properties. For efficiency, all property names are hashed into property IDs , which are used as actual property names. When using Set or Get
methods on Animator, Material or Shader , we can use integer values ​​instead of strings . The latter also needs to be hashed once and is not as straightforward as the integer value. Use Animator.StringToHash to convert Animator property names , and Shader.PropertyToID to convert Material and Shader property names .

    public static int IS_WALKING;
    private void Awake()
    {
    
    
        IS_WALKING = Animator.StringToHash("IsWalking");
    }
    void FixedUpdate()
    {
    
    
       //使用ID修改条件
       m_Animator.SetBool(IS_WALKING, isWaking);
    }

Choose the right data structure

Since the data structure may be iterated thousands of times per frame, its structure has a large impact on performance. If you don't know whether the data collection should be represented by List, Array or Dictionary, you can refer to C#'s MSDN data structure guide to choose the correct structure.

insert image description here


Avoid adding components at runtime

Calling AddComponent at runtime will take a certain amount of running cost, and Unity must check whether the component has duplication or dependencies .


Caching GameObjects and Components

Calling GameObject.Find, GameObject.GetComponent, and Camera.main (versions below 2020.2) will generate a large execution load, so these methods are not suitable for calling in Update, but should be called and cached in Start .

private Renderer myRenderer;
void Start()
{
    
    
    myRenderer = GetComponent<Renderer>();
}

void Update()
{
    
    
    ExampleFunction(myRenderer);
} 

Using ScriptableObjects (Programmable Objects)

Constant values ​​or configuration information can be stored in a ScriptableObject, not necessarily in a MonoBehaviour. ScriptableObject can be accessed by the whole project, once set can be applied globally to the project.

statement:

using UnityEngine;

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
    
    
    public string prefabName;

    public int numberOfPrefabsToCreate;
    public Vector3[] spawnPoints;
}

use:

using UnityEngine;

public class Spawner : MonoBehaviour
{
    
    
    // 要实例化的游戏对象。
    public GameObject entityToSpawn;

    //上面定义的 ScriptableObject 的一个实例。
    public SpawnManagerScriptableObject spawnManagerValues;

    //这将附加到创建的实体的名称,并在创建每个实体时递增。
    int instanceNumber = 1;

    void Start()
    {
    
    
        SpawnEntities();
    }

    void SpawnEntities()
    {
    
    
        int currentSpawnPointIndex = 0;

        for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++)
        {
    
    
            //在当前生成点处创建预制件的实例。
            GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints[currentSpawnPointIndex], Quaternion.identity);

            //将实例化实体的名称设置为 ScriptableObject 中定义的字符串,然后为其附加一个唯一编号。
            currentEntity.name = spawnManagerValues.prefabName + instanceNumber;

            // 移动到下一个生成点索引。如果超出范围,则回到起始点。
            currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;

            instanceNumber++;
        }
    }
}

Packaging 64-bit Android package

Build Setting -> Player Setting -> Player -> Other Settings,
modify Scripting Backend to IL2CPP, and check ARM64 for Target Architectures.
(as the picture shows)

insert image description here
After generating the apk, open the lib folder with decompression software, if it is arm64-v8a, it is 64-bit:
insert image description here

Guess you like

Origin blog.csdn.net/qq_28644183/article/details/125487290