sexta-feira, 14 de agosto de 2020

Creating a Timer in Unreal C++

One of the values displayed on the screen is from the Time variable that stores the time remaining to end the game. In another article, we will see how to draw the values of the variables on the screen.


The Time variable starts with the value 30. We need a way to decrease 1 of the value of this variable every second. To do this we are going to create a Timer. A Timer allows a function to be executed after the specified time has passed. This function can be performed only once or periodically.

Before creating a Timer, we will need a variable of type FTimerHandle that will be used to reference the Timer that will be created. It will also be necessary to create a function that will be executed by the Timer. The function will be called Clock().

Open the file TutoProjectGameMode.h, place the variable TimerHandleClock and the declaration of the Clock() function in the protected block below the BeginPlay() function as shown below. 
...
protected:
	int32 PlayerLevel;

	int32 Score;

	int32 ItemCount;

	int32 Time;

	bool  bGameOver;

	virtual void BeginPlay() override;

	FTimerHandle TimerHandleClock;

	void Clock();
};

A running game has a Timer Manager that can be accessed using the GetWorldTimerManager() function on any AActor subclass. The Timer Manager has a function called SetTimer() used to create a Timer.

We will place the creation of the Timer inside the StartGame() function that is in the file TutoProjectGameMode.cpp. The StartGame() function will have this content:
void ATutoProjectGameMode::StartGame()
{
  Score = 0;
  PlayerLevel = 1;
  ItemCount = 0;
  Time = 30;
  bGameOver = false;

  GetWorldTimerManager().SetTimer(TimerHandleClock, this, &ATutoProjectGameMode::Clock,
                                  1.0f, true);
}

The SetTimer() function is receiving five parameters, let's analyze the function call and each of the parameters:
  • GetWorldTimerManager().SetTimer() : The first thing that happens on this line is the execution of the GetWorldTimerManager() function that returns an FTimeManager instance. After that, the SetTimer() function of the FTimeManager instance that was returned is executed. 
  • TimerHandleClock : This is the first parameter of the SetTimer() function. TimerHandleClock is the variable of type FTimerHandle that we created. It will be filled with the necessary information so that we can later reference the Timer that was created. 
  • this : This is a C++ keyword that references the instance that is currently running. It is similar to the word Self used in Blueprints. 
  • &ATutoProjectGameMode::Clock : In this parameter, we inform which is the function that will be executed by the Timer. Note that before the function identification there is the & operator. This operator is used to return the function's memory address. The function identification consists of the class name, the scope resolution operator :: and the function name without parentheses. 
  • 1.0f : This parameter indicates the time in seconds that the Timer must wait before executing the function. This is a float value. We will analyze the float type in another article. 
  • true : This Boolean parameter is Loop. If true then the Timer will execute the function periodically. If false, the function will be executed only once. 
 
The SetTimer() function is equivalent to the Blueprint node called Set Timer by Function Name which is in the image below. 


We just need to define the Clock() function to finish our Timer. Add the code below at the end of the file TutoProjectGameMode.cpp
void ATutoProjectGameMode::Clock()
{
  if (Time > 0)
  {
    Time--;
  } 
  else
  {
    bGameOver = true;
    GetWorldTimerManager().ClearTimer(TimerHandleClock);
  }
}
The Timer executes the Clock() function once per second. We use the if conditional to test whether the value of the Time variable is greater than zero. If it is true then the Time variable is decremented, that is, its value is decreased by 1.

If the result of the if expression is false, then the else block will be executed. In the else block, the Boolean variable bGameOver receives the value true to indicate that the game is over. Then the ClearTime() function is called to stop the Timer that we created.