unity3d

Topics related to unity3d:

Getting started with unity3d

Quaternions

Prefabs

Singletons in Unity

While there are schools of thought which make compelling arguments why unconstrained use of Singletons is a bad idea, e.g. Singleton on gameprogrammingpatterns.com, there are occasions when you might want to persist a GameObject in Unity over multiple Scenes (e.g. for seamless background music) while ensuring that no more than one instance can exist; a perfect use case for a Singleton.

By adding this script to a GameObject, once it has been instantiated (e.g. by including it anywhere in a Scene) it will remain active across Scenes, and only one instance will ever exist.


ScriptableObject (UnityDoc) instances provide a valid alternative to Singletons for some use cases. While they don't implicitly enforce the single instance rule, they retain their state between scenes and play nicely with the Unity serialization process. They also promote Inversion of Control as dependencies are injected through the editor.

// MyAudioManager.cs
using UnityEngine;

[CreateAssetMenu] // Remember to create the instance in editor
public class MyAudioManager : ScriptableObject {
    public void PlaySound() {}
}
// MyGameObject.cs
using UnityEngine;

public class MyGameObject : MonoBehaviour
{
    [SerializeField]
    MyAudioManager audioManager; //Insert through Inspector

    void OnEnable()
    {
        audioManager.PlaySound();
    }
}

Further reading

Transforms

Using Git source control with Unity

Object Pooling

User Interface System (UI)

MonoBehaviour class implementation

Extending the Editor

Raycast

Input System

Coroutines

Performance considerations

It's best to use coroutines in moderation as the flexibility comes with a performance cost.

  • Coroutines in great numbers demands more from the CPU than standard Update methods.
  • There is an issue in some versions of Unity where coroutines produce garbage each update cycle due to Unity boxing the MoveNext return value. This was last observed in 5.4.0b13. (Bug report)

Reduce garbage by caching YieldInstructions

A common trick to reduce the garbage generated in coroutines is to cache the YieldInstruction.

IEnumerator TickEverySecond()
{
    var wait = new WaitForSeconds(1f); // Cache
    while(true)
    {
        yield return wait; // Reuse
    }
}

Yielding null produces no extra garbage.

Optimization

  1. If possible, disable scripts on objects when they are not needed. For example if you have a script on an enemy object that searchers for and fires at the player consider disabling this script when the enemy is too far for example from the player.

ScriptableObject

ScriptableObjects with AssetBundles

Pay attention when adding prefabs to AssetBundles if they contain references to ScriptableObjects. Since ScriptableObjects are essentially assets, Unity creates duplicates of them before adding them to AssetBundles, which may result in undesired behaviour during runtime.

When you load such a GameObject from an AssetBundle, it may be necessary to reinject the ScriptableObject assets to the loaded scripts, replacing the bundled ones. See Dependency Injection

Physics

Finding and collecting GameObjects

Which method to use

Be careful while looking for GameObjects at runtime, as this can be resource consuming. Especially : don't run FindObjectOfType or Find in Update, FixedUpdate or more generally in a method called one or more time per frame.

  • Call runtime methods FindObjectOfType and Find only when necessary
  • FindGameObjectWithTag has very good performance compared to other string based methods. Unity keeps separate tabs on tagged objects and queries those instead of the entire scene.
  • For "static" GameObjects (such as UI elements and prefabs) created in the editor use serializable GameObject reference in the editor
  • Keep your lists of GameObjects in List or Arrays that you manage yourself
  • In general, if you instantiate a lot of GameObjects of the same type take a look at Object Pooling
  • Cache your search results to avoid running the expensive search methods again and again.

Going deeper

Besides the methods that come with Unity, it's relatively easy to design your own search and collection methods.

  • In case of FindObjectsOfType(), you could have your scripts keep a list of themselves in a static collection. It is far faster to iterate a ready list of objects than to search and inspect objects from the scene.

  • Or make a script that stores their instances in a string based Dictionary, and you have a simple tagging system you can expand upon.

Resources

Collision

How to use asset packages

CullingGroup API

Since using CullingGroups is not always very straightforward, it may be helpful to encapsulate the bulk of the logic behind a manager class.

Below is a blueprint how such a manager might operate.

using UnityEngine;
using System;
public interface ICullingGroupManager
{
    int ReserveSphere();
    void ReleaseSphere(int sphereIndex);
    void SetPosition(int sphereIndex, Vector3 position);
    void SetRadius(int sphereIndex, float radius);
    void SetCullingEvent(int sphereIndex, Action<CullingGroupEvent> sphere);
}

The gist of it is that you reserve a culling sphere from the manager which returns the index of the reserved sphere. You then use the given index to manipulate your reserved sphere.

Layers

Multiplatform development

Importers and (Post)Processors

Use String.Contains() to process only assets that have a given string in their asset paths.

if (assetPath.Contains("ProcessThisFolder"))
{
    // Process asset
}

Unity Animation

Tags

Attributes

SerializeField

Unity's serialization system can be used to do the following:

  • Can serialize public nonstatic fields (of serializable types)
  • Can serialize nonpublic nonstatic fields marked with the [SerializeField] attribute
  • Cannot serialize static fields
  • Cannot serialize static properties

Your field, even if marked with the SerializeField attribute, will only be attributed if it is of a type that Unity can serialize, which are:

  • All classes inheriting from UnityEngine.Object (e.g. GameObject, Component, MonoBehaviour, Texture2D)
  • All basic data types like int, string, float, bool
  • Some built-in types like Vector2/3/4, Quaternion, Matrix4x4, Color, Rect, LayerMask
  • Arrays of a serializable type
  • List of a serializable type
  • Enums
  • Structs

Communication with server

Networking

Headless mode in Unity

If you are building a Server to deploy in Linux, the Build settings have a "Headless mode" option. An application build with this option doesn't display anything and doesn't read user input, which is usually what we want for a Server.

Headless mode in Build settings

Asset Store

Virtual Reality (VR)

Mobile platforms

Immediate Mode Graphical User Interface System (IMGUI)

Unity Profiler

Using Profiler on different Device

There are few importants things to know to properly hook the Profiler on different platforms.

Android

In order to properly attach the profile, "Build and Run" button from the Build Settings window with the option Autoconnect Profiler checked must be used.

enter image description here

Another mandatory option, in Android Player Settings inspector in the Other Settings tab, there is a checkbox Enable Internal profiler which needs to be checked so LogCat will output profiler info.

enter image description here

Using only "Build" will not allow the profiler to connect to an Android device because the "Build and Run" use specific command line arguments to start it with LogCat.

iOS

In order to properly attach the profile, "Build and Run" button from the Build Settings window with the option Autoconnect Profiler checked must be used on the first run.

enter image description here

On iOS, there is no option in player settings that must be set for the Profiler to be enable. It should work out of the box.

Vector3

Unity Lighting

Audio System

Ads integration

This applies to Unity Ads.

Make sure that Test Mode for Unity Ads is enabled during development

You, as the developer, are not allowed to generate impressions or installs by clicking on ads in your own game. Doing so violates the Unity Ads Terms of Service agreement, and you will be banned from the Unity Ads network for attempted fraud.

For more information, read the Unity Ads Terms of Service agreement.

Android Plugins 101 - An Introduction

Through this series, I extensively use external links that I encourage you to read. While paraphrased versions of the relevant content will be included here, there may be times when the additional reading will help.


Beginning with Android plugins

Currently, Unity provides two ways to call native Android code.

  1. Write native Android code in Java, and call these Java functions using C#
  2. Write C# code to directly call functions that are part of the Android OS

To interact with native code, Unity provides some classes and functions.

  • AndroidJavaObject - This is the base class that Unity provides to interact with native code. Almost any object returned from native code can be stored as and AndroidJavaObject
  • AndroidJavaClass - Inherits from AndroidJavaObject. This is used to reference classes in your native code
  • Get / Set values of an instance of a native object, and the static GetStatic / SetStatic versions
  • Call / CallStatic to call native non-static & static functions


Outline to creating a plugin and terminology

  1. Write native Java code in Android Studio
  2. Export the code in a JAR / AAR file (Steps here for JAR files and AAR files)
  3. Copy the JAR / AAR file into your Unity project at Assets/Plugins/Android
  4. Write code in Unity (C# has always been the way to go here) to call functions in the plugin

Note that the first three steps apply ONLY if you wish to have a native plugin!

From here on out, I'll refer to the JAR / AAR file as the native plugin, and the C# script as the C# wrapper



Choosing between the plugin creation methods

It's immediately obvious that the first way of creating plugins is long drawn, so choosing your route seems moot. However, method 1 is the ONLY way to call custom code. So, how does one choose?

Simply put, does your plugin

  1. Involve custom code - Choose method 1
  2. Only invoke native Android functions? - Choose method 2

Please do NOT try to "mix" (i.e. a part of the plugin using method 1, and the other using method 2) the two methods! While entirely possible, it's often impractical and painful to manage.

Design Patterns