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;
}
-
I want to build and rely on my own Locomotion System.
-
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.
-
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: