sábado, 5 de dezembro de 2020

For loops and TActorRange

In the C++ language, a loop is used to repeat a block of code while a specified condition is true. One type of loop is the for statement.

The code below shows an example of using the for statement. The TotalEnemies variable stores the number of enemies that must be created at the level. The Counter variable is incremented with each execution of the for loop. The code block of the for loop will be repeated while the value of Counter is less than the value of TotalEnemies. Ten instances of the AEnemyActor class will be created at random locations in the level.  

int32 TotalEnemies = 10;
int32 Counter;
float XPosition;
float YPosition;
	
FVector  SpawnLocation;
FRotator SpawnRotation = FRotator(0.0f, 0.0f, 0.0f);
	
for(Counter = 0; Counter < TotalEnemies; Counter++)
{
  XPosition = FMath::RandRange(-1000, 1000);
  YPosition = FMath::RandRange(-1000, 1000);
		
  SpawnLocation = FVector(XPosition, YPosition, 130.0f);
		
  GetWorld()->SpawnActor<AEnemyActor>(AEnemyActor::StaticClass(),
                                      SpawnLocation, SpawnRotation );
}

The for statement has a variation called ranged-based for loop. In this type of for, a variable is declared to store the current element of a group of elements. The code block will be repeated until all elements have been used. The ranged-based for loop has this format: 

for(variable : range_expression) 
{

}

Unreal TArray, TMap and TSet containers work with ranged-based for loop.

Unreal Engine has a C++ template called TActorRange that provides a range expression representing the instances of a given class that are present at the level. The ranged-based for loop below uses TActorRange to toggle the visibility of all instances of the APointLight class on the level.

for (APointLight* PointLightInstance : TActorRange<APointLight>( GetWorld() ) )
{	
  PointLightInstance->GetLightComponent()->ToggleVisibility();
}

The APointLight class contains a LightComponent that has the ToggleVisibility() function.

The APointLight instances at the level need to be Movable so that they can have their visibility modified, as we will see in the example usage.


Example usage:

For this example, you will need a C++ project that has the Third Person template. We will add several Point Light Actors to the level and toggle their visibility by pressing the Enter key.

First, let's create an input mapping called PressSwitch that will be triggered when the player presses the Enter key.

In the level editor, access the Edit->Project Settings... menu and in the Engine category choose the Input option. Click the + symbol next to Action Mappings, enter the name PressSwitch for the new Action Mapping, and select the Enter key. The Action Mappings for the project will look like this:

Now we are going to modify the C++ code. Open the Character class header file created by the Third Person template. The default file name is ProjectNameCharacter.h. For example, the name of my project is TutoProject, and the name of the header file is TutoProjectCharacter.h.

In the header file, add the declaration of the ToggleLights() function below the SetupPlayerInputComponent() function:

protected:
  // APawn interface
  virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
                                                                             override;
  // End of APawn interface

  void ToggleLights();
  

In the Character cpp file, you must add these #include lines at the beginning of the file:

#include "Engine/PointLight.h"
#include "Components/LightComponent.h"
#include "EngineUtils.h"
#include "Engine/World.h"

In the SetupPlayerInputComponent() function, the Input PressSwitch will be bound with the ToggleLights() function, after the Input ResetVR. Change the name ATutoProjectCharacter to the name of your project's Character class and don't forget to put the & operator before the name. It is used to return the memory address of the function. 

PlayerInputComponent->BindAction("ResetVR", IE_Pressed, this,
                                 &ATutoProjectCharacter::OnResetVR);

PlayerInputComponent->BindAction("PressSwitch", IE_Pressed, this,
                                 &ATutoProjectCharacter::ToggleLights);

At the end of the cpp file, create the function ToggleLights() with the content below. Don't forget to change the name of the class that is before the "::" operator. 

void ATutoProjectCharacter::ToggleLights()
{ 
  for (APointLight* PointLightInstance : TActorRange<APointLight>( GetWorld() ) )
  {
    PointLightInstance->GetLightComponent()->ToggleVisibility();
  }	
}

Compile the C++ code. To test our example, we need to add instances of Point Light at the level. Access the Place Actors tab, Basic category. Drag some Point Lights and drop them on one of the walls of the level. 


Select each of the Point Light instances and change the Mobility property to Movable.


Start the game and go near the Point Light instances. Press the Enter key to turn the Point Lights off and on.



Table of Contents C++