Need Help: Improving my Custom Locomotion System

I need some help improving my locomotion system.

This is my setup so far:

namespace CndSys_Locomotion

FHitResult Get_Hit_Obstacle_Face(ACndCharacter_Master* CharacterTarget, FGD_CndSys_ODS_Input_Face InputSweepData)
{

	FHitResult HR_Face;

	// Get Data

	FVector CndOwner_Location = InputSweepData.Owner_Location;
	float CndOwner_Height = InputSweepData.Owner_Height;		
	float SweepDistance = InputSweepData.SweepDistance;
	ECndComp_LocomotionSys_SweepType SweepType = InputSweepData.SweepType;

	// Modifies Shape of Face Trace Height
	CharacterTarget->CndSys_ODS.Params.Trace.Face.Height = CndOwner_Height;

	FVector TraceFace_Start = CndOwner_Location;

	FVector TraceFace_End;

	if (SweepType == Velocity)
	{

		FVector CndOwnerVelocity = CndCharacter_Data_Basic::Get_Velocity(CharacterTarget);
		FVector TraceFace_End_Velocity = TraceFace_Start + CndOwnerVelocity.GetSafeNormal() * SweepDistance;

		TraceFace_End = TraceFace_End_Velocity;

	}
	else if (SweepType == Facing)
	{

		FVector CndOwnerForwardVector = CndCharacter_Data_Basic::Get_ForwardVector(CharacterTarget);
		FVector TraceFace_End_Face = TraceFace_Start + CndOwnerForwardVector.GetSafeNormal() * SweepDistance;

		TraceFace_End = TraceFace_End_Face;

	}

	bool Hit = CharacterTarget->GetWorld()->SweepSingleByObjectType(
		HR_Face,
		TraceFace_Start,
		TraceFace_End,
		FQuat::Identity,
		CharacterTarget->CndSys_ODS.Params.CollisionObjectQueryParams,
		CharacterTarget->CndSys_ODS.Params.Trace.Face.Shape,
		CharacterTarget->CndSys_ODS.Params.CollisionQueryParams
	);

	if (CharacterTarget->CO_ELS->ELS_DebugEnabled)
	{
		// Draw the capsule trace path
		FColor TraceColor = HR_Face.bBlockingHit ? FColor::Red : FColor::Green;

		DrawDebugCapsule(CharacterTarget->GetWorld(),
			TraceFace_End,
			CharacterTarget->CndSys_ODS.Params.Trace.Face.Height,
			CharacterTarget->CndSys_ODS.Params.Trace.Face.Radius,
			FQuat::Identity,
			TraceColor,
			false,
			0.0f
		);

		DrawDebugLine(CharacterTarget->GetWorld(),
			TraceFace_Start,
			TraceFace_End,
			TraceColor,
			false,
			0.0f
		);

		if (HR_Face.bBlockingHit)
		{

		DrawDebugSphere(
			CharacterTarget->GetWorld(),
			HR_Face.ImpactPoint,
			10.0f, // Radius
			CharacterTarget->CndSys_ODS.Params.Trace.Ground.Segments,
			TraceColor,
			false,
			0.0f
		);

		}
	}

	return HR_Face;
}
FHitResult Get_Hit_Obstacle_Top(ACndCharacter_Master* CharacterTarget, FGD_CndSys_ODS_Input_Height InputSweepData)
{

	FHitResult HR_HeightCheck;

	FVector Wall_Location = InputSweepData.Location;
	FVector Wall_Normal = InputSweepData.Normal;
	float Owner_Height = InputSweepData.Owner_Height;

	FRotator Normal_RotFromX = FRotationMatrix::MakeFromX(Wall_Normal).Rotator();
	FVector Normal_ForwardVector = Normal_RotFromX.Vector(); // Same as GetForwardVector()

	float Height_Owner = Owner_Height;

	FVector LocAndNormal = Wall_Location + Normal_ForwardVector;

	FVector TraceDown_Start = LocAndNormal + FVector(0.0, 0.0, Height_Owner);
	FVector TraceDown_End = LocAndNormal - FVector(0.0, 0.0, Height_Owner);


	bool Hit = CharacterTarget->GetWorld()->SweepSingleByObjectType(
		HR_HeightCheck,
		TraceDown_Start,
		TraceDown_End,
		FQuat::Identity,
		CharacterTarget->CndSys_ODS.Params.CollisionObjectQueryParams,
		CharacterTarget->CndSys_ODS.Params.Trace.Down.Shape,
		CharacterTarget->CndSys_ODS.Params.CollisionQueryParams
	);

	if (CharacterTarget->CO_ELS->ELS_DebugEnabled)
	{

		FColor TraceColor = HR_HeightCheck.bBlockingHit ? FColor::Yellow : FColor::Magenta;

		DrawDebugSphere(
			CharacterTarget->GetWorld(),
			TraceDown_Start,
			CharacterTarget->CndSys_ODS.Params.Trace.Down.Radius,
			CharacterTarget->CndSys_ODS.Params.Trace.Down.Segments,
			TraceColor,
			false,
			0.0f, // Lifetime
			0, // Depth Priority (Front Visibility)
			0.50f // Thickness 
		);

		DrawDebugLine(CharacterTarget->GetWorld(),
			TraceDown_Start,
			TraceDown_End,
			TraceColor,
			false,
			0.0f, // Lifetime
			0, // Depth Priority (Front Visibility)
			1.0f // Thickness
		);

		DrawDebugSphere(
			CharacterTarget->GetWorld(),
			TraceDown_End,
			CharacterTarget->CndSys_ODS.Params.Trace.Down.Radius,
			CharacterTarget->CndSys_ODS.Params.Trace.Down.Segments,
			TraceColor,
			false,
			0.0f, // Lifetime
			0, // Depth Priority
			0.50f // Thickness
		);

		DrawDebugSphere(
			CharacterTarget->GetWorld(),
			HR_HeightCheck.ImpactPoint,
			5.0f, // Radius
			CharacterTarget->CndSys_ODS.Params.Trace.Down.Segments,
			FColor::Magenta,
			false,
			0.0f, // Lifetime
			0, // Depth Priority
			1.0f // Thickness
		);

	}

	return HR_HeightCheck;

}

FGD_CndSys_ObstacleDetection_Results_Obstacle Get_ObstacleData(ACndCharacter_Master* CharacterTarget, ECndComp_LocomotionSys_SweepType SweepType)
{

	FVector Owner_Location = CndCharacter_Data_Basic::Get_Location(CharacterTarget);
	float Target_Height = CndCharacter_Data_Params::Get_Height_Current(CharacterTarget);	

	// Step 01: Input Data for Face Sweep
	FGD_CndSys_ODS_Input_Face FaceSweep_Data;

	FaceSweep_Data.Owner_Location = Owner_Location;
	FaceSweep_Data.Owner_Height = Target_Height;
	FaceSweep_Data.SweepDistance = CharacterTarget->CndSys_ODS.Settings.Range.Springboard;
	FaceSweep_Data.SweepType = SweepType;

	// Then Sweep Capsule Forward, using Facing / Velocity sweep type.

	// Step 02: Get Results from Facing/Velocity sweep.
	FHitResult HR_Face = Get_Hit_Obstacle_Face(CharacterTarget, FaceSweep_Data);

	// Step 03: Input Data for Height Sweep
	FGD_CndSys_ODS_Input_Height HeightSweep_Data;

	HeightSweep_Data.Location = HR_Face.Location;
	HeightSweep_Data.Normal = HR_Face.Normal;
	HeightSweep_Data.Owner_Height = Target_Height;

	// Step 04: Trace Line Down from Owner's Height
	FHitResult HR_Height = Get_Hit_Obstacle_Top(CharacterTarget, HeightSweep_Data);

	// Step 05: Check if there's room.

	// Step 06: Get Obstacle Data
	FGD_CndSys_ObstacleDetection_Results_Obstacle Obstacle;

	Obstacle.bHit = HR_Face.bBlockingHit;
	Obstacle.Top = HR_Height.Location;

	return Obstacle;
}

  1. I want to build and rely on my own Locomotion System.

  2. Tutorials, like LocoDev’s Vaulting Tutorial only covers the line-trace, which is useless for my types of vaultable obstacles (varying with height and spaces between/below them). Hence where Capsule Sweep is needed here.

  3. I’m trying to make it coop with climbing up the vents.

Basically, what I want is to get better apex of the vaultable obstacle, obstacle thickness, the room on the other side of the obstacle, so I can trace down, if there’s ground. And also to coop with climbing up the vents.

But first, I wanna focus on vaultable obstacles.

And that’s how it all works so far: