*WIP* Robot Base Class, LuckyWorldSubsystem, LuckyRobotMovementComponent
- Robot Base Class -> Handles inputs, has Mujoco settings, creates proper movement component - LuckyWorldSubsystem -> Has Get and Ready functions for many Robot values/updates - LuckyRobotMovementComponent -> Base component for robot movement. Can read any value or input from the owning robot. Can be reused on similar robots or custom components can be created if needed.
This commit is contained in:
parent
b91d8c9412
commit
b31dad8ca5
@ -50,14 +50,14 @@ class LUCKYMUJOCO_API AMujocoVolumeActor : public AActor
|
|||||||
UPROPERTY(Transient, VisibleAnywhere, Category = "Mujoco | Debug")
|
UPROPERTY(Transient, VisibleAnywhere, Category = "Mujoco | Debug")
|
||||||
TArray<TSoftObjectPtr<UMujocoTendonComponent>> TendonComponents;
|
TArray<TSoftObjectPtr<UMujocoTendonComponent>> TendonComponents;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Mujoco")
|
|
||||||
void InitializeMujoco();
|
|
||||||
|
|
||||||
template <typename ComponentType> void AssignComponentsToArray(UWorld* World, TArray<TSoftObjectPtr<ComponentType>>& ComponentArray);
|
template <typename ComponentType> void AssignComponentsToArray(UWorld* World, TArray<TSoftObjectPtr<ComponentType>>& ComponentArray);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AMujocoVolumeActor();
|
AMujocoVolumeActor();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Mujoco")
|
||||||
|
void InitializeMujoco();
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation", meta = (Min = 0, Max = 100, ClampMin = 0, ClampMax = 100))
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mujoco | Simulation", meta = (Min = 0, Max = 100, ClampMin = 0, ClampMax = 100))
|
||||||
int32 FrameSkip = 0;
|
int32 FrameSkip = 0;
|
||||||
|
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Gameplay/Robot/Components/Movement/LuckyRobotMovementComponent.h"
|
||||||
|
#include "Actors/MujocoVolumeActor.h"
|
||||||
|
#include "Gameplay/Robot/LuckyRobotPawnBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
ULuckyRobotMovementComponent::ULuckyRobotMovementComponent()
|
||||||
|
{
|
||||||
|
PrimaryComponentTick.bCanEverTick = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULuckyRobotMovementComponent::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULuckyRobotMovementComponent::InitializeMovementComponent(ALuckyRobotPawnBase* InOwningRobot)
|
||||||
|
{
|
||||||
|
if (IsValid(InOwningRobot))
|
||||||
|
{
|
||||||
|
OwningRobot = InOwningRobot;
|
||||||
|
|
||||||
|
if (GetOwningRobot())
|
||||||
|
{
|
||||||
|
MujocoVolumeActor = GetOwningRobot()->GetMujocoVolumeActor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,328 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Gameplay/Robot/LuckyRobotPawnBase.h"
|
||||||
|
#include "Actors/MujocoVolumeActor.h"
|
||||||
|
#include "Core/LuckyRobotsGameInstance.h"
|
||||||
|
#include "Gameplay/Robot/Components/Movement/LuckyRobotMovementComponent.h"
|
||||||
|
#include "Subsystems/LuckyWorldSubsystem.h"
|
||||||
|
#include "EnhancedInputComponent.h"
|
||||||
|
#include "EnhancedInputSubsystems.h"
|
||||||
|
|
||||||
|
|
||||||
|
ALuckyRobotPawnBase::ALuckyRobotPawnBase()
|
||||||
|
{
|
||||||
|
PrimaryActorTick.bCanEverTick = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::InitializeMujocoVolumeActor()
|
||||||
|
{
|
||||||
|
RemoveMujocoVolumeActor();
|
||||||
|
|
||||||
|
if (GetWorld() && IsValid(RobotSettings.MujocoSettings.Get()))
|
||||||
|
{
|
||||||
|
if (AMujocoVolumeActor* SpawnedVolume = GetWorld()->SpawnActorDeferred<AMujocoVolumeActor>(RobotSettings.MujocoSettings.Get(), FTransform::Identity, nullptr, nullptr, ESpawnActorCollisionHandlingMethod::AlwaysSpawn))
|
||||||
|
{
|
||||||
|
// do anything here we need to for the MujocoVolumeActor before we finalize spawning
|
||||||
|
SpawnedVolume->FinishSpawning(FTransform::Identity);
|
||||||
|
MujocoVolumeSettings = SpawnedVolume;
|
||||||
|
|
||||||
|
if (GetMujocoVolumeActor())
|
||||||
|
{
|
||||||
|
GetMujocoVolumeActor()->InitializeMujoco();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::InitializeMovementComponent()
|
||||||
|
{
|
||||||
|
if (!GetRobotMovementComponent() && IsValid(RobotSettings.MovementComponentClass.Get()))
|
||||||
|
{
|
||||||
|
if (UActorComponent* NewComp = AddComponentByClass(RobotSettings.MovementComponentClass.Get(), false, FTransform::Identity, false))
|
||||||
|
{
|
||||||
|
if (ULuckyRobotMovementComponent* NewMoveComp = Cast<ULuckyRobotMovementComponent>(NewComp))
|
||||||
|
{
|
||||||
|
RobotMovementComponent = NewMoveComp;
|
||||||
|
|
||||||
|
if (GetRobotMovementComponent())
|
||||||
|
{
|
||||||
|
GetRobotMovementComponent()->InitializeMovementComponent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
InitializeMujocoVolumeActor();
|
||||||
|
InitializeMovementComponent();
|
||||||
|
|
||||||
|
if (GetLuckyWorldSubsystem())
|
||||||
|
{
|
||||||
|
GetLuckyWorldSubsystem()->RegisterLuckyRobot(this);
|
||||||
|
|
||||||
|
GetLuckyWorldSubsystem()->TargetSpeedChanged.AddUniqueDynamic(this, &ALuckyRobotPawnBase::SetTargetSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Tick(float DeltaTime)
|
||||||
|
{
|
||||||
|
Super::Tick(DeltaTime);
|
||||||
|
|
||||||
|
// need to check NaviPoint to see if it is paused
|
||||||
|
TaskTime += DeltaTime;
|
||||||
|
|
||||||
|
// if (HasTaskExpired())
|
||||||
|
// {
|
||||||
|
// IncrementCurrentTask();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::NotifyControllerChanged()
|
||||||
|
{
|
||||||
|
Super::NotifyControllerChanged();
|
||||||
|
|
||||||
|
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
|
||||||
|
{
|
||||||
|
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
|
||||||
|
{
|
||||||
|
Subsystem->AddMappingContext(DefaultMappingContext, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||||
|
{
|
||||||
|
if (!GetEnhancedInputComponent())
|
||||||
|
{
|
||||||
|
EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetEnhancedInputComponent())
|
||||||
|
{
|
||||||
|
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Started, this, &ALuckyRobotPawnBase::MoveStart);
|
||||||
|
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ALuckyRobotPawnBase::Move);
|
||||||
|
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Completed, this, &ALuckyRobotPawnBase::MoveStop);
|
||||||
|
|
||||||
|
EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Started, this, &ALuckyRobotPawnBase::TurnStart);
|
||||||
|
EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Triggered, this, &ALuckyRobotPawnBase::Turn);
|
||||||
|
EnhancedInputComponent->BindAction(TurnAction, ETriggerEvent::Completed, this, &ALuckyRobotPawnBase::TurnStop);
|
||||||
|
|
||||||
|
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ALuckyRobotPawnBase::Look);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::MoveStart(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: MoveStart"));
|
||||||
|
|
||||||
|
CachedMovementInputValues.X = Value.Get<float>();
|
||||||
|
|
||||||
|
PreviousInputType = CurrentInputType;
|
||||||
|
CurrentInputType = ERobotInputType::Move;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Move(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: Move (%f)"), Value.Get<float>());
|
||||||
|
|
||||||
|
CachedMovementInputValues.X = Value.Get<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::MoveStop(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: MoveStop"));
|
||||||
|
|
||||||
|
CachedMovementInputValues.X = 0.f;
|
||||||
|
|
||||||
|
if (CurrentInputType == ERobotInputType::Move && PreviousInputType == ERobotInputType::Turn && !FMath::IsNearlyZero(CachedMovementInputValues.Y, 0.01f))
|
||||||
|
{
|
||||||
|
CurrentInputType = ERobotInputType::Turn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentInputType = ERobotInputType::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviousInputType = ERobotInputType::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::TurnStart(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: TurnStart"));
|
||||||
|
|
||||||
|
CachedMovementInputValues.Y = Value.Get<float>();
|
||||||
|
|
||||||
|
PreviousInputType = CurrentInputType;
|
||||||
|
CurrentInputType = ERobotInputType::Turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Turn(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: Turn (%f)"), Value.Get<float>());
|
||||||
|
|
||||||
|
CachedMovementInputValues.Y = Value.Get<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::TurnStop(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: TurnStop"));
|
||||||
|
|
||||||
|
CachedMovementInputValues.Y = 0.f;
|
||||||
|
|
||||||
|
if (CurrentInputType == ERobotInputType::Turn && PreviousInputType == ERobotInputType::Move && !FMath::IsNearlyZero(CachedMovementInputValues.X, 0.01f))
|
||||||
|
{
|
||||||
|
CurrentInputType = ERobotInputType::Move;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CurrentInputType = ERobotInputType::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviousInputType = ERobotInputType::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Look(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("ALuckyRobotPawnBase :: Input :: Look (%s)"), *Value.Get<FVector2D>().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::RemoveMujocoVolumeActor()
|
||||||
|
{
|
||||||
|
if (GetMujocoVolumeActor())
|
||||||
|
{
|
||||||
|
GetMujocoVolumeActor()->Destroy();
|
||||||
|
MujocoVolumeSettings.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||||
|
{
|
||||||
|
Super::EndPlay(EndPlayReason);
|
||||||
|
|
||||||
|
RemoveMujocoVolumeActor();
|
||||||
|
}
|
||||||
|
|
||||||
|
ULuckyWorldSubsystem* ALuckyRobotPawnBase::GetLuckyWorldSubsystem()
|
||||||
|
{
|
||||||
|
if (!LuckyWorldSubsystem.Get() && GetWorld())
|
||||||
|
{
|
||||||
|
LuckyWorldSubsystem = GetWorld()->GetSubsystem<ULuckyWorldSubsystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LuckyWorldSubsystem.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 ALuckyRobotPawnBase::GetTaskCount()
|
||||||
|
{
|
||||||
|
if (GetLuckyRobotsGameInstance())
|
||||||
|
{
|
||||||
|
return GetLuckyRobotsGameInstance()->GetTaskNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ALuckyRobotPawnBase::HasTaskExpired()
|
||||||
|
{
|
||||||
|
if (GetLuckyRobotsGameInstance())
|
||||||
|
{
|
||||||
|
return TaskTime >= GetFastEndTaskTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULuckyRobotsGameInstance* ALuckyRobotPawnBase::GetLuckyRobotsGameInstance()
|
||||||
|
{
|
||||||
|
if (!LuckyGameInstance.Get() && GetWorld() && GetWorld()->GetGameInstance())
|
||||||
|
{
|
||||||
|
LuckyGameInstance = Cast<ULuckyRobotsGameInstance>(GetWorld()->GetGameInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
return LuckyGameInstance.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ALuckyRobotPawnBase::GetInfiniteTime()
|
||||||
|
{
|
||||||
|
if (GetLuckyRobotsGameInstance())
|
||||||
|
{
|
||||||
|
return GetLuckyRobotsGameInstance()->bInfiniteTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ALuckyRobotPawnBase::GetFastEndTaskTime()
|
||||||
|
{
|
||||||
|
if (GetLuckyRobotsGameInstance())
|
||||||
|
{
|
||||||
|
return GetLuckyRobotsGameInstance()->FastEndTaskTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ALuckyRobotPawnBase::SetActuators(const TArray<FStretchRobotActuator>& InActuators)
|
||||||
|
{
|
||||||
|
Actuators.Empty();
|
||||||
|
Actuators = InActuators;
|
||||||
|
return !Actuators.IsEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPEED CONFIG
|
||||||
|
void ALuckyRobotPawnBase::SetTargetSpeed(const float InTargetSpeed)
|
||||||
|
{
|
||||||
|
const float OldValue = TargetSpeed;
|
||||||
|
TargetSpeed = InTargetSpeed;
|
||||||
|
|
||||||
|
Internal_TargetSpeedChanged(OldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Internal_TargetSpeedChanged(const float OldValue)
|
||||||
|
{
|
||||||
|
TargetSpeedChanged(TargetSpeed, OldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TORQUE LIMITER
|
||||||
|
void ALuckyRobotPawnBase::SetTorqueLimiter(const float InTorqueLimiter)
|
||||||
|
{
|
||||||
|
const float OldValue = TorqueLimiter;
|
||||||
|
TorqueLimiter = InTorqueLimiter;
|
||||||
|
|
||||||
|
Internal_TorqueLimiterChanged(OldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Internal_TorqueLimiterChanged(const float OldValue)
|
||||||
|
{
|
||||||
|
TorqueLimiterChanged(TorqueLimiter, OldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CURRENT TASK INDEX
|
||||||
|
void ALuckyRobotPawnBase::SetCurrentTaskIndex(const int32 InCurrentTaskIndex)
|
||||||
|
{
|
||||||
|
const int32 OldValue = CurrentTaskIndex;
|
||||||
|
CurrentTaskIndex = InCurrentTaskIndex;
|
||||||
|
|
||||||
|
Internal_CurrentTaskIndexChanged(OldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::IncrementCurrentTask()
|
||||||
|
{
|
||||||
|
TaskTime = 0.f;
|
||||||
|
SetCurrentTaskIndex(GetCurrentTaskIndex() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALuckyRobotPawnBase::Internal_CurrentTaskIndexChanged(const int32 OldValue)
|
||||||
|
{
|
||||||
|
if (GetLuckyWorldSubsystem())
|
||||||
|
{
|
||||||
|
GetLuckyWorldSubsystem()->UpdateCurrentTaskIndex(CurrentTaskIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentTaskIndexChanged(CurrentTaskIndex, OldValue);
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Subsystems/LuckyWorldSubsystem.h"
|
||||||
|
#include "Gameplay/Robot/LuckyRobotPawnBase.h"
|
||||||
|
|
||||||
|
void ULuckyWorldSubsystem::CheckSimulationReady()
|
||||||
|
{
|
||||||
|
if (!bSimulationReady)
|
||||||
|
{
|
||||||
|
bool bReady = true;
|
||||||
|
if (!GetLuckyRobot())
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Log, TEXT("CheckSimulationReady -> LuckyRobot IS NOT READY"));
|
||||||
|
bReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add any other false checks here if they are not ready
|
||||||
|
|
||||||
|
if (bReady)
|
||||||
|
{
|
||||||
|
bSimulationReady = true;
|
||||||
|
if (LuckyRobotSimulationReady.IsBound())
|
||||||
|
{
|
||||||
|
LuckyRobotSimulationReady.Broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULuckyWorldSubsystem::RegisterLuckyRobot(ALuckyRobotPawnBase* InLuckyRobot)
|
||||||
|
{
|
||||||
|
if (InLuckyRobot)
|
||||||
|
{
|
||||||
|
LuckyRobotPawn = InLuckyRobot;
|
||||||
|
|
||||||
|
if (LuckyRobotReady.IsBound())
|
||||||
|
{
|
||||||
|
LuckyRobotReady.Broadcast(GetLuckyRobot());
|
||||||
|
//LuckyRobotReady.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckSimulationReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULuckyWorldSubsystem::UpdateCurrentTaskIndex(const float InCurrentTaskIndex)
|
||||||
|
{
|
||||||
|
Robot_CurrentTaskIndex = InCurrentTaskIndex;
|
||||||
|
|
||||||
|
if (CurrentTaskIndexChanged.IsBound())
|
||||||
|
{
|
||||||
|
CurrentTaskIndexChanged.Broadcast(Robot_CurrentTaskIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULuckyWorldSubsystem::UpdateTargetSpeed(const float InTargetSpeed)
|
||||||
|
{
|
||||||
|
Robot_TargetSpeed = InTargetSpeed;
|
||||||
|
|
||||||
|
if (TargetSpeedChanged.IsBound())
|
||||||
|
{
|
||||||
|
TargetSpeedChanged.Broadcast(Robot_TargetSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULuckyWorldSubsystem::UpdateTorqueLimiter(const float InTorqueLimiter)
|
||||||
|
{
|
||||||
|
Robot_TorqueLimiter = InTorqueLimiter;
|
||||||
|
|
||||||
|
if (TorqueLimiterChanged.IsBound())
|
||||||
|
{
|
||||||
|
TorqueLimiterChanged.Broadcast(Robot_TorqueLimiter);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "LuckyRobotMovementComponent.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AMujocoVolumeActor;
|
||||||
|
class ALuckyRobotPawnBase;
|
||||||
|
|
||||||
|
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent), BlueprintType, Blueprintable)
|
||||||
|
class LUCKYWORLDV2_API ULuckyRobotMovementComponent : public UActorComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
public:
|
||||||
|
ULuckyRobotMovementComponent();
|
||||||
|
|
||||||
|
void InitializeMovementComponent(ALuckyRobotPawnBase* InOwningRobot);
|
||||||
|
|
||||||
|
ALuckyRobotPawnBase* GetOwningRobot() const { return OwningRobot.Get(); }
|
||||||
|
|
||||||
|
AMujocoVolumeActor* GetMujocoVolumeActor() const { return MujocoVolumeActor.Get(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
TWeakObjectPtr<ALuckyRobotPawnBase> OwningRobot;
|
||||||
|
TWeakObjectPtr<AMujocoVolumeActor> MujocoVolumeActor;
|
||||||
|
};
|
@ -0,0 +1,42 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "RobotSettings.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ULuckyRobotMovementComponent;
|
||||||
|
class AMujocoVolumeActor;
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class ERobotInputType : uint8
|
||||||
|
{
|
||||||
|
None UMETA(DisplayName = "None"),
|
||||||
|
Move UMETA(DisplayName = "Move"),
|
||||||
|
Turn UMETA(DisplayName = "Turn"),
|
||||||
|
Pathfinding UMETA(DisplayName = "Pathfinding")
|
||||||
|
};
|
||||||
|
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class ERobotInputHandlingMethod : uint8
|
||||||
|
{
|
||||||
|
None UMETA(DisplayName = "None"),
|
||||||
|
SingleInput UMETA(DisplayName = "SingleInput"),
|
||||||
|
CombinedInput UMETA(DisplayName = "CombinedInput")
|
||||||
|
};
|
||||||
|
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FRobotSettings
|
||||||
|
{
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
||||||
|
TSubclassOf<AMujocoVolumeActor> MujocoSettings;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
||||||
|
TSubclassOf<ULuckyRobotMovementComponent> MovementComponentClass;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Robot Settings")
|
||||||
|
ERobotInputHandlingMethod InputHandlingMethod = ERobotInputHandlingMethod::CombinedInput;
|
||||||
|
};
|
168
Source/LuckyWorldV2/Public/Gameplay/Robot/LuckyRobotPawnBase.h
Normal file
168
Source/LuckyWorldV2/Public/Gameplay/Robot/LuckyRobotPawnBase.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Data/RobotSettings.h"
|
||||||
|
#include "GameFramework/Pawn.h"
|
||||||
|
#include "LuckyRobotPawnBase.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ULuckyWorldSubsystem;
|
||||||
|
class AMujocoVolumeActor;
|
||||||
|
struct FGoalsTaskData;
|
||||||
|
struct FStretchRobotActuator;
|
||||||
|
class ULuckyRobotsGameInstance;
|
||||||
|
class ULuckyRobotMovementComponent;
|
||||||
|
class UInputMappingContext;
|
||||||
|
class UInputAction;
|
||||||
|
struct FInputActionValue;
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class LUCKYWORLDV2_API ALuckyRobotPawnBase : public APawn
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
ALuckyRobotPawnBase();
|
||||||
|
|
||||||
|
virtual void Tick(float DeltaTime) override;
|
||||||
|
|
||||||
|
virtual void NotifyControllerChanged() override;
|
||||||
|
|
||||||
|
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
|
||||||
|
|
||||||
|
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
ULuckyRobotsGameInstance* GetLuckyRobotsGameInstance();
|
||||||
|
|
||||||
|
// should this be replaced with bInfiniteTask ? and instead of setting a bool -and- loop count, we just say 0 loops is endless/infinite and the GetInfiniteTime just checks if loop count == 0
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
bool GetInfiniteTime();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
float GetFastEndTaskTime();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
bool SetActuators(const TArray<FStretchRobotActuator>& InActuators);
|
||||||
|
|
||||||
|
// SPEED CONFIG
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
void SetTargetSpeed(const float InTargetSpeed = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
float GetTargetSpeed() const { return TargetSpeed; }
|
||||||
|
|
||||||
|
void Internal_TargetSpeedChanged(const float OldValue = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintImplementableEvent, Category = "Lucky Robot Pawn")
|
||||||
|
void TargetSpeedChanged(const float NewValue = 0.f, const float OldValue = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
ULuckyRobotMovementComponent* GetRobotMovementComponent() const { return RobotMovementComponent.Get(); }
|
||||||
|
|
||||||
|
// TORQUE LIMITER
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
void SetTorqueLimiter(const float InTorqueLimiter = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
float GetTorqueLimiter() const { return TorqueLimiter; }
|
||||||
|
|
||||||
|
void Internal_TorqueLimiterChanged(const float OldValue = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintImplementableEvent, Category = "Lucky Robot Pawn")
|
||||||
|
void TorqueLimiterChanged(const float NewValue = 0.f, const float OldValue = 0.f);
|
||||||
|
|
||||||
|
// CURRENT TASK INDEX
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
void SetCurrentTaskIndex(const int32 InCurrentTaskIndex = -1);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
int32 GetCurrentTaskIndex() const { return CurrentTaskIndex; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
void IncrementCurrentTask();
|
||||||
|
|
||||||
|
void Internal_CurrentTaskIndexChanged(const int32 OldValue = -1);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintImplementableEvent, Category = "Lucky Robot Pawn")
|
||||||
|
void CurrentTaskIndexChanged(const int32 NewValue = 0, const int32 OldValue = 0);
|
||||||
|
|
||||||
|
// TASK LIST
|
||||||
|
// we should have the game instance broadcast a delegate with the TaskList and we just bind to it here and update when it changes
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
int32 GetTaskCount();
|
||||||
|
|
||||||
|
// TASK TIME
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
bool HasTaskExpired();
|
||||||
|
|
||||||
|
// MUJOCO
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
AMujocoVolumeActor* GetMujocoVolumeActor() const { return MujocoVolumeSettings.Get(); }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
void InitializeMujocoVolumeActor();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky Robot Pawn")
|
||||||
|
void InitializeMovementComponent();
|
||||||
|
|
||||||
|
// ROBOT DATA
|
||||||
|
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Lucky Robot Pawn")
|
||||||
|
FRobotSettings RobotSettings = FRobotSettings();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
ULuckyWorldSubsystem* GetLuckyWorldSubsystem();
|
||||||
|
|
||||||
|
// INPUTS
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky Robot Pawn")
|
||||||
|
UEnhancedInputComponent* GetEnhancedInputComponent() const { return EnhancedInputComponent.Get(); }
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||||
|
UInputMappingContext* DefaultMappingContext;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||||
|
UInputAction* MoveAction;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||||
|
UInputAction* TurnAction;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||||
|
UInputAction* LookAction;
|
||||||
|
|
||||||
|
void MoveStart(const FInputActionValue& Value);
|
||||||
|
void Move(const FInputActionValue& Value);
|
||||||
|
void MoveStop(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
void TurnStart(const FInputActionValue& Value);
|
||||||
|
void Turn(const FInputActionValue& Value);
|
||||||
|
void TurnStop(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
void Look(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
void RemoveMujocoVolumeActor();
|
||||||
|
|
||||||
|
TWeakObjectPtr<ULuckyRobotsGameInstance> LuckyGameInstance;
|
||||||
|
TWeakObjectPtr<AMujocoVolumeActor> MujocoVolumeSettings;
|
||||||
|
TWeakObjectPtr<ULuckyRobotMovementComponent> RobotMovementComponent;
|
||||||
|
TWeakObjectPtr<ULuckyWorldSubsystem> LuckyWorldSubsystem;
|
||||||
|
TWeakObjectPtr<UEnhancedInputComponent> EnhancedInputComponent;
|
||||||
|
|
||||||
|
TArray<FStretchRobotActuator> Actuators;
|
||||||
|
|
||||||
|
float AccelerationRate = 1.f;
|
||||||
|
FVector2D CachedMovementInputValues = FVector2D::ZeroVector;
|
||||||
|
|
||||||
|
ERobotInputType PreviousInputType = ERobotInputType::None;
|
||||||
|
ERobotInputType CurrentInputType = ERobotInputType::None;
|
||||||
|
|
||||||
|
float TargetSpeed = 0.f;
|
||||||
|
float TorqueLimiter = 0.85f;
|
||||||
|
int32 CurrentTaskIndex = -1;
|
||||||
|
float TaskTime = 0.f;
|
||||||
|
};
|
78
Source/LuckyWorldV2/Public/Subsystems/LuckyWorldSubsystem.h
Normal file
78
Source/LuckyWorldV2/Public/Subsystems/LuckyWorldSubsystem.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Subsystems/WorldSubsystem.h"
|
||||||
|
#include "LuckyWorldSubsystem.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AMujocoVolumeActor;
|
||||||
|
class ALuckyRobotPawnBase;
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FLuckyRobotSimulationReadyDelegate);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuckyRobotPawnReadyDelegate, ALuckyRobotPawnBase*, LuckyRobot);
|
||||||
|
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);
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class LUCKYWORLDV2_API ULuckyWorldSubsystem : public UWorldSubsystem
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
public:
|
||||||
|
// GENERAL
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
|
FLuckyRobotSimulationReadyDelegate LuckyRobotSimulationReady;
|
||||||
|
|
||||||
|
void CheckSimulationReady();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Lucky World Subsystem")
|
||||||
|
bool IsSimulationReady() const { return bSimulationReady; }
|
||||||
|
|
||||||
|
// LUCKY ROBOT
|
||||||
|
void RegisterLuckyRobot(ALuckyRobotPawnBase* InLuckyRobot);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky World Subsystem")
|
||||||
|
ALuckyRobotPawnBase* GetLuckyRobot() const { return LuckyRobotPawn.Get(); }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
|
FLuckyRobotPawnReadyDelegate LuckyRobotReady;
|
||||||
|
|
||||||
|
// CURRENT TASK
|
||||||
|
void UpdateCurrentTaskIndex(const float InCurrentTaskIndex = -1);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky World Subsystem")
|
||||||
|
float GetCurrentTaskIndex() const { return Robot_CurrentTaskIndex; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
|
FLuckyRobotCurrentTaskChangedDelegate CurrentTaskIndexChanged;
|
||||||
|
|
||||||
|
// TARGET SPEED
|
||||||
|
void UpdateTargetSpeed(const float InTargetSpeed = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky World Subsystem")
|
||||||
|
float GetTargetSpeed() const { return Robot_TargetSpeed; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
|
FLuckyRobotTargetSpeedChangedDelegate TargetSpeedChanged;
|
||||||
|
|
||||||
|
// TORQUE LIMITER
|
||||||
|
void UpdateTorqueLimiter(const float InTorqueLimiter = 0.f);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Lucky World Subsystem")
|
||||||
|
float GetTorqueLimiter() const { return Robot_TorqueLimiter; }
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Lucky World Subsystem")
|
||||||
|
FLuckyRobotTorqueLimiterChangedDelegate TorqueLimiterChanged;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TWeakObjectPtr<ALuckyRobotPawnBase> LuckyRobotPawn;
|
||||||
|
TWeakObjectPtr<AMujocoVolumeActor> MujocoVolumeActor;
|
||||||
|
|
||||||
|
float Robot_TargetSpeed = 0.f;
|
||||||
|
float Robot_TorqueLimiter = 0.85f;
|
||||||
|
int32 Robot_CurrentTaskIndex = -1;
|
||||||
|
|
||||||
|
bool bSimulationReady = false;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user