Robot Nav Path Spline Updates
- Robots now generate the spline based on their input type - There is now a curve generated with the spline with speed values for any distance along the spline
This commit is contained in:
parent
b0fec0cc7a
commit
a028ed8caf
Binary file not shown.
BIN
Content/Developers/Wdev/Robots/NewBlueprint.uasset
Normal file
BIN
Content/Developers/Wdev/Robots/NewBlueprint.uasset
Normal file
Binary file not shown.
@ -3,14 +3,13 @@
|
|||||||
|
|
||||||
#include "Gameplay/Robot/Components/Movement/LRMC_Stretch.h"
|
#include "Gameplay/Robot/Components/Movement/LRMC_Stretch.h"
|
||||||
#include "Actors/MujocoVolumeActor.h"
|
#include "Actors/MujocoVolumeActor.h"
|
||||||
|
#include "Gameplay/Robot/LuckyRobotPawnBase.h"
|
||||||
|
|
||||||
|
|
||||||
void ULRMC_Stretch::PerformMovement(float DeltaTime, const ERobotInputHandlingMethod InputHandlingMethod, const ERobotInputType InputType, const FVector2D& InputValues)
|
void ULRMC_Stretch::PerformMovement(float DeltaTime, const ERobotInputHandlingMethod InputHandlingMethod, const ERobotInputType InputType, const FVector2D& InputValues)
|
||||||
{
|
{
|
||||||
Super::PerformMovement(DeltaTime, InputHandlingMethod, InputType, InputValues);
|
Super::PerformMovement(DeltaTime, InputHandlingMethod, InputType, InputValues);
|
||||||
|
|
||||||
constexpr float TurnMod = 0.1f;
|
|
||||||
|
|
||||||
// we can not do this because the rear actuator is not being used, so Turn would always override Move every frame with a value of 0.f
|
// we can not do this because the rear actuator is not being used, so Turn would always override Move every frame with a value of 0.f
|
||||||
//Move(InputValues.X);
|
//Move(InputValues.X);
|
||||||
//Turn(InputValues.Y * TurnMod);
|
//Turn(InputValues.Y * TurnMod);
|
||||||
@ -38,7 +37,7 @@ void ULRMC_Stretch::PerformMovement(float DeltaTime, const ERobotInputHandlingMe
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Turn(InputValues.Y * TurnMod);
|
Turn(InputValues.Y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERobotInputType::Pathfinding:
|
case ERobotInputType::Pathfinding:
|
||||||
@ -54,7 +53,7 @@ void ULRMC_Stretch::PerformMovement(float DeltaTime, const ERobotInputHandlingMe
|
|||||||
case ERobotInputType::Turn:
|
case ERobotInputType::Turn:
|
||||||
{
|
{
|
||||||
PreviousInputType = ERobotInputType::Turn;
|
PreviousInputType = ERobotInputType::Turn;
|
||||||
Turn(InputValues.Y * TurnMod);
|
Turn(InputValues.Y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERobotInputType::Pathfinding:
|
case ERobotInputType::Pathfinding:
|
||||||
@ -75,7 +74,8 @@ void ULRMC_Stretch::Turn(const float InValue) const
|
|||||||
{
|
{
|
||||||
if (GetMujocoVolumeActor())
|
if (GetMujocoVolumeActor())
|
||||||
{
|
{
|
||||||
GetMujocoVolumeActor()->SetActuatorValueByIndex(0, -InValue);
|
const float TurnMod = GetOwningRobot() ? GetOwningRobot()->GetTurnModifier() : 1.f;
|
||||||
GetMujocoVolumeActor()->SetActuatorValueByIndex(1, InValue);
|
GetMujocoVolumeActor()->SetActuatorValueByIndex(0, InValue * -TurnMod);
|
||||||
|
GetMujocoVolumeActor()->SetActuatorValueByIndex(1, InValue * TurnMod);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,192 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Gameplay/Robot/Data/RobotSettings.h"
|
||||||
|
#include "Components/SplineComponent.h"
|
||||||
|
#include "Gameplay/Robot/LuckyRobotPawnBase.h"
|
||||||
|
#include "Kismet/KismetMathLibrary.h"
|
||||||
|
|
||||||
|
void FRobotSplinePath::GenerateSplinePath(ALuckyRobotPawnBase* InRobot, const FRobotNavPath& InNavPath)
|
||||||
|
{
|
||||||
|
if (IsValid(InRobot) && !InNavPath.NavPoints.IsEmpty())
|
||||||
|
{
|
||||||
|
Robot = InRobot;
|
||||||
|
NavPath = InNavPath;
|
||||||
|
|
||||||
|
if (GetRobot())
|
||||||
|
{
|
||||||
|
USplineComponent* OldSplinePath = GetSplinePath();
|
||||||
|
|
||||||
|
if (UActorComponent* NewComp = GetRobot()->AddComponentByClass(USplineComponent::StaticClass(), false, FTransform::Identity, false))
|
||||||
|
{
|
||||||
|
if (USplineComponent* NewSplineComp = Cast<USplineComponent>(NewComp))
|
||||||
|
{
|
||||||
|
NewSplineComp->ClearSplinePoints();
|
||||||
|
NewSplineComp->SetAbsolute(true, true, true);
|
||||||
|
int32 PointIndex = 0;
|
||||||
|
for (auto const& NavPoint : NavPath.NavPoints)
|
||||||
|
{
|
||||||
|
NewSplineComp->AddSplinePointAtIndex(NavPoint.Location, PointIndex, ESplineCoordinateSpace::World, false);
|
||||||
|
PointIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewSplineComp->UpdateSpline();
|
||||||
|
SplinePath = NewSplineComp;
|
||||||
|
RegenerateSplinePathValues();
|
||||||
|
|
||||||
|
// begin debug
|
||||||
|
if (GetSplinePath())
|
||||||
|
{
|
||||||
|
GetSplinePath()->SetVisibility(true);
|
||||||
|
GetSplinePath()->SetHiddenInGame(false);
|
||||||
|
}
|
||||||
|
// end debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsValid(OldSplinePath))
|
||||||
|
{
|
||||||
|
OldSplinePath->DestroyComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FRobotSplinePath::RegenerateSplinePathValues()
|
||||||
|
{
|
||||||
|
if (GetRobot() && GetSplinePath())
|
||||||
|
{
|
||||||
|
constexpr float SplinePredictionTime = 1.f;
|
||||||
|
constexpr float SplinePredictionDistanceMin = 64.f;
|
||||||
|
const float SpeedLimit = GetRobot()->RobotSettings.SpeedLimit;
|
||||||
|
const float TargetSpeed = FMath::Min<float>(GetRobot()->GetTargetSpeed(), SpeedLimit);
|
||||||
|
const float SplinePredictionDistance = FMath::Max<float>(SplinePredictionTime * TargetSpeed, SplinePredictionDistanceMin);
|
||||||
|
constexpr float TangentClamp = 128.f;
|
||||||
|
const int32 SplinePoints = GetSplinePath()->GetNumberOfSplinePoints();
|
||||||
|
|
||||||
|
const bool bSingleInput = GetRobot()->RobotSettings.InputHandlingMethod == ERobotInputHandlingMethod::SingleInput;
|
||||||
|
|
||||||
|
if (bSingleInput)
|
||||||
|
{
|
||||||
|
for (int32 x = 0; x < SplinePoints; x++)
|
||||||
|
{
|
||||||
|
GetSplinePath()->SetTangentAtSplinePoint(x, FVector::ZeroVector, ESplineCoordinateSpace::Local, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int32 x = 0; x < SplinePoints; x++)
|
||||||
|
{
|
||||||
|
if (x < SplinePoints)
|
||||||
|
{
|
||||||
|
GetSplinePath()->SetSplinePointType(x, ESplinePointType::CurveCustomTangent, false);
|
||||||
|
|
||||||
|
const FVector PointLoc1 = GetSplinePath()->GetSplinePointAt(x - 1, ESplineCoordinateSpace::World).Position;
|
||||||
|
const FVector PointLoc2 = GetSplinePath()->GetSplinePointAt(x, ESplineCoordinateSpace::World).Position;
|
||||||
|
const FVector PointLoc3 = GetSplinePath()->GetSplinePointAt(x + 1, ESplineCoordinateSpace::World).Position;
|
||||||
|
const float Distance1 = FVector::Dist(PointLoc1, PointLoc2);
|
||||||
|
const float Distance2 = FVector::Dist(PointLoc2, PointLoc3);
|
||||||
|
|
||||||
|
constexpr float PointDistanceMod = 0.33f;
|
||||||
|
const float TangentMin = FMath::Min<float>(SplinePredictionDistance * 10.f, TangentClamp);
|
||||||
|
const FVector ArriveTangent = (PointLoc3 - PointLoc1).GetSafeNormal() * FMath::Min<float>(Distance1 * PointDistanceMod, TangentMin);
|
||||||
|
const FVector LeaveTangent = (PointLoc3 - PointLoc1).GetSafeNormal() * FMath::Min<float>(Distance2 * PointDistanceMod, TangentMin);
|
||||||
|
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("RegenerateSplinePathValues ArriveTangent (%s)"), *ArriveTangent.ToString());
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("RegenerateSplinePathValues LeaveTangent (%s)"), *LeaveTangent.ToString());
|
||||||
|
|
||||||
|
GetSplinePath()->SetTangentsAtSplinePoint(x, ArriveTangent, LeaveTangent, ESplineCoordinateSpace::World, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetSplinePath()->UpdateSpline();
|
||||||
|
const float SplineLength = GetSplinePath()->GetSplineLength();
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.Reset();
|
||||||
|
constexpr float MinSpeedMod = 0.2f;
|
||||||
|
constexpr float SplinePrecision = 10.f;
|
||||||
|
|
||||||
|
if (bSingleInput)
|
||||||
|
{
|
||||||
|
constexpr float SectionSpeedMod = 0.4f;
|
||||||
|
const float SectionSpeedClamp = FMath::Min<float>(SpeedLimit * SectionSpeedMod, TargetSpeed);
|
||||||
|
const float DecelerationStep = SplinePredictionDistance + SplinePrecision;
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(0.f, SectionSpeedClamp);
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SplineLength, TargetSpeed * MinSpeedMod);
|
||||||
|
|
||||||
|
const float FirstSectionEnd = GetSplinePath()->GetDistanceAlongSplineAtSplinePoint(1);
|
||||||
|
if (FirstSectionEnd >= DecelerationStep)
|
||||||
|
{
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SplinePrecision, TargetSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 y = 1; y < SplinePoints; y++)
|
||||||
|
{
|
||||||
|
const float SectionStart = GetSplinePath()->GetDistanceAlongSplineAtSplinePoint(y - 1);
|
||||||
|
const float SectionEnd = GetSplinePath()->GetDistanceAlongSplineAtSplinePoint(y);
|
||||||
|
const float SectionDistance = SectionEnd - SectionStart;
|
||||||
|
|
||||||
|
if (SectionDistance >= DecelerationStep)
|
||||||
|
{
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SectionEnd - SplinePredictionDistance, SectionSpeedClamp);
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SectionEnd - DecelerationStep, TargetSpeed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SectionStart, SectionSpeedClamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SectionEnd, SectionSpeedClamp);
|
||||||
|
|
||||||
|
if (y < SplinePoints)
|
||||||
|
{
|
||||||
|
const float NextSectionEnd = GetSplinePath()->GetDistanceAlongSplineAtSplinePoint(y + 1);
|
||||||
|
const float NextSectionDistance = NextSectionEnd - SectionEnd;
|
||||||
|
|
||||||
|
if (NextSectionDistance >= DecelerationStep)
|
||||||
|
{
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SectionEnd + SplinePrecision, TargetSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int32 SplineIntervals = UKismetMathLibrary::SafeDivide(SplineLength, SplinePrecision);
|
||||||
|
for (int32 z = SplineIntervals; z >= 0; z--)
|
||||||
|
{
|
||||||
|
if (z == 0)
|
||||||
|
{
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(0.f, TargetSpeed * MinSpeedMod);
|
||||||
|
}
|
||||||
|
else if (z == SplineIntervals)
|
||||||
|
{
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SplineLength, TargetSpeed * MinSpeedMod);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
constexpr float MaxSpeedMod = 1.f;
|
||||||
|
const float SplineDistance = z * SplinePrecision;
|
||||||
|
const float DistanceToPathEnd = SplineLength - SplineDistance;
|
||||||
|
const float PathEndMod = DistanceToPathEnd <= SplinePredictionDistance ? FMath::Max<float>(UKismetMathLibrary::SafeDivide(DistanceToPathEnd, SplinePredictionDistance), 0.f) : 1.f;
|
||||||
|
const FVector IntervalTangent = GetSplinePath()->GetTangentAtDistanceAlongSpline(SplineDistance, ESplineCoordinateSpace::Local);
|
||||||
|
const float IntervalCurve = FMath::Min<float>(IntervalTangent.Length(), TangentClamp);
|
||||||
|
const float IntervalAlpha = UKismetMathLibrary::SafeDivide(IntervalCurve, TangentClamp);
|
||||||
|
const float SpeedMod = (MaxSpeedMod - IntervalAlpha) * PathEndMod;
|
||||||
|
const float ClampedSpeed = FMath::Min<float>(SpeedLimit * SpeedMod, SpeedLimit * MinSpeedMod);
|
||||||
|
SplinePathSpeedModifier.EditorCurveData.AddKey(SplineDistance, ClampedSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// begin debug
|
||||||
|
|
||||||
|
const int32 SplineIntervals = UKismetMathLibrary::SafeDivide(SplineLength, SplinePrecision);
|
||||||
|
for (int32 z = SplineIntervals; z >= 0; z--)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("SpeedCurveValue [%f :: %f]"), z * SplinePrecision, SplinePathSpeedModifier.EditorCurveData.Eval(z * SplinePrecision));
|
||||||
|
}
|
||||||
|
|
||||||
|
// end debug
|
||||||
|
}
|
||||||
|
}
|
@ -56,8 +56,6 @@ void ALuckyRobotPawnBase::InitializeMovementComponent()
|
|||||||
|
|
||||||
void ALuckyRobotPawnBase::BeginPlay()
|
void ALuckyRobotPawnBase::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
|
||||||
|
|
||||||
InitializeMujocoVolumeActor();
|
InitializeMujocoVolumeActor();
|
||||||
InitializeMovementComponent();
|
InitializeMovementComponent();
|
||||||
|
|
||||||
@ -66,7 +64,10 @@ void ALuckyRobotPawnBase::BeginPlay()
|
|||||||
GetLuckyWorldSubsystem()->RegisterLuckyRobot(this);
|
GetLuckyWorldSubsystem()->RegisterLuckyRobot(this);
|
||||||
|
|
||||||
GetLuckyWorldSubsystem()->TargetSpeedChanged.AddUniqueDynamic(this, &ALuckyRobotPawnBase::SetTargetSpeed);
|
GetLuckyWorldSubsystem()->TargetSpeedChanged.AddUniqueDynamic(this, &ALuckyRobotPawnBase::SetTargetSpeed);
|
||||||
|
GetLuckyWorldSubsystem()->RobotNavPathChanged.AddUniqueDynamic(this, &ALuckyRobotPawnBase::SetRobotNavPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Super::BeginPlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ALuckyRobotPawnBase::HasMovementValue() const
|
bool ALuckyRobotPawnBase::HasMovementValue() const
|
||||||
@ -123,6 +124,8 @@ void ALuckyRobotPawnBase::SetupPlayerInputComponent(UInputComponent* PlayerInput
|
|||||||
EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Completed, this, &ALuckyRobotPawnBase::TurnStop);
|
EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Completed, this, &ALuckyRobotPawnBase::TurnStop);
|
||||||
|
|
||||||
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ALuckyRobotPawnBase::Look);
|
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ALuckyRobotPawnBase::Look);
|
||||||
|
|
||||||
|
EnhancedInputComponent->BindAction(TogglePathfindingAction, ETriggerEvent::Started, this, &ALuckyRobotPawnBase::TogglePathfinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,6 +253,12 @@ void ALuckyRobotPawnBase::Look(const FInputActionValue& Value)
|
|||||||
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: Look (%s)"), *Value.Get<FVector2D>().ToString());
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: Look (%s)"), *Value.Get<FVector2D>().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::TogglePathfinding(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
PreviousInputType = ERobotInputType::None;
|
||||||
|
CurrentInputType = IsPathfinding() ? ERobotInputType::None : ERobotInputType::Pathfinding;
|
||||||
|
}
|
||||||
|
|
||||||
void ALuckyRobotPawnBase::RemoveMujocoVolumeActor()
|
void ALuckyRobotPawnBase::RemoveMujocoVolumeActor()
|
||||||
{
|
{
|
||||||
if (GetMujocoVolumeActor())
|
if (GetMujocoVolumeActor())
|
||||||
@ -276,6 +285,18 @@ ULuckyWorldSubsystem* ALuckyRobotPawnBase::GetLuckyWorldSubsystem()
|
|||||||
return LuckyWorldSubsystem.Get();
|
return LuckyWorldSubsystem.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::SetRobotNavPath(const FRobotNavPath& InRobotNavPath)
|
||||||
|
{
|
||||||
|
CurrentSplinePath.GenerateSplinePath(this, InRobotNavPath);
|
||||||
|
|
||||||
|
Internal_RobotNavPathChanged(CurrentSplinePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Internal_RobotNavPathChanged(const FRobotSplinePath& NewNavPath)
|
||||||
|
{
|
||||||
|
RobotNavPathChanged(NewNavPath);
|
||||||
|
}
|
||||||
|
|
||||||
int32 ALuckyRobotPawnBase::GetTaskCount()
|
int32 ALuckyRobotPawnBase::GetTaskCount()
|
||||||
{
|
{
|
||||||
if (GetLuckyRobotsGameInstance())
|
if (GetLuckyRobotsGameInstance())
|
||||||
@ -344,6 +365,8 @@ void ALuckyRobotPawnBase::SetTargetSpeed(const float InTargetSpeed)
|
|||||||
|
|
||||||
void ALuckyRobotPawnBase::Internal_TargetSpeedChanged(const float OldValue)
|
void ALuckyRobotPawnBase::Internal_TargetSpeedChanged(const float OldValue)
|
||||||
{
|
{
|
||||||
|
GetCurrentNavPath().RegenerateSplinePathValues();
|
||||||
|
|
||||||
TargetSpeedChanged(TargetSpeed, OldValue);
|
TargetSpeedChanged(TargetSpeed, OldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,4 +72,14 @@ void ULuckyWorldSubsystem::UpdateTorqueLimiter(const float InTorqueLimiter)
|
|||||||
{
|
{
|
||||||
TorqueLimiterChanged.Broadcast(Robot_TorqueLimiter);
|
TorqueLimiterChanged.Broadcast(Robot_TorqueLimiter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ULuckyWorldSubsystem::UpdateRobotNavPath(const FRobotNavPath& InRobotNavPath)
|
||||||
|
{
|
||||||
|
RobotNavPath = InRobotNavPath;
|
||||||
|
|
||||||
|
if (RobotNavPathChanged.IsBound())
|
||||||
|
{
|
||||||
|
RobotNavPathChanged.Broadcast(RobotNavPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -48,6 +48,7 @@ protected:
|
|||||||
|
|
||||||
FRobotSettings RobotSettings = FRobotSettings();
|
FRobotSettings RobotSettings = FRobotSettings();
|
||||||
|
|
||||||
|
//virtual void EvaluateRobotPath();
|
||||||
virtual void InterpolateSpeedValues(const float DeltaTime, const float Acceleration, const float Deceleration);
|
virtual void InterpolateSpeedValues(const float DeltaTime, const float Acceleration, const float Deceleration);
|
||||||
|
|
||||||
FVector2D CurrentSpeedValues = FVector2D::ZeroVector;
|
FVector2D CurrentSpeedValues = FVector2D::ZeroVector;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "RobotSettings.generated.h"
|
#include "RobotSettings.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ALuckyRobotPawnBase;
|
||||||
|
class USplineComponent;
|
||||||
class ULuckyRobotMovementComponent;
|
class ULuckyRobotMovementComponent;
|
||||||
class AMujocoVolumeActor;
|
class AMujocoVolumeActor;
|
||||||
|
|
||||||
@ -30,6 +32,9 @@ USTRUCT(BlueprintType)
|
|||||||
struct FRobotSettings
|
struct FRobotSettings
|
||||||
{
|
{
|
||||||
GENERATED_USTRUCT_BODY()
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
||||||
|
float SpeedLimit = 15.f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
||||||
TSubclassOf<AMujocoVolumeActor> MujocoSettings;
|
TSubclassOf<AMujocoVolumeActor> MujocoSettings;
|
||||||
@ -39,4 +44,54 @@ struct FRobotSettings
|
|||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
||||||
ERobotInputHandlingMethod InputHandlingMethod = ERobotInputHandlingMethod::CombinedInput;
|
ERobotInputHandlingMethod InputHandlingMethod = ERobotInputHandlingMethod::CombinedInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FRobotNavPoint
|
||||||
|
{
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Nav Point")
|
||||||
|
FVector Location = FVector::ZeroVector;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Nav Point")
|
||||||
|
bool bDestination = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FRobotNavPath
|
||||||
|
{
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Nav Path")
|
||||||
|
TArray<FRobotNavPoint> NavPoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FRobotSplinePath
|
||||||
|
{
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path")
|
||||||
|
TWeakObjectPtr<ALuckyRobotPawnBase> Robot;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path")
|
||||||
|
FRobotNavPath NavPath = FRobotNavPath();
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path")
|
||||||
|
TWeakObjectPtr<USplineComponent> SplinePath;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path")
|
||||||
|
FRuntimeFloatCurve SplinePathSpeedModifier = FRuntimeFloatCurve();
|
||||||
|
|
||||||
|
ALuckyRobotPawnBase* GetRobot() const { return Robot.Get(); }
|
||||||
|
void GenerateSplinePath(ALuckyRobotPawnBase* InRobot, const FRobotNavPath& InNavPath);
|
||||||
|
void RegenerateSplinePathValues();
|
||||||
|
USplineComponent* GetSplinePath() const { return SplinePath.Get(); }
|
||||||
|
|
||||||
|
FRobotSplinePath() {}
|
||||||
|
FRobotSplinePath(ALuckyRobotPawnBase* InRobot, const FRobotNavPath& InNavPath)
|
||||||
|
{
|
||||||
|
GenerateSplinePath(InRobot, InNavPath);
|
||||||
|
}
|
||||||
};
|
};
|
@ -45,11 +45,11 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
float GetFastEndTaskTime();
|
float GetFastEndTaskTime();
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
UFUNCTION()
|
||||||
bool SetActuators(const TArray<FStretchRobotActuator>& InActuators);
|
bool SetActuators(const TArray<FStretchRobotActuator>& InActuators);
|
||||||
|
|
||||||
// SPEED CONFIG
|
// SPEED CONFIG
|
||||||
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
UFUNCTION()
|
||||||
void SetTargetSpeed(const float InTargetSpeed = 0.f);
|
void SetTargetSpeed(const float InTargetSpeed = 0.f);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
@ -64,7 +64,7 @@ public:
|
|||||||
ULuckyRobotMovementComponent* GetRobotMovementComponent() const { return RobotMovementComponent.Get(); }
|
ULuckyRobotMovementComponent* GetRobotMovementComponent() const { return RobotMovementComponent.Get(); }
|
||||||
|
|
||||||
// TORQUE LIMITER
|
// TORQUE LIMITER
|
||||||
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
UFUNCTION()
|
||||||
void SetTorqueLimiter(const float InTorqueLimiter = 0.f);
|
void SetTorqueLimiter(const float InTorqueLimiter = 0.f);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
@ -116,6 +116,18 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
ULuckyWorldSubsystem* GetLuckyWorldSubsystem();
|
ULuckyWorldSubsystem* GetLuckyWorldSubsystem();
|
||||||
|
|
||||||
|
// NAV ROBOT PATH CHANGED
|
||||||
|
UFUNCTION()
|
||||||
|
void SetRobotNavPath(const FRobotNavPath& InRobotNavPath);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
FRobotSplinePath& GetCurrentNavPath() { return CurrentSplinePath; }
|
||||||
|
|
||||||
|
void Internal_RobotNavPathChanged(const FRobotSplinePath& NewNavPath);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintImplementableEvent, Category = "Lucky Robot Pawn")
|
||||||
|
void RobotNavPathChanged(const FRobotSplinePath& NewNavPath);
|
||||||
|
|
||||||
// INPUTS
|
// INPUTS
|
||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
UEnhancedInputComponent* GetEnhancedInputComponent() const { return EnhancedInputComponent.Get(); }
|
UEnhancedInputComponent* GetEnhancedInputComponent() const { return EnhancedInputComponent.Get(); }
|
||||||
@ -132,6 +144,9 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||||
UInputAction* LookAction;
|
UInputAction* LookAction;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||||
|
UInputAction* TogglePathfindingAction;
|
||||||
|
|
||||||
void MoveStart(const FInputActionValue& Value);
|
void MoveStart(const FInputActionValue& Value);
|
||||||
void Move(const FInputActionValue& Value);
|
void Move(const FInputActionValue& Value);
|
||||||
void MoveStop(const FInputActionValue& Value);
|
void MoveStop(const FInputActionValue& Value);
|
||||||
@ -142,6 +157,8 @@ public:
|
|||||||
|
|
||||||
void Look(const FInputActionValue& Value);
|
void Look(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
void TogglePathfinding(const FInputActionValue& Value);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
ERobotInputType GetCurrentInputType() const { return CurrentInputType; }
|
ERobotInputType GetCurrentInputType() const { return CurrentInputType; }
|
||||||
|
|
||||||
@ -154,6 +171,9 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
float GetDecelerationRate() const { return DecelerationRate; }
|
float GetDecelerationRate() const { return DecelerationRate; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
float GetTurnModifier() const { return TurnModifier; }
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lucky Robot Pawn")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lucky Robot Pawn")
|
||||||
float AccelerationRate = 1.5f;
|
float AccelerationRate = 1.5f;
|
||||||
|
|
||||||
@ -163,11 +183,15 @@ public:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||||
float TargetSpeed = 0.f;
|
float TargetSpeed = 0.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
|
||||||
|
float TurnModifier = 1.f;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void BeginPlay() override;
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
bool HasMovementValue() const;
|
bool HasMovementValue() const;
|
||||||
bool HasTurnValue() const;
|
bool HasTurnValue() const;
|
||||||
|
bool IsPathfinding() const { return CurrentInputType == ERobotInputType::Pathfinding; }
|
||||||
|
|
||||||
void RemoveMujocoVolumeActor();
|
void RemoveMujocoVolumeActor();
|
||||||
|
|
||||||
@ -187,4 +211,7 @@ protected:
|
|||||||
float TorqueLimiter = 0.85f;
|
float TorqueLimiter = 0.85f;
|
||||||
int32 CurrentTaskIndex = -1;
|
int32 CurrentTaskIndex = -1;
|
||||||
float TaskTime = 0.f;
|
float TaskTime = 0.f;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
FRobotSplinePath CurrentSplinePath = FRobotSplinePath();
|
||||||
};
|
};
|
@ -3,6 +3,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "Gameplay/Robot/Data/RobotSettings.h"
|
||||||
#include "Subsystems/WorldSubsystem.h"
|
#include "Subsystems/WorldSubsystem.h"
|
||||||
#include "LuckyWorldSubsystem.generated.h"
|
#include "LuckyWorldSubsystem.generated.h"
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotPawnReadyDelegate, ALucky
|
|||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotCurrentTaskChangedDelegate, const int32, NewTaskIndex);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotCurrentTaskChangedDelegate, const int32, NewTaskIndex);
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotTargetSpeedChangedDelegate, const float, NewTargetSpeed);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotTargetSpeedChangedDelegate, const float, NewTargetSpeed);
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotTorqueLimiterChangedDelegate, const float, NewTorqueLimiter);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotTorqueLimiterChangedDelegate, const float, NewTorqueLimiter);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotNavPathChangedDelegate, const FRobotNavPath&, NewRobotNavPath);
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class LUCKYWORLDV2_API ULuckyWorldSubsystem : public UWorldSubsystem
|
class LUCKYWORLDV2_API ULuckyWorldSubsystem : public UWorldSubsystem
|
||||||
@ -65,11 +67,24 @@ public:
|
|||||||
|
|
||||||
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
FLuckyRobotTorqueLimiterChangedDelegate TorqueLimiterChanged;
|
FLuckyRobotTorqueLimiterChangedDelegate TorqueLimiterChanged;
|
||||||
|
|
||||||
|
// ROBOT NAV PATH
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky World Subsystem")
|
||||||
|
void UpdateRobotNavPath(const FRobotNavPath& InRobotNavPath);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky World Subsystem")
|
||||||
|
FRobotNavPath GetRobotNavPath() const { return RobotNavPath; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
|
FLuckyRobotNavPathChangedDelegate RobotNavPathChanged;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TWeakObjectPtr<ALuckyRobotPawnBase> LuckyRobotPawn;
|
TWeakObjectPtr<ALuckyRobotPawnBase> LuckyRobotPawn;
|
||||||
TWeakObjectPtr<AMujocoVolumeActor> MujocoVolumeActor;
|
TWeakObjectPtr<AMujocoVolumeActor> MujocoVolumeActor;
|
||||||
|
|
||||||
|
UPROPERTY()
|
||||||
|
FRobotNavPath RobotNavPath = FRobotNavPath();
|
||||||
|
|
||||||
float Robot_TargetSpeed = 0.f;
|
float Robot_TargetSpeed = 0.f;
|
||||||
float Robot_TorqueLimiter = 0.85f;
|
float Robot_TorqueLimiter = 0.85f;
|
||||||
int32 Robot_CurrentTaskIndex = -1;
|
int32 Robot_CurrentTaskIndex = -1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user