This tutorial is outdated, you can find the latest version here: GitHub
We begin with Wikipedia's defintion of the flyweight pattern:
In computer programming, flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.
So the basic idea is that if you have a lot of objects in your game, there's a high probability that you can increase the performance of your game by optimizing memory usage by making those objects "lighter." If this is going to work, your objects have to share some data which is the same for all objects. If they do share some data, then you can create the data once and then store a reference to the data in the object. This might sound complicated, so we need an example.
One common example to use is trees. Each tree in a game is the same to all other trees. So what's being shared among all trees is:
But the trees don't have the same position, so that's the only thing in the tree object that's different from all other trees.
Trees are kinda dull, so we are here going to use Aliens with thousands of eyes, arms, and legs. So we need an alien class that describes an alien:
using UnityEngine; using System.Collections; using System.Collections.Generic; namespace FlyweightPattern { //Class that includes lists with position of body parts public class Alien { public List<Vector3> eyePositions; public List<Vector3> legPositions; public List<Vector3> armPositions; } }
Before the flyweight pattern we will create all aliens and generate new body-part-positions for each alien:
using UnityEngine; using System.Collections; using System.Collections.Generic; //Flyweight design pattern main class namespace FlyweightPattern { public class Flyweight : MonoBehaviour { //The list that stores all aliens List<Alien> allAliens = new List<Alien>(); List<Vector3> eyePositions; List<Vector3> legPositions; List<Vector3> armPositions; void Start() { //List used when flyweight is enabled eyePositions = GetBodyPartPositions(); legPositions = GetBodyPartPositions(); armPositions = GetBodyPartPositions(); //Create all aliens for (int i = 0; i < 10000; i++) { Alien newAlien = new Alien(); //Add eyes and leg positions //Without flyweight newAlien.eyePositions = GetBodyPartPositions(); newAlien.armPositions = GetBodyPartPositions(); newAlien.legPositions = GetBodyPartPositions(); //With flyweight //newAlien.eyePositions = eyePositions; //newAlien.armPositions = legPositions; //newAlien.legPositions = armPositions; allAliens.Add(newAlien); } } //Generate a list with body part positions List<Vector3> GetBodyPartPositions() { //Create a new list List<Vector3> bodyPartPositions = new List<Vector3>(); //Add body part positions to the list for (int i = 0; i < 1000; i++) { bodyPartPositions.Add(new Vector3()); } return bodyPartPositions; } } }
If you add the Flyweight.cs to an empty gameobject, open the profiler, press play, click on the Memory box, you will see this image:
The box you should pay attention to is Mono, which, according to Unity, is the "total heap size and used heap size used by Managed Code - this memory is garbagecollected." It's currently at 0.63 Gb, which is the number we are going to lower with the flyweight pattern.
To add the flyweight pattern, we just assume that all aliens have the same body-part-positions. It might not be realistic, but this is just a test to see how the flyweight pattern is working. So modify the code so it looks like this:
//Add eyes and leg positions //Without flyweight //newAlien.eyePositions = GetBodyPartPositions(); //newAlien.armPositions = GetBodyPartPositions(); //newAlien.legPositions = GetBodyPartPositions(); //With flyweight newAlien.eyePositions = eyePositions; newAlien.armPositions = legPositions; newAlien.legPositions = armPositions;
So we generate the body-part-positions once in the beginning and then add a reference to them to each Alien object. If you now open the profiler, press play, click on the Memory box, you will see this image:
So the Memory has gone from 0.63 Gb to 17 Mb!