Unity provides a cross platform game development environment for developers. Developers can use C# language and/or JavaScript syntax based UnityScript for programming the game. Target deployment platforms can be switched easily in the editor. All core game code stays same except some platform dependent features. A list of all the versions and corresponding downloads and release notes can be found here: https://unity3d.com/get-unity/download/archive.
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();
}
}
It's best to use coroutines in moderation as the flexibility comes with a performance cost.
MoveNext
return value. This was last observed in 5.4.0b13. (Bug report)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.
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
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.
FindObjectOfType
and Find
only when necessaryFindGameObjectWithTag
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.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.
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.
Use String.Contains()
to process only assets that have a given string in their asset paths.
if (assetPath.Contains("ProcessThisFolder"))
{
// Process asset
}
Unity's serialization system can be used to do the following:
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:
There are few importants things to know to properly hook the Profiler on different platforms.
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.
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.
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.
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.
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.
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.
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.
Currently, Unity provides two ways to call native Android code.
To interact with native code, Unity provides some classes and functions.
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
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
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.