feat: first-person player with Enhanced Input

AGigLineCharacter: 1.75 m capsule, 1.60 m eye camera, 4 m/s walk, mouse look
scaled in degrees per second (no double DeltaTime), jump. Loaded ahead of a
Blueprint so the demo is playable with no assets wired by hand.

Tools/ue_create_input_assets.py builds /Game/Input headlessly: five 1D actions
and an 11-mapping context. One action per direction instead of per-key modifiers,
because modifier objects do not survive the save path here: a mapping's modifier
array serialises None, and dimensioning a 2D move with per-key axis masks would
need exactly those modifiers. The cost is four action assets rather than two.

Also adds a fourth review camera at eye height and documents it; its approval is
pending.
This commit is contained in:
zwitschi committed 2026-11-07 10:05:13 +01:00
1 parent b3815499e0
commit a0de0a6626
16 files changed
+522 -8

No files matched your search

@@ -0,0 +1,86 @@
// First-person player character for the 0.1.0 walkable Hollywood block.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "GigLineCharacter.generated.h"
class UCameraComponent;
class UInputAction;
class UInputMappingContext;
/**
* Walking first-person character.
*
* Movement is C++ and network-agnostic in the shapes it uses (Enhanced Input ->
* AddMovementInput), so a Blueprint subclass can retune values without touching
* code. Defaults are human-scale: 1.75 m capsule, 1.6 m eye height, 4 m/s walk.
*/
UCLASS()
class GIGLINE_API AGigLineCharacter : public ACharacter
{
GENERATED_BODY()
public:
AGigLineCharacter();
virtual void BeginPlay() override;
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
/** Loads the Enhanced Input assets from /Game/Input; called from BeginPlay. */
void LoadInputAssets();
/** Moves along the control yaw by the given forward/strafe amounts. */
void ApplyMove(float Forward, float Strafe);
/** Handles input actions to movement; assigned in C++ so the project runs with no assets. */
/** Forward/back and strafe are separate 1D actions, summed into one move. */
void MoveForward(const FInputActionValue& Value);
void MoveStrafe(const FInputActionValue& Value);
void MoveBack(const FInputActionValue& Value);
void MoveLeft(const FInputActionValue& Value);
void Look(const FInputActionValue& Value);
void StartJump();
void StopJump();
/** Mapping context for the gamepad and keyboard. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputMappingContext> MappingContext;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> MoveAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> MoveBackAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> StrafeAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> StrafeLeftAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> LookAction;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> JumpAction;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
TObjectPtr<UCameraComponent> FirstPersonCamera;
/** Degrees per second per unit of mouse input; defaults to Unreal's usual 45. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera")
float LookSensitivity = 45.0f;
/** Invert the pitch axis, for players who prefer it. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera")
bool bInvertLookY = false;
/** Walk speed in metres per second; converted to Unreal units on first use. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
float WalkSpeedMetresPerSecond = 4.0f;
};