How to Create an Energy System (That Can’t Easily be Cheated)

Energy
Unity
Author image
Johannes Fornaeus10 min read
Cover image

In games, and especially mobile games like Candy Crush or Archero, it’s not uncommon to introduce a mechanic that gates the player to prevent them from running through content too fast. Mechanics like this could for example be:

  • Lives
  • Energy
  • Cooldowns
  • Idle Earnings

These mechanics often use the device’s time to check if a certain amount of time has passed. So on a mobile device, that would be the local clock and time zone. A problem with this is that players can just set their time manually instead, circumventing any time-gated systems. This allows players to time cheat to for example get more lives, instant energy refills, or big idle earnings.

Thankfully with LootLocker, preventing this type of cheating is very simple. This can be achieved in 4 steps:

  • Create a LootLocker account
  • Install the LootLocker SDK into your game
  • Start a session
  • Check and store the server time

That’s it.

Now, this will not make it completely impossible to time cheat. We’ll store the time on the client's side, so it would be possible for someone to hack the game and change it, but average users will at least not be able to use their device time to do so.

This guide will teach you how to set up a simple lives system using LootLocker using the server's time to check if the user should get a new life or not. For this guide, we will be using Unity Engine 2021.2.12f, but the implementation should work in any recent Unity version.

This implementation is made to be built upon, so if you want to use this implementation for an energy system or offline earning system, or any other type of time-based earning system, there’s not much that needs to change:

To make it into an energy system: Instead of removing a life when a player loses, have your game remove a life whenever the player performs an action, such as starting a level or crafting an item.

To make it into an offline earning system: Use the “timeOffline” variable to calculate how long the player was away and reward them using that variable.

To make it into a cooldown system: Use the “timeOffline” variable to check if it has gone above a certain threshold, if so remove the cooldown.

At the end of this guide, you’ll find the full source code for an example with a lives system, an offline earnings system, and an energy system, as seen in the example gif above. You can also test out our implementation by following the link below:

Foo

Now let’s get started.

Creating a LootLocker account

First, let’s create a LootLocker account and set up the SDK using the links below. These guides will show you how to set up LootLocker with Unity and configure everything so that you’re good to go.

Foo

Foo

We are using Guest Login for this guide, so make sure you enable Guest Login in Platforms on your LootLocker dashboard.

Creating the system

The great thing about this implementation is that it’s not very complex as it just needs a few things to work:

  1. Get the time from the server
    1. For a first time player, set the “game time” to the difference between the server time and a previous date
    2. For a returning player, get the difference between the “game time” and server time
  2. Increase this time as long as the game has focus
  3. If the game loses focus, go to step 1

As you can see the implementation of this mechanic is not complex. You can download the script and the examples that are shown in the gif from the link below.

Foo

Note: If you want to make this into an offline system, the only thing that needs to change is to get the time from the device instead of the server. But we don’t want that, since that would make it possible for our players to easily get more lives or energy by adjusting their clock.

Setting it up

I’ll now walk you through the script for the lives system step by step and explain what happens.

  1. First, we create variables to store the times and information that we need:
  • When the game starts we get the stored values we have for the player and times from PlayerPrefs:
  • Then we start a coroutine called SetupRoutine():
  • SetupRoutine() does a few things:
    1. It starts a guest session
    2. Waits until it receives a response
    3. Sets the bool loggedIn to true
    4. Starts the function UpdateTime()
  • In UpdateTime() we take the server time and calculate the difference since the last time the player was in the game
    1. Ping the server (we’ll get to the updateLifeTime variable further down):
  • Parse the server date into a System.DateTime variable:
  • Create a new dateTime that is earlier than the server time (if it is in the future, the value will be negative, and we don’t want that)
  • Get the difference between these two times
  • We now have a base value for our time. The start date will always be the same, but the server time will not, so if the player is away for 1 second, we will know that by subtracting the gameTime from the difference:
  • If the user hasn’t played before (gameTime == 0), we set the gameTime to the difference, this is the player “starting time”:
  • If the gameTime is not zero, that means it has been set before, so we add the diffSeconds to the gameTime to make the game synchronized with the server:
  • Now we update the new values for our new times:
  • We then check if we should update the value for our timeToGetNewLife variable(we need this for later when we remove a life):
  • Then we run a function to check how many lives we’ve gotten offline and set our timeIsFresh bool to true since we now know that the game and server are synchronized:
  • CalculateLivesGottenOffline() is a simple function, it checks the gameTime against the timeToGetNewLife variable and adds to it whenever it passes, so it will iterate through as many lives as the player can get, and then add a life every time it can:
  • Calculating the time in-game

    We now have all the information from the server that we need to check the status of the gameTime which is what we’ll use to see if the player should get a new life or not.

    In Update() we’ll check if a new life should be added every second. There is no need for us to check more often than that

    1. First we need to know that time is correct
  • Then we check if we can get anymore lives or not:
  • After that we increase the timer, and continue if there was a new second (life timer larger or equals to 1):
  • Increase the gameTime with one second and store the variables:
  • Same as with the function for checking offline, we check if the gameTime has passed the timeToGetNewLife, and if so, we give the player a new life:
  • Then we reset the timer:
  • Correct the time when losing focus

    Now we have the correct time while we are playing the game, but what do we do if the player doesn’t quit the game, but instead just puts the app out of focus? If this happens, we just need to update the time again from the server as we did in Start(). Unity has a built-in function to check if the app lost focus or not, which makes it easy for us:

    When the app loses or gains focus;

    1. Check if we are logged in, if we’re not logged in then don’t do anything:
  • If the game gets focus (the user opened it after it was closed or minimized) we stop the gameTime by setting timeIsFresh to false and then fetch a new time with UpdateTime():
  • Losing a life

    The only thing we have left now is what we do when the player loses a life. Since we don’t count the time when the player’s lives are full (5/5 hearts in our implementation) we don’t know if the server time has been recently checked. Therefore, we need to update the gameTime when removing a life if the player’s lives are full.

    So we need to update the gameTime when removing a life if the life amount is at the max:

    1. Check to see if we should remove the maxAmount life from the player
  • We set our timeIsFresh variable to false, and then we fetch a new time from the server and update timeToGetNewLife by adding a true to UpdateTime():
  • And then we remove a life from the player:
  • Next steps

    And with that, we have a working lives system that is a lot harder to cheat than just turning your device clock backward or forwards in time. As I stated at the beginning of the guide, changing the lives system into another type of energy system is simple. Here are some different use cases:

    An energy system: Instead of removing a life when the player loses, change it to remove a life when the player does an action; starting a level, performing crafting, or similar.

    Offline earning system: Use the “timeOffline” variable to calculate how long the player was away and reward them using that variable.

    Cooldown system: Use the “timeOffline” variable to check if it has gone above a certain threshold, if so remove the cooldown.

    Now, these are just a few of the implementations that this system can be used for. For example, by using the gameTime variable you could reward the player for staying with your game for a long time or reward your players with Loot Boxes or DLC when they have played for a certain amount of time.

    Hopefully, you found this guide quick, simple, and easy. All LootLocker features are quick, simple, and easy to set up and implement.

    Here is the full source code for this project on GitHub:

    Foo

    You can also test out this implementation by using this link:

    Foo

    As usual, if you have any questions, please don't hesitate to get in touch via Twitter or Discord.

    If you like these guides, please let me know by tweeting me directly!

    Stay up to date.

    Join our newsletter and get these posts sent directly to your inbox.