ECOPOINT
David and Goliath, Action-Adventure, UE Tech Showcase
Overview
Project Duration
9 Weeks at PlaygroundSquad
Game Engine
Unreal Engine 5.4
Platforms
PC
Responsibilities
Character Controller
Movement
Grapple hook
Climbing
Rolling
Optimization & Performance
Nanite
Lumen
Raytracing
This is a showcase of what I made during the project
Developed with a team of 14 members (5 programmers, 2 designers, and 7 artists)
Unlike the past projects I wanted to showcase my knowledge deeper rather than working on something new, thus I decided to work on the character aspect of the game.
This was one of the most difficult tasks I did during PlaygroundSquad due to the sheer scale of the project, everything from making PCG (Procedural Content Generation) to work well to having lumen & nanite work hand in hand with the overall environment.
Though I have explained more in detail about technical more than gameplay, this is by design, due to the nature of this project, we wanted to focus more on what a group of students can do in 9 weeks in the sense of using Unreal Engine.
I hope you enjoy exploring this project, and look deeper at what I contributed to the game!
Character Controller
Grapple & Climbing
void UPlayerGrappleComponent::OnGrappleHit(TObjectPtr<AActor> HitActor, const FVector& HitLocation, const FHitResult& HitResult)
Uses a cable component to know what object to grapple towards
GrappledComponent = HitResult.GetComponent();
LocalHitLocation = GrappledComponent->GetComponentTransform().InverseTransformPosition(HitLocation);
PlayerCharacter->CurrentPlayerState = Grappling;
GetWorld()->GetTimerManager().SetTimer(PullWaitTimeHandle, this, &UPlayerGrappleComponent::StartPulling, PullWaitTime, false);
PlayerCharacter->bIsInputAllowed = false;
GrappleCable->AttachToComponent(PlayerCharacter->GetRootComponent(), FAttachmentTransformRules::SnapToTargetNotIncludingScale);
GrappleCable->EndLocation = PlayerCharacter->GetActorTransform().InverseTransformPosition(TargetLocation);
void UPlayerGrappleComponent::PullTowardsTarget(float DeltaTime)
When pulling towards target that is moving, we used the local hit location of the grapple component to be able to move our player with it
if (GrappledComponent)
{
TargetLocation = GrappledComponent->GetComponentTransform().TransformPosition(LocalHitLocation);
}
FVector CurrentLocation = PlayerCharacter->GetActorLocation();
float DistanceToTarget = FVector::Dist(CurrentLocation, TargetLocation);
FVector NewLocation = FMath::VInterpTo(CurrentLocation, TargetLocation, DeltaTime, PullingSpeed / DistanceToTarget);
GrappleCable->EndLocation = PlayerCharacter->GetActorTransform().InverseTransformPosition(TargetLocation);
PlayerCharacter->bIsInputAllowed = false;
if (DistanceToTarget <= 60.0f)
{
CurrentGrappleState = Holding;
}
PlayerCharacter->SetActorLocation(NewLocation);
Challenges
Optimization
GPU/CPU profiling is something I am glad I worked as much as I did during this project due to the nature of researching this topic gave me a lot of contrary solutions, knowing this the way we worked ensured fast iteration without losing performance or fidelity
Performance
We knew performance would be an issue even before starting, that is why I became the "Lead" Optimizer, this was mostly due to my own initiative but also because of my past work on Rocket Rider
Solutions & Outcome
Nanite
We had struggles getting nanite to work properly with our world, everything from artifacting to frame time issues, one of the solutions to this was changing the dicing rate (the rate of which nanite clusters are created)
Performance
As mentioned, we opted to go all out when talking about Unreal Engine tech, lumen and ray tracing being the 2 major problems we dealt with.
Due to the nature of the project we opted to use emissives as light sources instead of real light, which gave us an overall better boost to performance with quality still matching our intentions.