diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_PlayerController.cpp b/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_PlayerController.cpp index 0ae5fb8..30b7250 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_PlayerController.cpp +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_PlayerController.cpp @@ -10,6 +10,9 @@ #include "PS_Editor_SplineEditable.h" #include "PS_Editor_PointPlaceable.h" #include "Engine/LevelStreamingDynamic.h" +#include "GameFramework/Character.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "PS_Editor_SpawnableComponent.h" #include "Engine/PostProcessVolume.h" #include "PS_Editor_CameraStart.h" #include "PS_Editor_ChildMovable.h" @@ -256,7 +259,7 @@ void APS_Editor_PlayerController::StartSimulation() SelectionManager->ClearSelection(); } - // Enable AI logic on all spawned pawns + // Enable AI logic on all spawned pawns and restore movement settings from class defaults if (SpawnManager) { for (const TWeakObjectPtr& Weak : SpawnManager->GetSpawnedActors()) @@ -264,6 +267,25 @@ void APS_Editor_PlayerController::StartSimulation() if (APawn* P = Cast(Weak.Get())) { P->SetActorTickEnabled(true); + + // Restore rotation/movement settings saved when AI was disabled + UPS_Editor_SpawnableComponent* SaveComp = P->FindComponentByClass(); + if (SaveComp && SaveComp->bSavedMovementState) + { + P->bUseControllerRotationYaw = SaveComp->bSavedUseControllerRotationYaw; + P->bUseControllerRotationPitch = SaveComp->bSavedUseControllerRotationPitch; + P->bUseControllerRotationRoll = SaveComp->bSavedUseControllerRotationRoll; + if (ACharacter* Char = Cast(P)) + { + if (UCharacterMovementComponent* Move = Char->GetCharacterMovement()) + { + Move->bOrientRotationToMovement = SaveComp->bSavedOrientRotationToMovement; + Move->bUseControllerDesiredRotation = SaveComp->bSavedUseControllerDesiredRotation; + Move->SetMovementMode(SaveComp->SavedMovementMode, SaveComp->SavedCustomMovementMode); + } + } + } + if (AAIController* AIC = Cast(P->GetController())) { AIC->SetActorTickEnabled(true); @@ -315,7 +337,7 @@ void APS_Editor_PlayerController::StopSimulation() if (!bSimulating) return; bSimulating = false; - // Disable AI logic on all spawned pawns + // Disable AI logic and re-apply rotation/movement overrides on all spawned pawns if (SpawnManager) { for (const TWeakObjectPtr& Weak : SpawnManager->GetSpawnedActors()) @@ -331,6 +353,20 @@ void APS_Editor_PlayerController::StopSimulation() Brain->StopLogic(TEXT("PS_Editor")); } } + + // Re-apply editor overrides (values were already saved at first disable) + if (ACharacter* Char = Cast(P)) + { + if (UCharacterMovementComponent* Move = Char->GetCharacterMovement()) + { + Move->bOrientRotationToMovement = false; + Move->bUseControllerDesiredRotation = false; + Move->SetMovementMode(MOVE_None); + } + } + P->bUseControllerRotationYaw = false; + P->bUseControllerRotationPitch = false; + P->bUseControllerRotationRoll = false; } } } diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneLoader.cpp b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneLoader.cpp index 55052f7..cbbd49a 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneLoader.cpp +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneLoader.cpp @@ -10,6 +10,8 @@ #include "PS_Editor_TimelineSubsystem.h" #include "PS_Editor_SpawnManager.h" #include "PS_Editor_PlayerController.h" +#include "AIController.h" +#include "BrainComponent.h" #include "JsonObjectConverter.h" #include "Misc/FileHelper.h" #include "Misc/Paths.h" @@ -160,7 +162,47 @@ bool UPS_Editor_SceneLoader::LoadSceneFromData(UWorld* World, const FPS_Editor_S TimelineSS->SetData(SceneData.Timeline); if (!IsInEditorMode() && SceneData.Timeline.Tracks.Num() > 0) { - TimelineSS->Play(); + // Start timeline only when all spawned pawns have their BT running. + // Poll each tick until ready to avoid firing keys before AI-driven sequences start. + TWeakObjectPtr WeakTS = TimelineSS; + TArray> WeakPawns; + for (AActor* A : OutActors) + { + if (APawn* P = Cast(A)) WeakPawns.Add(P); + } + TWeakObjectPtr WeakWorld = World; + TSharedPtr PollTimerPtr = MakeShared(); + TSharedPtr PollCount = MakeShared(0); + + World->GetTimerManager().SetTimer(*PollTimerPtr, [WeakTS, WeakPawns, WeakWorld, PollTimerPtr, PollCount]() + { + (*PollCount)++; + + // Check all pawns have an AIController with a running BrainComponent + bool bAllReady = true; + for (const TWeakObjectPtr& WeakP : WeakPawns) + { + APawn* P = WeakP.Get(); + if (!P) continue; + AAIController* AIC = Cast(P->GetController()); + if (!AIC) { bAllReady = false; continue; } + UBrainComponent* Brain = AIC->GetBrainComponent(); + if (!Brain || !Brain->IsRunning()) { bAllReady = false; continue; } + } + + // Wait for all pawns AND at least 2 poll cycles to ensure BT has started its first task + if (bAllReady && *PollCount >= 2) + { + if (UPS_Editor_TimelineSubsystem* TS = WeakTS.Get()) + { + TS->Play(); + } + if (UWorld* W = WeakWorld.Get()) + { + W->GetTimerManager().ClearTimer(*PollTimerPtr); + } + } + }, 0.1f, true); // poll every 100ms } } diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneSerializer.cpp b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneSerializer.cpp index 60c192c..9a25ed6 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneSerializer.cpp +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Serialization/PS_Editor_SceneSerializer.cpp @@ -10,6 +10,8 @@ #include "PS_Editor_SplineActor.h" #include "AIController.h" #include "BrainComponent.h" +#include "GameFramework/Character.h" +#include "GameFramework/CharacterMovementComponent.h" #include "PS_Editor_SplineEditable.h" #include "PS_Editor_TimelineSubsystem.h" #include "JsonObjectConverter.h" @@ -348,6 +350,39 @@ bool UPS_Editor_SceneSerializer::LoadScene(const FString& SceneName, UPS_Editor_ Brain->StopLogic(TEXT("PS_Editor")); } } + + // Save original movement/rotation state on SpawnableComponent, then override + UPS_Editor_SpawnableComponent* SaveComp = Pawn->FindComponentByClass(); + if (SaveComp && !SaveComp->bSavedMovementState) + { + SaveComp->bSavedUseControllerRotationYaw = Pawn->bUseControllerRotationYaw; + SaveComp->bSavedUseControllerRotationPitch = Pawn->bUseControllerRotationPitch; + SaveComp->bSavedUseControllerRotationRoll = Pawn->bUseControllerRotationRoll; + if (ACharacter* Char = Cast(Pawn)) + { + if (UCharacterMovementComponent* Move = Char->GetCharacterMovement()) + { + SaveComp->bSavedOrientRotationToMovement = Move->bOrientRotationToMovement; + SaveComp->bSavedUseControllerDesiredRotation = Move->bUseControllerDesiredRotation; + SaveComp->SavedMovementMode = Move->MovementMode; + SaveComp->SavedCustomMovementMode = Move->CustomMovementMode; + } + } + SaveComp->bSavedMovementState = true; + } + + if (ACharacter* Char = Cast(Pawn)) + { + if (UCharacterMovementComponent* Move = Char->GetCharacterMovement()) + { + Move->bOrientRotationToMovement = false; + Move->bUseControllerDesiredRotation = false; + Move->SetMovementMode(MOVE_None); + } + } + Pawn->bUseControllerRotationYaw = false; + Pawn->bUseControllerRotationPitch = false; + Pawn->bUseControllerRotationRoll = false; }; DisableAI(P); diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnManager.cpp b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnManager.cpp index 7715a16..953e56e 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnManager.cpp +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnManager.cpp @@ -8,6 +8,8 @@ #include "AIController.h" #include "BrainComponent.h" #include "GameFramework/PlayerController.h" +#include "GameFramework/Character.h" +#include "GameFramework/CharacterMovementComponent.h" #include "Engine/World.h" namespace @@ -209,6 +211,40 @@ AActor* UPS_Editor_SpawnManager::SpawnFromCatalogAtLocation(int32 Index, FVector Brain->StopLogic(TEXT("PS_Editor")); } } + + // Save original movement/rotation state on SpawnableComponent, then override + UPS_Editor_SpawnableComponent* SaveComp = Pawn->FindComponentByClass(); + if (SaveComp && !SaveComp->bSavedMovementState) + { + SaveComp->bSavedUseControllerRotationYaw = Pawn->bUseControllerRotationYaw; + SaveComp->bSavedUseControllerRotationPitch = Pawn->bUseControllerRotationPitch; + SaveComp->bSavedUseControllerRotationRoll = Pawn->bUseControllerRotationRoll; + if (ACharacter* Char = Cast(Pawn)) + { + if (UCharacterMovementComponent* Move = Char->GetCharacterMovement()) + { + SaveComp->bSavedOrientRotationToMovement = Move->bOrientRotationToMovement; + SaveComp->bSavedUseControllerDesiredRotation = Move->bUseControllerDesiredRotation; + SaveComp->SavedMovementMode = Move->MovementMode; + SaveComp->SavedCustomMovementMode = Move->CustomMovementMode; + } + } + SaveComp->bSavedMovementState = true; + } + + // Override to prevent auto-rotation in editor + if (ACharacter* Char = Cast(Pawn)) + { + if (UCharacterMovementComponent* Move = Char->GetCharacterMovement()) + { + Move->bOrientRotationToMovement = false; + Move->bUseControllerDesiredRotation = false; + Move->SetMovementMode(MOVE_None); + } + } + Pawn->bUseControllerRotationYaw = false; + Pawn->bUseControllerRotationPitch = false; + Pawn->bUseControllerRotationRoll = false; }; DisableAI(SpawnedPawn); diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnableComponent.h b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnableComponent.h index 1e26bf6..07f4f86 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnableComponent.h +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/Spawn/PS_Editor_SpawnableComponent.h @@ -2,6 +2,7 @@ #include "CoreMinimal.h" #include "Components/ActorComponent.h" +#include "Engine/EngineTypes.h" #include "PS_Editor_SpawnableComponent.generated.h" /** @@ -52,4 +53,15 @@ public: * Use scene loading filters to load only preload actors or exclude them. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawnable") bool bPreload = false; + + // ---- Runtime-only: saved movement/rotation settings before editor override ---- + // Set when the editor disables AI/rotation overrides, restored on StartSimulation. + bool bSavedMovementState = false; + bool bSavedUseControllerRotationYaw = false; + bool bSavedUseControllerRotationPitch = false; + bool bSavedUseControllerRotationRoll = false; + bool bSavedOrientRotationToMovement = false; + bool bSavedUseControllerDesiredRotation = false; + TEnumAsByte SavedMovementMode = MOVE_Walking; + uint8 SavedCustomMovementMode = 0; };