My Building Escape after Iteration Through Valid Actors lecture

Hi There!!

In this lecture, we use the objects in our scene to open the door.

VS Code-

C++ File-

// Copyright Ateeb Ahmed 2021

#include "Engine/World.h"
#include "Components/PrimitiveComponent.h"
#include "GameFramework/PlayerController.h"
#include "OpenDoor.h"
#include "GameFramework/Actor.h"

#define OUT

// Sets default values for this component's properties
UOpenDoor::UOpenDoor()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;
}

// Called when the game starts
void UOpenDoor::BeginPlay()
{
	Super::BeginPlay();
	InitialYaw = GetOwner()->GetActorRotation().Yaw; // Stores the current yaw(Z axis) of the door.
	CurrentYaw = InitialYaw; 
	OpenAngle += InitialYaw;

	if(!PressurePlate)
	{
		UE_LOG(LogTemp, Error, TEXT("%s this actor does not have a pressure plate!!"), *GetOwner()->GetName());
	} 
	if(OpenAngle == 0.0f)
	{
		UE_LOG(LogTemp, Error, TEXT("%s this actor has 0 retation!!"), *GetOwner()->GetName());
	}

	ActorThatOpens = GetWorld()->GetFirstPlayerController()->GetPawn();
}

// Called every frame
void UOpenDoor::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (TotalMassOfActors() > MassToOpenDoors)
	{
		OpenDoor(DeltaTime);
		DoorLastOpened = GetWorld()->GetTimeSeconds();
	}
	else
	{
		if (GetWorld()->GetTimeSeconds() - DoorLastOpened > DoorCloseDelay)
		{
			CloseDoor(DeltaTime);
		}
	}
}

void UOpenDoor::OpenDoor(float DeltaTime)
{
	CurrentYaw = FMath::Lerp(CurrentYaw, OpenAngle, DeltaTime * DoorOpenVelocity); // Changing the yaw to the target yaw
	FRotator DoorRotation = GetOwner()->GetActorRotation(); // Getting the rotation of the door
	DoorRotation.Yaw = CurrentYaw; // Changing yaw of the door
	GetOwner()->SetActorRotation(DoorRotation);
}

void UOpenDoor::CloseDoor(float DeltaTime)
{
	CurrentYaw = FMath::Lerp(CurrentYaw, InitialYaw, DeltaTime * DoorCloseVelocity); // Changing the yaw to the target yaw
	FRotator DoorRotation = GetOwner()->GetActorRotation(); // Getting the rotation of the door
	DoorRotation.Yaw = CurrentYaw; // Changing yaw of the door
	GetOwner()->SetActorRotation(DoorRotation);
}

float UOpenDoor::TotalMassOfActors() const
{
	float TotalMass = 0.f; 

	// Find All Overlapping Actors.
	TArray<AActor*> OverlappingActors;

	// Add up thier Masses.
	if(PressurePlate)
	{
		PressurePlate->GetOverlappingActors(OUT OverlappingActors);
	}
	else
	{
		// UE_LOG(LogTemp, Warning, TEXT("No PressurePlate on: %s"), *GetOwner()->GetName());
	}

	// for(AActor* Actor : OverlappingActors)
	for(AActor* Actor : OverlappingActors)
	{
		TotalMass += Actor->FindComponentByClass<UPrimitiveComponent>()->GetMass();
		UE_LOG(LogTemp, Warning, TEXT("%s is on the pressureplate!"), *Actor->GetName());
	}

	return TotalMass;
}

C File-

// Copyright Ateeb Ahmed 2021

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Engine/TriggerVolume.h"
#include "OpenDoor.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class BUILDING_ESCAPE_API UOpenDoor : public UActorComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	UOpenDoor();

protected:
	// Called when the game starts
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
	void OpenDoor(float DeltaTime);
	void CloseDoor(float DeltaTime);
	float TotalMassOfActors() const;

private:

	float InitialYaw;
	float CurrentYaw;

	UPROPERTY(EditAnywhere)
	float MassToOpenDoors = 50.f;

	UPROPERTY(EditAnywhere)
	float OpenAngle = 70.f;
	
	float DoorLastOpened = 0.f;

	UPROPERTY(EditAnywhere)
	float DoorCloseDelay = 0.5f;

	UPROPERTY(EditAnywhere)
	float DoorOpenVelocity = 0.8f;

	UPROPERTY(EditAnywhere)
	float DoorCloseVelocity = 2.f;

	UPROPERTY(EditAnywhere)
	ATriggerVolume* PressurePlate;

	UPROPERTY(EditAnywhere)
	AActor* ActorThatOpens;

};

Now, I’m using a for loop to iterate through the overlapping actors list and get their mass, add them, and check if it’s greater than the required mass.

Make sure you protect yourself from the null pointers! Check for null pointers in the TotalMassOfActors() function or else UE will crash without any helpful error messages.

UE Editor-

Actors not in PressurePlate-

Actors in PressurePlate-

Now, I can use the cube and cone to open the door and escape!

Previous post: My Building Escape after Refactoring Rules lecture

Thanks for reading,
BYE!!

1 Like

It’s so satisfying to see this working.

1 Like

Privacy & Terms