Tips on Unity Development

Created on: 19 Jul 21 13:12 +0700 by Son Nguyen Hoang in English

Some notable tips on Unity Game Dev

Unity is so big, so complicated and the editor get update too frequent that sometime I feel a little bit overwhelmed. This post lists critical problems that I encountered when making game using Unity.

This article is under ongoing development hence the content may be updated and changed regularly.


  1. Game Object position between object in game scene & value logged to console not be the same.

Explaination: It is very likely the the two position we see on console & on scene are two different variant. There are three different type of position for Unity Game Object:

  • position: world space position
  • localPosition: localPosition is where the pivot of the element is in relation to the parents pivot.
  • anchorPosition: is where the pivot of your element is in relation to your elements anchor.

Depend on the scenarios, how you setup game objects, position of anchor, etc…. You will prefer one over the others and use it in the code.

P/S: I feel like the UI of Unity when showing the rectTransform never mention about these three type of position. Did I miss something?


  1. Find usage of any game assest.

Motivation: Sometime, when your project increased by size, you regconize that your gameObject prefab used a lot of sprites, assest, music, reference to other prefab, etc. This lead to one annoying problem: If there is an assest in my game folders, then which prefab object is using it?

Some might say that you can use a Build Report Tool to list all assests and their usage. However, this is never enough. My lastest experience with a report tool shows me that it only indicates the game scene where the assest be used, not the exact game prefab using it.

Solution:

  • Find the assests you need to locate the usage. My example is an image named thumbnail.jpg
  • Search for the file’s metadata.
  • Look for its GUID value
  • Using git grep to find the reference by the GUID.

Code:

git grep <GUID>

  1. Wrong position/alignment when render inline graphic in TMPRO.

Illustration:

I used TMPRo and sprite assest to render inline graphic, this time it is an icon from the EmojiOne default icon set in TMPro package.

As you can see in the image, the second icon displays incorrectly so that the end of the prior character (letter ’d') is inlined with the center of that icon.

Solution #1:

  • Modify pivot of icon from center to bottom left
  • In my Unity editor, version 2019, you also must create the sprite sheet again and then select it from TMPro setting.

Solution #2:

  • Modify position in the corresponding Sprite Glyph Table

  1. Optimization techniques for Mobile Game, Summarized from Zenva Course

Original Link: https://academy.zenva.com/course/publishing-and-optimizing-mobile-games/

Light Baking:

An alternative to real-time lighting. Basically, real-time lighting is default, which calculate lighting & shadow in each frame. This is computing expensive.

Baked lighting means pre-calculate & render lighting for objects, which basically render static texture for light & shadows. This is usually used for static objects, such as non-moving game objects like trees, houses, etc.

A small warning is that the objects selected for baked lighting should be static.

UI Optimization:
  • UI Element which doesn’t need to track interaction, e.g score indicator, should have raycast target be disabled.
  • Spliting Menu to different CANVAS.
Scripting Optimization:
  • Reduce Debug.Loc call
  • Reduce Raycast call
  • Using Object Pooling

  1. Get all children recursively from gameObject
private void GetChildRecursive(GameObject obj, List<GameObject> listOfChildren)
{
    if (null == obj)
        return;

    foreach (Transform child in obj.transform)
    {
        if (null == child)
            continue;
        //child.gameobject contains the current child you can do whatever you want like add it to an array
        listOfChildren.Add(child.gameObject);
        GetChildRecursive(child.gameObject, listOfChildren);
    }
}

Declare & Init a blank List then pass it into the method


  1. Error: JAVA_HOME is not set and no 'java' command could be found in your PATH (Unity 202.0.23f1)

I tried to tick/untick the JDK checkbox (Preference) as recommended by this link, however, it just didn’t work.

https://forum.unity.com/threads/java_home-is-not-set-and-no-java-command-could-be-found-in-your-path.740264/

The solution that’s work for me is to manually set the ‘JAVA_HOME’ to the JDK folder that Unity installed for us. One final notice is that you should add that path to USER VARIABLE, NOT SYSTEM VARIABLE


  1. Reinstalling support module (Android, IOS, … ) to Unity Hub

Sometime, you encountered a crazy bugs regarding to the Unity Hub

Details

  • You install Android JDK
  • The Unity Hub tells you the package has been installed
  • In reality, the installation of the addon failed
  • However, in Unity Hub, the checkbox for the addon is marked, hence you cannot reinstall it.

Comment This is most likely a front-end, GUI bug of Unity Developer, I encountered it in Unity 2021.2.7f.

Solution

  • The the json file that lists your Unity modules and its status (modules.json). This is often located in Unity/Hub/Editor/[YOUR UNITY EDITOR VERSION]/
  • Find the lines corresponding to the module you wish to reinstall. Look for the field selected then set it to “false”.
  • You may want to do some tweaks to edit that file. This file cannot be edited directly in my machine. Hence I make a copy of it then paste it back to the folder using admin permission.

  1. Cannot Click on Editor Buttons

Not sure if it is a big or glitch. But on weird situation I cannot click on this area from Unity Editor (2020.3.2f1)

Illustration:

To solve this problem, Hit on the bottom, right area, find the Debugger Enabled button and switch the release mode. The problem should be gone for good now. Also, after the bug gone you can revert the debugger mode.


  1. DON’USE Task.wait or Task.delay on WebGL Build

Tested on Unity 2020.3.34: Avoid using above functions at all cost! Things seem to run properly on Editor but go wrong pretty fast when we build the game and run it on WebGL

Solution

Use Unity Coroutine Instead!


  1. BUG ‘Newtonsoft’ could not be found!

Solution

  • Open the Packages folder in your system’s file browser

  • edit manifest.json. In the dependencies section, add this line:

“com.unity.nuget.newtonsoft-json”: “2.0.0”

  • (optional) go to the Package Manager window and update to the current version.

Source: https://stackoverflow.com/questions/38084186/json-net-in-unity-throwing-the-type-or-namespace-newtonsoft-could-not-be-foun


  1. Cannot Edit Transparency Sort Axis in URP 12.1 (Unity 3d)

This bug appears on Unity 3d (2021.3.11f1 LTS) When URP is applied to the project. In Edit -> Project Setting -> Graphics; There is no more option to edit “Transparency Sort Axis”.

To edit this, the only way is to edit “m_TransparencySortAxis” in the file GraphicsSettings.asset. Edit the file directly (by VSCODE or Notepad) without Unity Editor.

  1. Bug when Build APK: duplicate class (Unity 3d)

Check for similarity between packages you installed. At the moment when this bug is noted (21-12-2022), I encountered this error when install both Unity Advertisement (Legacy) and Unity Ads for Mediation.

A second solution could be go to Asset (On the toolbar) -> Mobile Dependency Resolver -> Android -> Delete Resolved Library

  1. Physics2D.RaycastAll detect wrong collision (Unity 2d)

Sometime Physics2D.RaycastAll produces wrong result. For example, even that the ray was successfully casted, the detected results were not correct. The bug was found in my company project with Unity 2019.4.40. Using Physics2D.GetRayIntersectionAll instead. Sample code was given below:

   Ray ray = MainCamera.ScreenPointToRay(gestureFocus);
   hits = Physics2D.GetRayIntersectionAll(ray, Mathf.Infinity);

I actually went to the forum and ask about the difference. The answer of mod is quoted below:

2D physics is 2D so there is no raycast in or out (Z axis) of the world. It's 2D dimensional. GetRayIntersection is a pseudo-3D query because it projects your 3D ray into a 2D (XY) raycast then sorts the results that come out of the physics system by the Transform Z on the GameObject.

The problem is that devs quite often take code posted for 3D raycasting and apply it to 2D without really considering that it's not appropriate to do that.

The equivalent of raycasting directly along the Z axis is Physics2D.OverlapPoint but the order isn't defined because no Z.

Original link: https://forum.unity.com/threads/physics2d-raycastall-returningn-all-objects-in-scene.1172692/

  1. Scroll the ScrollRect to top/bottom
using UnityEngine;
using UnityEngine.UI;
public static class ScrollRectExtensions
{
    public static void ScrollToTop(this ScrollRect scrollRect)
    {
        scrollRect.normalizedPosition = new Vector2(0, 1);
    }
    public static void ScrollToBottom(this ScrollRect scrollRect)
    {
        scrollRect.normalizedPosition = new Vector2(0, 0);
    }
}

Original Link: https://forum.unity.com/threads/scroll-to-the-bottom-of-a-scrollrect-in-code.310919/

  1. Avoid casting enum -> String in all cost.

The function was much more expensive, especially when you put it inside something like Update() and OnTriggerSay().

alt text

The above image was profiler from my test. Inside each OnTriggerStay was a enum casting on Tag. The check was done after casting Tag (enum) into String. The total long to compute wwas about 6 miliseconds (divided into 3 divisions)

Without the casting. The performance was only 0.15 miliseconds (in total).

  1. Every fbx file imported to Project has wrong scale factor
public class ImportSettings : AssetPostprocessor
{
	//public const float importScale = 1.0f;
	
	void OnPreprocessModel()
	{
		ModelImporter importer = assetImporter as ModelImporter;
		
		//importer.globalScale  = 1f;
		importer.materialImportMode = ModelImporterMaterialImportMode.None;
		importer.generateAnimations = ModelImporterGenerateAnimations.None;
		importer.importAnimation = false;
	}
}
Back To Top