ACharacter defaults bUseControllerRotationYaw to true, which makes
the Controller's rotation overwrite the actor's rotation every tick
-- stomping our manual AddActorLocalRotation calls almost immediately
(visible as a barely-perceptible tick instead of a turn). Plain Pawn
(the ship) doesn't have this default, which is why the same rotation
logic worked fine there. Disabled it on both the class default and
the placed instance.
F key on the ship: teleports the player character to just above the
ship's location and possesses it. F key on the character: possesses
the ship back. Same controller, so possessing one pawn automatically
unpossesses the other.
Notable implementation detail: GameplayStatics::GetActorOfClass
looked like the obvious way to find "the other pawn" at runtime, but
this MCP plugin's pin_defaults mechanism can't correctly set a Class-
type pin (it accepts the string silently but the compiler later
rejects it as an invalid default) -- there's no supported node type
for a class-literal either. Worked around it by adding real object-
reference variables (PlayerCharacterRef / ShipPawnRef) via
unreal.BlueprintEditorLibrary.get_object_reference_type() directly
through the Python escape hatch, marking them instance-editable, and
wiring the actual actor references between the two placed level
instances. Avoids needing any runtime class lookup at all.
BP_PlayerCharacter (Character-based): first-person camera, WASD
movement + A/D turning (same input scheme as the ship), SuitOxygen
stat that depletes each tick, clamped at 0. Not auto-possessed yet --
that's the ship exit/enter transition (next task). Placed one
instance in L_TestFlight near the ship spawn.
Also reverted level gravity to default (-980): FloatingPawnMovement
(ship) never reads world gravity regardless of its value, but
CharacterMovementComponent (this character) needs real gravity to
walk normally. Zero gravity was an unnecessary leftover from Phase 0
that would have broken on-foot movement.
Added a landing zone as a region of the existing test level (at
X=8000) rather than a separate level/L_Landing01 -- avoids needing
level-streaming and cross-level pawn-transfer machinery that Phase 1
doesn't need yet. Ground platform (scaled plane), 3 scattered rock
obstacles, and a flat landing pad marker disc.
CameraBoom was parented to ShipMesh, which is rotated 90deg to point
the placeholder cone forward -- the camera inherited that rotation,
producing a badly skewed near-edge-on view. Reparented CameraBoom to
the actor root instead, so its pitch is relative to actor-forward,
not the mesh's cosmetic rotation.
Also added 5 marker cubes around the spawn point: the level was
completely empty, so with a rigidly-attached chase camera, forward/
backward translation had zero visual reference and could look like
nothing was happening even if movement was working correctly.
The level had zero actors besides the ship, so it rendered fully
black (no directional light, no sky light). Added a DirectionalLight
and a real-time-capture SkyLight so the placeholder ship is actually
visible during PIE testing.
BP_ShipPawn: cone mesh, FloatingPawnMovement for gravity-free flight,
spring-arm chase camera. Placed in L_TestFlight and set to
auto-possess Player 0 for PIE testing. No input wiring yet.