feat(review): deterministic walking capture, and the defect it exposed
The shot actor can now photograph a moving pawn: a per-shot ShotFollow flag re-places the camera every frame at a fixed offset in the pawn's frame, and the walk is driven per shot (SetReviewWalk) with the pawn returned to spawn after a follow shot, so the fixed-camera shots later in the list still find it in place. With that, the capture stopped depending on where a 4.5 m/s pawn happened to be. Two further bugs fixed on the way: - the engine's screenshot folder is cleared before each run. The collect step copies every review-*.png it finds in Saved/, so a shot retired from the camera list kept reappearing with byte-identical content from an older run - which is how a walk shot that was never captured looked like a captured one. - UpdateBodyAnimation no longer calls SetAnimation every frame. Re-setting the same clip restarts it, which freezes the body on frame 0. What the deterministic capture then exposed: the walk clip is applied but does not advance - every walking frame shows the same pose (arms forward, legs together). The stride shot is retired again rather than shipped, and TODO.md names the next step: log GetCurrentAssetTime across frames and check the imported PlayRate. The harness stays wired for when the clip plays. Shots 6 and 7 were re-rendered after these changes and still pass; 7/7 verify.
This commit is contained in:
1 parent
f84093adba
commit
eeeabe56b1
42 files changed
+160
-68
No files matched your search
@@ -1,5 +1,8 @@
|
||||
#include "GigLineShotActor.h"
|
||||
|
||||
#include "GigLineCharacter.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
#include "Camera/CameraActor.h"
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "Engine/World.h"
|
||||
@@ -32,6 +35,12 @@ void AGigLineShotActor::Tick(float DeltaSeconds)
|
||||
|
||||
if (bWaitingForSettle)
|
||||
{
|
||||
// A follow shot tracks the pawn while it settles, otherwise the subject
|
||||
// walks out of the frame between placement and capture.
|
||||
if (CurrentShot < ShotFollow.Num() && ShotFollow[CurrentShot])
|
||||
{
|
||||
UpdateFollowCamera();
|
||||
}
|
||||
SettleCountdown -= DeltaSeconds;
|
||||
if (SettleCountdown <= 0.f)
|
||||
{
|
||||
@@ -53,11 +62,40 @@ void AGigLineShotActor::Tick(float DeltaSeconds)
|
||||
{
|
||||
bWaitingForScreenshot = false;
|
||||
UE_LOG(LogTemp, Log, TEXT("GigLineShotActor: captured %s"), *FScreenshotRequest::GetFilename());
|
||||
// Walking shots move the pawn; put it back before the fixed-camera shots run.
|
||||
if (ShotFollow.IsValidIndex(CurrentShot) && ShotFollow[CurrentShot])
|
||||
{
|
||||
if (AGigLineCharacter* Character = Cast<AGigLineCharacter>(UGameplayStatics::GetPlayerPawn(this, 0)))
|
||||
{
|
||||
Character->ReturnToStartForReview();
|
||||
}
|
||||
}
|
||||
++CurrentShot;
|
||||
NextShot();
|
||||
}
|
||||
}
|
||||
|
||||
void AGigLineShotActor::UpdateFollowCamera()
|
||||
{
|
||||
if (!CurrentCamera)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0);
|
||||
if (!Pawn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Offset in the pawn's frame: to its right, slightly above, looking at the
|
||||
// pelvis. Right-of-pawn gives a profile view, which is where a stride reads.
|
||||
const FVector Right = Pawn->GetActorRightVector();
|
||||
const FVector Origin = Pawn->GetActorLocation();
|
||||
const FVector CameraLocation = Origin + Right * 420.f + FVector(0.f, 0.f, 90.f);
|
||||
const FVector Target = Origin + FVector(0.f, 0.f, 40.f);
|
||||
CurrentCamera->SetActorLocation(CameraLocation);
|
||||
CurrentCamera->SetActorRotation((Target - CameraLocation).Rotation());
|
||||
}
|
||||
|
||||
void AGigLineShotActor::NextShot()
|
||||
{
|
||||
if (!PlayerController)
|
||||
@@ -93,6 +131,20 @@ void AGigLineShotActor::NextShot()
|
||||
Cam->SetFieldOfView(ShotFieldOfView[CurrentShot]);
|
||||
}
|
||||
}
|
||||
// Follow shots ignore their recorded transform after this point: the camera is
|
||||
// rebuilt from the pawn every frame until the capture. They also own the walking:
|
||||
// the pawn only holds forward input while a follow shot is being taken, so the
|
||||
// fixed-camera shots later in the list still find it at the spawn point.
|
||||
const bool bFollowThisShot = ShotFollow.IsValidIndex(CurrentShot) && ShotFollow[CurrentShot];
|
||||
if (AGigLineCharacter* Character = Cast<AGigLineCharacter>(UGameplayStatics::GetPlayerPawn(this, 0)))
|
||||
{
|
||||
Character->SetReviewWalk(bFollowThisShot);
|
||||
}
|
||||
if (bFollowThisShot)
|
||||
{
|
||||
UpdateFollowCamera();
|
||||
}
|
||||
|
||||
PlayerController->SetViewTarget(CurrentCamera);
|
||||
|
||||
SettleCountdown = SettleSeconds;
|
||||
|
||||
Reference in new issue
Block a user