
Features
Hunter Survivor is a first-person cat-and-mouse prototype game developed in Unreal Engine 5.

Sneak around a randomly generated maze to collect the orbs without getting caught by the hunter cube.
The maze layout and orb spawn points are unique for every playthrough.





Avoid the hunter cube or it will chase you down!

The hunter cube can’t see you while it sleeps, but noise can wake it up.
The hunter cube’s expression shows its current state. Green means it’s wandering, yellow means it’s searching for you, and red means it sees you!




Use stealth mechanics to avoid detection.
The HUD meters measure how visible you are and how much noise you’re making.

Crouching and walking behind walls keeps you quiet and out of sight. Running and jumping through open space raises your noise and visibility levels. Even picking up an orb will alert the cube to your position.

Portals on the edges of the maze help teleport you to the opposite side. And offer an escape when being chased…

Portal C++ Code:
Portal.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SceneCaptureComponent2D.h" // Include scene capture component.
#include "Engine/TextureRenderTarget2D.h" // Include texture render target.
#include "Components/BoxComponent.h" // Include box component.
#include "Components/ArrowComponent.h" // Inlcude arrow component.
#include "Portal.generated.h"
class HunterSurvivorCharacter; // Forward declaration for player character.
UCLASS()
class HUNTERSURVIVOR_API APortal : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
APortal();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Variable for static mesh component.
UPROPERTY(EditAnywhere)
UStaticMeshComponent* mesh;
// Variable for capture component.
UPROPERTY(EditAnywhere, BlueprintReadWrite)
USceneCaptureComponent2D* sceneCapture;
// Variable for arrow component.
UPROPERTY(EditAnywhere)
UArrowComponent* rootArrow;
// Variable for render target.
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UTextureRenderTarget2D* renderTarget;
// Variable for box component.
UPROPERTY(EditAnywhere)
UBoxComponent* boxComp;
// Variable for this class (portal).
UPROPERTY(EditAnywhere)
APortal* OtherPortal;
// Variable for the material interface.
UPROPERTY(EditAnywhere)
UMaterialInterface* mat;
// Function for the overlap of character and portal.
UFUNCTION()
void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
// Function to toggle boolean set in the character class.
UFUNCTION()
void SetBool(AHunterSurvivorCharacter* playerCharacter);
// Function to call teleport.
UFUNCTION()
void UpdatePortals();
};
Portal.cpp
#include "Portal.h"
#include "HunterSurvivorCharacter.h" // Include player character.
#include "Kismet/GameplayStatics.h" // Include kismet gameplay statics.
// Sets default values
APortal::APortal()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Initialize components.
mesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
boxComp = CreateDefaultSubobject<UBoxComponent>("Box Comp");
sceneCapture = CreateDefaultSubobject<USceneCaptureComponent2D>("Capture");
rootArrow = CreateDefaultSubobject<UArrowComponent>("Root Arrow");
// Set attachments.
RootComponent = boxComp; // Box component is the root component.
mesh->SetupAttachment(boxComp); // Mesh is attached to the box component.
sceneCapture->SetupAttachment(mesh); // Scene capture is attached to the mesh.
rootArrow->SetupAttachment(RootComponent); // Attach pivot arrow to the root component.
// Disable the collisions for the mesh so player can walk through portal.
mesh->SetCollisionResponseToAllChannels(ECR_Ignore);
}
// Called when the game starts or when spawned
void APortal::BeginPlay()
{
Super::BeginPlay();
// Call overlap function when player overlaps box component.
boxComp->OnComponentBeginOverlap.AddDynamic(this, &APortal::OnOverlapBegin);
mesh->SetHiddenInSceneCapture(true); // Hide mesh from its own scene capture.
// Validate and set material.
if (mat)
{
mesh->SetMaterial(0, mat);
}
}
// Called every frame
void APortal::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UpdatePortals(); // Call update portal function to spawn portal illusion.
}
// Function for when the player overlaps the portal actor.
void APortal::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
AHunterSurvivorCharacter* playerChar = Cast<AHunterSurvivorCharacter>(OtherActor); // Cast to player character.
if (playerChar) // Validate player character cast.
{
if (OtherPortal) // Validate other portal.
{
if (!playerChar->isTeleporting) // Check to make sure player is not already teleporting.
{
playerChar->isTeleporting = true; // Set player as teleporting to prevent infinite loop.
FVector loc = OtherPortal->rootArrow->GetComponentLocation(); // Set other portal spawn location to arrow.
playerChar->SetActorLocation(loc); // Send player character to the portal's set location.
// Set time to pass player through.
FTimerHandle TimerHandle;
FTimerDelegate TimerDelegate;
TimerDelegate.BindUFunction(this, "SetBool", playerChar);
GetWorld()->GetTimerManager().SetTimer(TimerHandle, TimerDelegate, 1, false);
}
}
}
}
// Function for resetting the teleport status of player.
void APortal::SetBool(AHunterSurvivorCharacter* playerChar)
{
// Set teleport status to false.
if (playerChar)
{
playerChar->isTeleporting = false;
}
}
// Function to move scene capture component.
void APortal::UpdatePortals()
{
FVector Location = this->GetActorLocation() - OtherPortal->GetActorLocation();
FVector camLocation = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetTransformComponent()->GetComponentLocation();
FRotator camRotation = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->GetTransformComponent()->GetComponentRotation();
FVector CombinedLocation = camLocation + Location;
sceneCapture->SetWorldLocationAndRotation(CombinedLocation, camRotation);
}