One of the most important things to get right when developing a tycoon game is the simulation logic. While Unity is a versatile engine that can support many types of games, it’s also its Achilles heel. To develop a tycoon game in Unity, you will need to implement and update the simulation logic yourself. So what is the best way of updating a simulation inside of Unity? One way is to update the simulation using a custom simulation tick inside of your Unity game.


What Is a Custom Simulation Tick
When developing a game in Unity, you might know that a MonoBehaviour has an Update method. This method is called every frame. Meaning, if your game is running at 60 fps, the Update method will be called 60 times per second. This is actually a nice simulation tick that Unity provides out of the box. Similarly, every MonoBehaviour has a FixedUpdate method that is called every time Unity’s physics system performs an update. So now you might ask yourself: Why does your tycoon game need a custom simulation tick?

Why Does My Unity Game Need a Custom Simulation Tick
The answer to this is actually quite simple. If your game runs at 60 fps then the Update method will also be called 60 times per second. Yet, the frame rate in a game is not constant. This fully depends on how optimized the game is and on what device it is running. As a result, there are moments the game runs at the desired 60 fps, yet there are also moments it dips below that target.

Obviously, when building a tycoon game in Unity, your simulation logic will need to update and run at a certain rate. However, does the simulation logic also need to run at the same rate as the frame rate?, If you have developed games before, you might argue that this should in fact be the case. However, there are actually benefits to running your simulation logic separately from the frame rate.
Why a Custom Simulation Tick is Helpful
Imagine a scenario where a player looses 1 health every second. Do we need to need to calculate the lost health per frame or can we also do it at a slower rate? It should be quite clear that instead of every frame, we could decrease the player’s health by 1 every second. That’s quite a significant performance improvement. For many cases in a tycoon game, we don’t have to update the simulation every frame. It is sufficient to update it at a slower rate.
Next to that, using a custom simulation tick in Unity, we can actually ‘run’ the game without playing the game. Think about it for a while. If we simply invoke the Simulation Tick a couple of times, we are effectively running the simulation. As a result, implementing a custom Simulation Tick will decouple your simulation logic from Unity. This is also very useful when you are building tests and don’t want to play the whole game..

How Often Should The Simulation Update
This is actually a difficult question to answer since each game has different requirements. There are games work well if their simulations are updated once very second. Yet, there are also games that need to be updated a few times per second. However, it is wrong to assume that a game only has one type of simulation tick.

Rather than thinking how a simulation tick should be implemented in a game, you should ask yourself what type of simulation tick a game system needs. For example, inside a city builder, traffic will have a much higher simulation tick rate than the system responsible for calculating electricity production and consumption. It all depends on priority and how much interaction is lost by lowering the tick rate. Determining the simulation tick is not about how often, but more a question about balance.
How To Make a Custom Simulation Tick in Unity
Make A Simulation Service Class
By now you might be wondering how to implement a custom simulation tick in Unity for your tycoon game. Let’s start by creating a new MonoBehaviour class called TickService and attach it to a new GameObject. We will also create a new class called Constants that contains constant values for our Tick Service
Constants.csTickService.cs
public class Constants { public class Tick { public const float Min = 0.01f; public const float Max = float.MaxValue; public const float Second = 1.0f; public const int ExecutionOrder = -1000; } }
using UnityEngine; [DefaultExecutionOrder(Constants.Tick.ExecutionOrder)] public class TickService : MonoBehaviour { [SerializeField, Range(Constants.Tick.Min, Constants.Tick.Max)] private float m_TickDuration = Constants.Tick.Second; private float m_ElapsedTime = 0.0f; private int m_CurrentTick = 0; }
When looking at the TickService class, we have exposed a variable called m_TickDuration which we will be using to specify the duration of a tick. This variable can be adjusted in the Inspector through a slider to keep it within valid ranges. Finally, we added the DefaultExecutionOrder attribute to change the Execution Order. This is done to make sure the Tick Service always runs before any other MonoBehaviour.
Measuring the Elapsed Time
Now that we have a class, we can start implementing our custom simulation tick. The way our simulation tick in Unity will work is that we sum up the elapsed time between frames. Then, if the class notices that enough time has passed, it will run a simulation tick and subtract the simulation tick duration from the elapsed time.
To do this, we add the following Update method to our Tick Service class. In here, we can see that we are summing up the time between frames and checking if a simulation tick needs to run. Now all that we need to do is implement the tick method itself.
TickService.csprivate void Update() { while(m_ElapsedTime >= m_TickDuration) { m_ElapsedTime -= m_TickDuration; // Perform a tick here... } // Accumulate the elapsed time for this frame m_ElapsedTime += Time.deltaTime; }
Calling the Simulation Tick
Since we now have a way of detecting when our custom simulation tick in Unity occurs, we can start responding to it. This is actually really simple as we only need to add another method. In our case, we will add a Tick method to the TickService class and call it from the Update method. The final code of our Tick Service class will look as following:
TickService.cs
using UnityEngine; [DefaultExecutionOrder(Constants.Tick.ExecutionOrder)] public class TickService : MonoBehaviour { [SerializeField, Range(Constants.Tick.Min, Constants.Tick.Max)] private float m_TickDuration = Constants.Tick.Second; private float m_ElapsedTime = 0.0f; private int m_CurrentTick = 0; private void Update() { while(m_ElapsedTime >= m_TickDuration) { m_ElapsedTime -= m_TickDuration; // Perform a tick here... Tick(m_TickDuration, m_CurrentTick * m_TickDuration); m_CurrentTick++; } // Accumulate the elapsed time for this frame m_ElapsedTime += Time.deltaTime; } public void Tick(float delta, float elapsed) { Debug.Log("Tick " + m_CurrentTick); } }
Using a Custom Simulation Tick in Unity
After implementing our custom simulation tick, we can start using it in a tycoon game. To demonstrate how this would work, we will use the electricity production and consumption example from earlier. For this basic example, we create an ElectricitySystem class that determines if enough electricity is being produced.
Once the Tick method is called from our Tick Service, the Electricity System calculates both the kWh production and consumption and compares both values. If not enough kWh is being produced, the system will print it to the console. Since the population of the city (consumers) and the power plants (producers) might not change that rapidly, we can simply do a tick every 1-5 seconds.
ElectricitySystem.cs
public class ElectricitySystem { private int numberOfPoducers = 0; private int numberOfConsumers = 0; private int kwhPerProducer = 1000; private int kwhPerConsumer = 10; public void SetProducers(int producers) { numberOfPoducers = producers; } public void SetConsumers(int consumers) { numberOfConsumers = consumers; } public void Tick() { // Called from TickService at custom specified rate int totalKwhProduction = numberOfPoducers * kwhPerProducer; int totalKwHConsumption = numberOfConsumers * kwhPerConsumer; if(totalKwhProduction < totalKwHConsumption) { Debug.Log("There is not enough electricity being produced!"); } } }
Summary
What we hope you have learned from this article
- The simulation logic does not have to run at the same rate as the frame rate
- There are benefits to decoupling your simulation logic from the frame rate.
- A game can have multiple types of simulation ticks
- Determining a simulation tick is about finding a balance between need and priority
- How to implement a custom simulation tick in Unity
- How to use a custom simulation tick to calculate values in other systems

Conclusion
Finally, we hope you now have a better understanding why it is useful to implement a simulation tick for your tycoon game. It can be practical to decouple your simulation completely from Unity. Next to that, we have shown you a way to implement a custom simulation tick in Unity. We did this by implementing a Tick Service class that measures the elapsed time and determines if a simulation tick should occur.
Further Reading
If you found this interesting, you might also like the following articles:
