Factory design pattern is used very often in Unity, but you might not even realize that. Well, you might don’t know that this is even a thing! Don’t believe me? When was last time when you instantiate prefabs in your project from code?
Yup, you used factory design pattern there without even knowing! Congrats! ?
Factory?
So what exactly is this whole factory thing? Factory is a design pattern used for creating new instances or copies of the predetermined object.
A great example of it can be an instantiation of bullets or enemies from prefabs. And this exactly what it is all about!
Implementation
As mentioned already this design pattern is often used without even realizing it, but I started separating it, and you don’t have to follow me on that. However, I believe that KISS (keep it simple, stupid) is the only proper way to write code! ?
So let’s take a look at KISS factory script:
using UnityEngine; /// <summary> /// Factory design pattern. /// </summary> public class Factory : MonoBehaviour { // Reference to prefab. [SerializeField] private MonoBehaviour prefab; /// <summary> /// Creating new instance of prefab. /// </summary> /// <returns>New instance of prefab.</returns> public MonoBehaviour GetNewInstance() { return Instantiate(prefab); } }
It’s as simple as it can get. Really! I mean almost! ?
So besides KISS, there is also DRY (don’t repeat yourself) way to write code. ?
But we are little evil geniuses here, and we can combine the power of both of them to create DRY KISS!!! ???
DRY KISS Factory?!?!?!?
You heard me right! We are going to implement DRY KISS Factory!
So our goal will be to make our existing Factory script to be a little bit more universal, and for that matter, we are going to use generics!
using UnityEngine; /// <summary> /// Factory design pattern with generic twist! /// </summary> public class GenericFactory<T> : MonoBehaviour where T : MonoBehaviour { // Reference to prefab of whatever type. [SerializeField] private T prefab; /// <summary> /// Creating new instance of prefab. /// </summary> /// <returns>New instance of prefab.</returns> public T GetNewInstance() { return Instantiate(prefab); } }
A lot has changed, isn’t it? Now we can make how many factories of a different kind as we want! ?
using UnityEngine; /// <summary> /// Factory for prefabs of TrailObjects /// </summary> public class TrailFactory : GenericFactory<TrailObject> { }
BAM! New factory! ?
using UnityEngine; /// <summary> /// Factory for prefabs of AudioObjects /// </summary> public class AudioFactory : GenericFactory<AudioObject> { }
BAM! And another one! ?
Now you see how easy it is to make new factories? Great! So the last thing will be to create a project to use our newly created factory!
Example
In this example, we will create spawner which will spawn and place self-destroying prefab on the scene. Our spawner will look like this:
using UnityEngine; /// <summary> /// Prefab spawner. /// Component uses factory to spawn new instance every few moments /// </summary> public class PrefabTimedSpawner : MonoBehaviour { // Spawn rate [SerializeField] private float spawnRatePerMinute = 30; // Current spawn count private int currentCount = 0; // Reference to used factory [SerializeField] private TimedObjectFactory factory; /// <summary> /// Unity's method called every frame /// </summary> private void Update() { var targetCount = Time.time * (spawnRatePerMinute / 60); while (targetCount > currentCount) { var inst = factory.GetNewInstance(); inst.transform.position = new Vector3(Random.Range(-7.0f, 7.0f), Random.Range(-5.0f, 5.0f), 0); currentCount++; } } }
Now we need a factory and self-destruction script on our prefab!
using UnityEngine; /// <summary> /// Factory for prefabs of TimeoutObjects /// </summary> public class TimedObjectFactory : GenericFactory<TimeoutObject> { }
using UnityEngine; /// <summary> /// Timeout object. /// It destroys itself after provided timeout. /// </summary> public class TimeoutObject : MonoBehaviour { // Time after which object will be destroyed [SerializeField] private float timeout = 2; // Saving enable time to calculate when to destroy itself private float startTime; /// <summary> /// Unity's method called on object enable /// </summary> private void OnEnable() { startTime = Time.time; } /// <summary> /// Unity's method called every frame /// </summary> private void Update() { // Waiting for timeout if (Time.time - startTime > timeout) { // Destroying object Destroy(gameObject); } } }
Done! Now we can see the results of it!
Congratulation! You just learned a new design pattern, and you understand how to use it!
As always I’m making the repository with this example public, and you can find it here.
Next time we are going to optimize it! Stay tuned!
Ok, so what if I have several enemy types represented as scriptable objects?