Battery Collector Undeclaired identifiers (variables out of scope)

Hello, Im following the Battery Collector tutorial (right now im on episode 20) and im getting some undeclaired identifiers errors.
I think its because they are going out of scope since Im declairing them inside the ::BeginPlay part of the code and then trying to use them inside my ::HandleNewState function, but im a newbie so i could be completly wrong.

    void ABatteryCollectorGameMode::BeginPlay()
    {
    	Super::BeginPlay();
    
    	//Find all spawn volume actors.
    	TArray<AActor*> FoundActors;
    	UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASpawnVolume::StaticClass(), FoundActors);
    
    	for (auto Actor : FoundActors)
    	{
    		ASpawnVolume* SpawnVolumeActor = Cast<ASpawnVolume>(Actor);
    		if (SpawnVolumeActor)
    		{
    			SpawnVolumeActors.AddUnique(SpawnVolumeActor);
    		}
    	}

.....

void ABatteryCollectorGameMode::HandleNewState(EBatteryPlayState NewState)
{
	switch (NewState)
	{
	//If the game is playing.
	case EBatteryPlayState::EPlaying:
	{
		//Set spawn volumes to active.
		for (ASpawnVolume* Volume : ASpawnVolumeActors)
		{
			Volume->SetSpawnActive(true);
		}
	}
	break;

	//If we´ve won the game.
	case EBatteryPlayState::EWon:
	{
		//Set spawn volumes to inactive.
		for (ASpawnVolume* Volume : ASpawnVolumeActors)
		{
			Volume->SetSpawnActive(false);
		}
	}
	break;

	//If we´ve lost the game.
	case EBatteryPlayState::EGameOver:
	{
		//Set spawn volumes to inactive.
		for (ASpawnVolume* Volume : ASpawnVolumeActors)
		{
			Volume->SetSpawnActive(false);
		}
		//Block player input.
		//Ragdoll the character.
	}
	break;

	//Unknown / default state.
	default:
	case EBatteryPlayState::EUnknown:
	{

	}
	break;

	}
}

Im getting undeclared identifiers errors on both “ASpawnVolumeActors” and “Volume” witch are created inside the ::BeginPlay,is there a way to fix this, maybe extend the scoope of the TArray that is beeing set up? Or maybe a way to tell the computer where is should look to find them?
I would really love if someone could help with this.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "Blueprint/UserWidget.h"
#include "BatteryCollectorGameMode.generated.h"

//Enum to store the current state of gameplay.
UENUM(BlueprintType)
enum class EBatteryPlayState : uint8
{
	EPlaying,
	EGameOver,
	EWon,
	EUnknown
};

UCLASS(minimalapi)
class ABatteryCollectorGameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	ABatteryCollectorGameMode();

	virtual void Tick(float DeltaTime) override;

	// Returns power needed to win, for the HUD.
	UFUNCTION(BlueprintPure, Category = "Power")
	float GetPowerToWin() const;

	virtual void BeginPlay() override;

	//Returns the current playing state.
	UFUNCTION(BlueprintPure, Category = "Power")
	EBatteryPlayState GetCurrentState() const;

	//Sets a new playing state.
	void SetCurrentState(EBatteryPlayState NewState);


protected:
	// The rate at witch the character loses power.
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Power", Meta = (BlueprintProtected = "true"))
	float DecayRate;

	// The power needed to win the game.
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Power", Meta = (BlueprintProtected = "true"))
	float PowerToWin;

	// The widget class to use for our HUD screen.
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Power", Meta = (BlueprintProtected = "true"))
	TSubclassOf<class UUserWidget> HUDWidgetClass;

	// The instance of the HUD.
	UPROPERTY()
	class UUserWidget* CurrentWidget;

private:
	//Keeps track on the current playing state.
	EBatteryPlayState CurrentState;

	TArray<class ASpawnVolume*> SpawnVolumeActors;

	//Handle any function calls that rely upon changing the playstate of our game.
	void HandleNewState(EBatteryPlayState NewState);
};

I do have my SpawnVolumeActors in there but no mention of the Volume.
By the way thanks for the explenation. :slight_smile:

Can you also share your .h file? If ASpawnVolumeActors and Volume are members of your class (variable inside class definition in .h file) then it is visible from your class methods in .cpp file too. They are not created in ::BeginPlay`` as you wrote. Your BeginPlayjust finds specific actors in the World and then adds them toSpawnVolumeActorscontainer (declared probably in the .h file as a class member). I am also not sure why you have bothASpawnVolumeActorsandSpawnVolumeActorsin your code, maybe it's just a typo? In::BeginPlayyou keep adding actors toSpawnVolumeActorscontainer however in::HandleNewStateyou iterate throughASpawnVolumeActors`. Shouldn’t it be the same container?

Your ABatteryCollectorGameMode.h header file might help.

I couldn´t reply to you with the code for some reason so i put it above in the question. :slight_smile:

I did find SpawnVolumeActors in my header so after reading your comment i cant really wrap my head around why I cant find a definition for atleast that one in my .cpp file.

Alright, you wrote that you have two undeclared identifiers: ASpawnVolumeActors and Volume in your .cpp file.

ASpawnVolumeActors

In your .cpp file you are using this class in 5 different places.

  1. First one is to tell GetAllActorsOfClass which objects you are looking for (objects of which type, which class). Then you store all found objects in FoundActors array.
  2. Second one is being used to cast (“change type” from one to another) generic type AActor to ASpawnVolume type because you know that your FoundActors array has only objects of type ASpawnVolume (see point 1).
  3. Third, fourth and fifth place where this class is being used is in three different for loops where you basically iterate (go through) over your ASpawnVolumeActors container.

In your .h file you do not have ASpawnVolumeActors at all. There is only SpawnVolumeActors (without A at the beginning) which is an Array for ASpawnVolume objects. I guess it’s a typo and you should change ASpawnVolumeActors to SpawnVolumeActors in your .cpp file to fix this issue.

Volume

Volume class is being used in three for loops in your .cpp file. In the line for (ASpawnVolume* Volume : ASpawnVolumeActors) you basically say “hey, please go through all items in ASpawnVolumeActors container (one at a time) and name found object temporarily Volume, och - btw. I know it will be of type ASpawnVolume because ASpawnVolumeActors container stores only objects of this type” (btw. ASpawnVolumeActors should be already renamed to SpawnVolumeActors at this point).

Inside all this for loops you call SetSpawnActive method on each found Volume (object of type ASpawnVolume). When you fix undeclared identifier of ASpawnVolumeActors I think issue with Volume will be fixed automatically.

Thank you so much dptd, you where completly correct, the Volume problem got solved once SpawnVolumeActors where correctly named.
And thank you for the wonderfull, and detailed explenation so i actually understood my mistake and hopefully wont make it again.

No problem, I’m happy I could help. Good luck and have fun with Unreal Engine. :slight_smile: