diff --git a/Content/Developers/Wdev/Robots/BP_Stretch.uasset b/Content/Developers/Wdev/Robots/BP_Stretch.uasset index 782b48bf..9c18e16e 100644 Binary files a/Content/Developers/Wdev/Robots/BP_Stretch.uasset and b/Content/Developers/Wdev/Robots/BP_Stretch.uasset differ diff --git a/Content/Developers/Wdev/Robots/NewBlueprint.uasset b/Content/Developers/Wdev/Robots/NewBlueprint.uasset new file mode 100644 index 00000000..ed5e8376 Binary files /dev/null and b/Content/Developers/Wdev/Robots/NewBlueprint.uasset differ diff --git a/Source/LuckyWorldV2/Private/Gameplay/Robot/Components/Movement/LRMC_Stretch.cpp b/Source/LuckyWorldV2/Private/Gameplay/Robot/Components/Movement/LRMC_Stretch.cpp index ec7285bc..9f257305 100644 --- a/Source/LuckyWorldV2/Private/Gameplay/Robot/Components/Movement/LRMC_Stretch.cpp +++ b/Source/LuckyWorldV2/Private/Gameplay/Robot/Components/Movement/LRMC_Stretch.cpp @@ -3,14 +3,13 @@ #include "Gameplay/Robot/Components/Movement/LRMC_Stretch.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) { 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 //Move(InputValues.X); //Turn(InputValues.Y * TurnMod); @@ -38,7 +37,7 @@ void ULRMC_Stretch::PerformMovement(float DeltaTime, const ERobotInputHandlingMe } else { - Turn(InputValues.Y * TurnMod); + Turn(InputValues.Y); } break; case ERobotInputType::Pathfinding: @@ -54,7 +53,7 @@ void ULRMC_Stretch::PerformMovement(float DeltaTime, const ERobotInputHandlingMe case ERobotInputType::Turn: { PreviousInputType = ERobotInputType::Turn; - Turn(InputValues.Y * TurnMod); + Turn(InputValues.Y); } break; case ERobotInputType::Pathfinding: @@ -75,7 +74,8 @@ void ULRMC_Stretch::Turn(const float InValue) const { if (GetMujocoVolumeActor()) { - GetMujocoVolumeActor()->SetActuatorValueByIndex(0, -InValue); - GetMujocoVolumeActor()->SetActuatorValueByIndex(1, InValue); + const float TurnMod = GetOwningRobot() ? GetOwningRobot()->GetTurnModifier() : 1.f; + GetMujocoVolumeActor()->SetActuatorValueByIndex(0, InValue * -TurnMod); + GetMujocoVolumeActor()->SetActuatorValueByIndex(1, InValue * TurnMod); } } \ No newline at end of file diff --git a/Source/LuckyWorldV2/Private/Gameplay/Robot/Data/RobotSettings.cpp b/Source/LuckyWorldV2/Private/Gameplay/Robot/Data/RobotSettings.cpp new file mode 100644 index 00000000..ca155dce --- /dev/null +++ b/Source/LuckyWorldV2/Private/Gameplay/Robot/Data/RobotSettings.cpp @@ -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(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(GetRobot()->GetTargetSpeed(), SpeedLimit); + const float SplinePredictionDistance = FMath::Max(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(SplinePredictionDistance * 10.f, TangentClamp); + const FVector ArriveTangent = (PointLoc3 - PointLoc1).GetSafeNormal() * FMath::Min(Distance1 * PointDistanceMod, TangentMin); + const FVector LeaveTangent = (PointLoc3 - PointLoc1).GetSafeNormal() * FMath::Min(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(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(UKismetMathLibrary::SafeDivide(DistanceToPathEnd, SplinePredictionDistance), 0.f) : 1.f; + const FVector IntervalTangent = GetSplinePath()->GetTangentAtDistanceAlongSpline(SplineDistance, ESplineCoordinateSpace::Local); + const float IntervalCurve = FMath::Min(IntervalTangent.Length(), TangentClamp); + const float IntervalAlpha = UKismetMathLibrary::SafeDivide(IntervalCurve, TangentClamp); + const float SpeedMod = (MaxSpeedMod - IntervalAlpha) * PathEndMod; + const float ClampedSpeed = FMath::Min(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 + } +} diff --git a/Source/LuckyWorldV2/Private/Gameplay/Robot/LuckyRobotPawnBase.cpp b/Source/LuckyWorldV2/Private/Gameplay/Robot/LuckyRobotPawnBase.cpp index c47884a9..2c9f66de 100644 --- a/Source/LuckyWorldV2/Private/Gameplay/Robot/LuckyRobotPawnBase.cpp +++ b/Source/LuckyWorldV2/Private/Gameplay/Robot/LuckyRobotPawnBase.cpp @@ -56,8 +56,6 @@ void ALuckyRobotPawnBase::InitializeMovementComponent() void ALuckyRobotPawnBase::BeginPlay() { - Super::BeginPlay(); - InitializeMujocoVolumeActor(); InitializeMovementComponent(); @@ -66,7 +64,10 @@ void ALuckyRobotPawnBase::BeginPlay() GetLuckyWorldSubsystem()->RegisterLuckyRobot(this); GetLuckyWorldSubsystem()->TargetSpeedChanged.AddUniqueDynamic(this, &ALuckyRobotPawnBase::SetTargetSpeed); + GetLuckyWorldSubsystem()->RobotNavPathChanged.AddUniqueDynamic(this, &ALuckyRobotPawnBase::SetRobotNavPath); } + + Super::BeginPlay(); } bool ALuckyRobotPawnBase::HasMovementValue() const @@ -123,6 +124,8 @@ void ALuckyRobotPawnBase::SetupPlayerInputComponent(UInputComponent* PlayerInput EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Completed, this, &ALuckyRobotPawnBase::TurnStop); 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().ToString()); } +void ALuckyRobotPawnBase::TogglePathfinding(const FInputActionValue& Value) +{ + PreviousInputType = ERobotInputType::None; + CurrentInputType = IsPathfinding() ? ERobotInputType::None : ERobotInputType::Pathfinding; +} + void ALuckyRobotPawnBase::RemoveMujocoVolumeActor() { if (GetMujocoVolumeActor()) @@ -276,6 +285,18 @@ ULuckyWorldSubsystem* ALuckyRobotPawnBase::GetLuckyWorldSubsystem() 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() { if (GetLuckyRobotsGameInstance()) @@ -344,6 +365,8 @@ void ALuckyRobotPawnBase::SetTargetSpeed(const float InTargetSpeed) void ALuckyRobotPawnBase::Internal_TargetSpeedChanged(const float OldValue) { + GetCurrentNavPath().RegenerateSplinePathValues(); + TargetSpeedChanged(TargetSpeed, OldValue); } diff --git a/Source/LuckyWorldV2/Private/Subsystems/LuckyWorldSubsystem.cpp b/Source/LuckyWorldV2/Private/Subsystems/LuckyWorldSubsystem.cpp index aefff6cd..c4609c6b 100644 --- a/Source/LuckyWorldV2/Private/Subsystems/LuckyWorldSubsystem.cpp +++ b/Source/LuckyWorldV2/Private/Subsystems/LuckyWorldSubsystem.cpp @@ -72,4 +72,14 @@ void ULuckyWorldSubsystem::UpdateTorqueLimiter(const float InTorqueLimiter) { TorqueLimiterChanged.Broadcast(Robot_TorqueLimiter); } -} \ No newline at end of file +} + +void ULuckyWorldSubsystem::UpdateRobotNavPath(const FRobotNavPath& InRobotNavPath) +{ + RobotNavPath = InRobotNavPath; + + if (RobotNavPathChanged.IsBound()) + { + RobotNavPathChanged.Broadcast(RobotNavPath); + } +} diff --git a/Source/LuckyWorldV2/Public/Gameplay/Robot/Components/Movement/LuckyRobotMovementComponent.h b/Source/LuckyWorldV2/Public/Gameplay/Robot/Components/Movement/LuckyRobotMovementComponent.h index d0f0a414..08943bfa 100644 --- a/Source/LuckyWorldV2/Public/Gameplay/Robot/Components/Movement/LuckyRobotMovementComponent.h +++ b/Source/LuckyWorldV2/Public/Gameplay/Robot/Components/Movement/LuckyRobotMovementComponent.h @@ -48,6 +48,7 @@ protected: FRobotSettings RobotSettings = FRobotSettings(); + //virtual void EvaluateRobotPath(); virtual void InterpolateSpeedValues(const float DeltaTime, const float Acceleration, const float Deceleration); FVector2D CurrentSpeedValues = FVector2D::ZeroVector; diff --git a/Source/LuckyWorldV2/Public/Gameplay/Robot/Data/RobotSettings.h b/Source/LuckyWorldV2/Public/Gameplay/Robot/Data/RobotSettings.h index a4bf6192..afe89433 100644 --- a/Source/LuckyWorldV2/Public/Gameplay/Robot/Data/RobotSettings.h +++ b/Source/LuckyWorldV2/Public/Gameplay/Robot/Data/RobotSettings.h @@ -6,6 +6,8 @@ #include "RobotSettings.generated.h" +class ALuckyRobotPawnBase; +class USplineComponent; class ULuckyRobotMovementComponent; class AMujocoVolumeActor; @@ -30,6 +32,9 @@ USTRUCT(BlueprintType) struct FRobotSettings { GENERATED_USTRUCT_BODY() + + UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings") + float SpeedLimit = 15.f; UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings") TSubclassOf MujocoSettings; @@ -39,4 +44,54 @@ struct FRobotSettings UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings") 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 NavPoints; +}; + +USTRUCT(BlueprintType) +struct FRobotSplinePath +{ + GENERATED_USTRUCT_BODY() + + UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path") + TWeakObjectPtr Robot; + + UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path") + FRobotNavPath NavPath = FRobotNavPath(); + + UPROPERTY(BlueprintReadOnly, Category = "Robot Spline Path") + TWeakObjectPtr 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); + } }; \ No newline at end of file diff --git a/Source/LuckyWorldV2/Public/Gameplay/Robot/LuckyRobotPawnBase.h b/Source/LuckyWorldV2/Public/Gameplay/Robot/LuckyRobotPawnBase.h index 2d63b9b3..7985459d 100644 --- a/Source/LuckyWorldV2/Public/Gameplay/Robot/LuckyRobotPawnBase.h +++ b/Source/LuckyWorldV2/Public/Gameplay/Robot/LuckyRobotPawnBase.h @@ -45,11 +45,11 @@ public: UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") float GetFastEndTaskTime(); - UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn") + UFUNCTION() bool SetActuators(const TArray& InActuators); // SPEED CONFIG - UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn") + UFUNCTION() void SetTargetSpeed(const float InTargetSpeed = 0.f); UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") @@ -64,7 +64,7 @@ public: ULuckyRobotMovementComponent* GetRobotMovementComponent() const { return RobotMovementComponent.Get(); } // TORQUE LIMITER - UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn") + UFUNCTION() void SetTorqueLimiter(const float InTorqueLimiter = 0.f); UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") @@ -116,6 +116,18 @@ public: UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") 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 UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") UEnhancedInputComponent* GetEnhancedInputComponent() const { return EnhancedInputComponent.Get(); } @@ -132,6 +144,9 @@ public: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) UInputAction* LookAction; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) + UInputAction* TogglePathfindingAction; + void MoveStart(const FInputActionValue& Value); void Move(const FInputActionValue& Value); void MoveStop(const FInputActionValue& Value); @@ -142,6 +157,8 @@ public: void Look(const FInputActionValue& Value); + void TogglePathfinding(const FInputActionValue& Value); + UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") ERobotInputType GetCurrentInputType() const { return CurrentInputType; } @@ -154,6 +171,9 @@ public: UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") float GetDecelerationRate() const { return DecelerationRate; } + UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn") + float GetTurnModifier() const { return TurnModifier; } + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lucky Robot Pawn") float AccelerationRate = 1.5f; @@ -163,11 +183,15 @@ public: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input") float TargetSpeed = 0.f; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input") + float TurnModifier = 1.f; + protected: virtual void BeginPlay() override; bool HasMovementValue() const; bool HasTurnValue() const; + bool IsPathfinding() const { return CurrentInputType == ERobotInputType::Pathfinding; } void RemoveMujocoVolumeActor(); @@ -187,4 +211,7 @@ protected: float TorqueLimiter = 0.85f; int32 CurrentTaskIndex = -1; float TaskTime = 0.f; + + UPROPERTY() + FRobotSplinePath CurrentSplinePath = FRobotSplinePath(); }; \ No newline at end of file diff --git a/Source/LuckyWorldV2/Public/Subsystems/LuckyWorldSubsystem.h b/Source/LuckyWorldV2/Public/Subsystems/LuckyWorldSubsystem.h index 939c4369..726e7e53 100644 --- a/Source/LuckyWorldV2/Public/Subsystems/LuckyWorldSubsystem.h +++ b/Source/LuckyWorldV2/Public/Subsystems/LuckyWorldSubsystem.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" +#include "Gameplay/Robot/Data/RobotSettings.h" #include "Subsystems/WorldSubsystem.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(FLuckyRobotTargetSpeedChangedDelegate, const float, NewTargetSpeed); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotTorqueLimiterChangedDelegate, const float, NewTorqueLimiter); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotNavPathChangedDelegate, const FRobotNavPath&, NewRobotNavPath); UCLASS() class LUCKYWORLDV2_API ULuckyWorldSubsystem : public UWorldSubsystem @@ -65,11 +67,24 @@ public: UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem") 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: TWeakObjectPtr LuckyRobotPawn; TWeakObjectPtr MujocoVolumeActor; + UPROPERTY() + FRobotNavPath RobotNavPath = FRobotNavPath(); + float Robot_TargetSpeed = 0.f; float Robot_TorqueLimiter = 0.85f; int32 Robot_CurrentTaskIndex = -1;