feat(player-controller): 实现v0.1角色控制系统
- 移除跳跃逻辑:删除JumpAction、DoJumpStart/End - 调整CMC参数:MaxWalkSpeed=450, Acceleration=2250, Brake=1500, RotationRate=720 - 调整SpringArm:TargetArmLength=350, SocketOffset.Z=80, CameraLag=6, ProbeSize=12 - 添加Pitch限幅:ViewPitchMin=-30, ViewPitchMax=45, 初始俯角-15° - 新增交互状态:bIsInteracting + SetInteracting/IsInteracting/IsRunning - 新增交互IA:InteractAction/CancelAction/SwitchInteractAction(占位回调) - DoMove添加交互中忽略移动输入检查 Task: P-011
This commit is contained in:
@@ -22,32 +22,39 @@ AChildHoodCharacter::AChildHoodCharacter()
|
|||||||
bUseControllerRotationYaw = false;
|
bUseControllerRotationYaw = false;
|
||||||
bUseControllerRotationRoll = false;
|
bUseControllerRotationRoll = false;
|
||||||
|
|
||||||
// Configure character movement
|
// Configure character movement — v0.1 player controller tech design parameters
|
||||||
GetCharacterMovement()->bOrientRotationToMovement = true;
|
auto* CMC = GetCharacterMovement();
|
||||||
GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f);
|
CMC->bOrientRotationToMovement = true; // 角色朝移动方向旋转
|
||||||
|
CMC->RotationRate = FRotator(0.0f, 720.0f, 0.0f); // 转向速度 720°/s(远快于鼠标 150°/s)
|
||||||
// Note: For faster iteration times these variables, and many more, can be tweaked in the Character Blueprint
|
CMC->MaxWalkSpeed = 450.0f; // 跑步速度 4.5 m/s
|
||||||
// instead of recompiling to adjust them
|
CMC->MaxAcceleration = 2250.0f; // 起步加速 0.2s (450/0.2)
|
||||||
GetCharacterMovement()->JumpZVelocity = 500.f;
|
CMC->BrakingDecelerationWalking = 1500.0f; // 停止减速 0.3s (450/0.3)
|
||||||
GetCharacterMovement()->AirControl = 0.35f;
|
CMC->BrakingDecelerationFalling = 1500.0f;
|
||||||
GetCharacterMovement()->MaxWalkSpeed = 500.f;
|
CMC->MinAnalogWalkSpeed = 20.f;
|
||||||
GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
|
// WalkableFloorAngle 默认 45°,无需修改
|
||||||
GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
|
// v0.1 不跳跃,不设置 JumpZVelocity / AirControl
|
||||||
GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f;
|
|
||||||
|
|
||||||
// Create a camera boom (pulls in towards the player if there is a collision)
|
// Create a camera boom (pulls in towards the player if there is a collision)
|
||||||
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
|
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
|
||||||
CameraBoom->SetupAttachment(RootComponent);
|
CameraBoom->SetupAttachment(RootComponent);
|
||||||
CameraBoom->TargetArmLength = 400.0f;
|
CameraBoom->TargetArmLength = 350.0f; // 摄像机距离 3.5m
|
||||||
|
CameraBoom->SocketOffset = FVector(0.f, 0.f, 80.f); // 摄像机高度 0.8m(头部上方)
|
||||||
CameraBoom->bUsePawnControlRotation = true;
|
CameraBoom->bUsePawnControlRotation = true;
|
||||||
|
|
||||||
|
// 摄像机软跟随
|
||||||
|
CameraBoom->bEnableCameraLag = true; // 启用位置延迟跟随
|
||||||
|
CameraBoom->CameraLagSpeed = 6.0f; // 跟随速度(可调 2-8)
|
||||||
|
CameraBoom->bEnableCameraRotationLag = false; // v0.1 不启用旋转延迟
|
||||||
|
|
||||||
|
// 摄像机碰撞处理
|
||||||
|
CameraBoom->bDoCollisionTest = true; // 启用碰撞检测
|
||||||
|
CameraBoom->ProbeSize = 12.0f; // 碰撞探针半径
|
||||||
|
CameraBoom->ProbeChannel = ECC_Camera; // 使用 Camera 碰撞通道
|
||||||
|
|
||||||
// Create a follow camera
|
// Create a follow camera
|
||||||
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
|
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
|
||||||
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
|
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
|
||||||
FollowCamera->bUsePawnControlRotation = false;
|
FollowCamera->bUsePawnControlRotation = false;
|
||||||
|
|
||||||
// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character)
|
|
||||||
// are set in the derived blueprint asset named ThirdPersonCharacter (to avoid direct content references in C++)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AChildHoodCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
void AChildHoodCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||||
@@ -55,16 +62,26 @@ void AChildHoodCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInput
|
|||||||
// Set up action bindings
|
// Set up action bindings
|
||||||
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
|
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
|
||||||
|
|
||||||
// Jumping
|
|
||||||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
|
|
||||||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
|
|
||||||
|
|
||||||
// Moving
|
// Moving
|
||||||
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AChildHoodCharacter::Move);
|
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AChildHoodCharacter::Move);
|
||||||
|
|
||||||
|
// Looking (gamepad + mouse)
|
||||||
|
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AChildHoodCharacter::Look);
|
||||||
EnhancedInputComponent->BindAction(MouseLookAction, ETriggerEvent::Triggered, this, &AChildHoodCharacter::Look);
|
EnhancedInputComponent->BindAction(MouseLookAction, ETriggerEvent::Triggered, this, &AChildHoodCharacter::Look);
|
||||||
|
|
||||||
// Looking
|
// Interaction IAs — bind to placeholder callbacks; interaction system will hook into these
|
||||||
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AChildHoodCharacter::Look);
|
if (InteractAction)
|
||||||
|
{
|
||||||
|
EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &AChildHoodCharacter::OnInteract);
|
||||||
|
}
|
||||||
|
if (CancelAction)
|
||||||
|
{
|
||||||
|
EnhancedInputComponent->BindAction(CancelAction, ETriggerEvent::Started, this, &AChildHoodCharacter::OnCancel);
|
||||||
|
}
|
||||||
|
if (SwitchInteractAction)
|
||||||
|
{
|
||||||
|
EnhancedInputComponent->BindAction(SwitchInteractAction, ETriggerEvent::Started, this, &AChildHoodCharacter::OnSwitchInteract);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -90,8 +107,30 @@ void AChildHoodCharacter::Look(const FInputActionValue& Value)
|
|||||||
DoLook(LookAxisVector.X, LookAxisVector.Y);
|
DoLook(LookAxisVector.X, LookAxisVector.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AChildHoodCharacter::OnInteract(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
// v0.1 placeholder — interaction system will provide implementation
|
||||||
|
// Interaction system hooks in via blueprint or future C++ delegate
|
||||||
|
}
|
||||||
|
|
||||||
|
void AChildHoodCharacter::OnCancel(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
// v0.1 placeholder — interaction system will provide implementation
|
||||||
|
}
|
||||||
|
|
||||||
|
void AChildHoodCharacter::OnSwitchInteract(const FInputActionValue& Value)
|
||||||
|
{
|
||||||
|
// v0.1 placeholder — interaction system will provide implementation
|
||||||
|
}
|
||||||
|
|
||||||
void AChildHoodCharacter::DoMove(float Right, float Forward)
|
void AChildHoodCharacter::DoMove(float Right, float Forward)
|
||||||
{
|
{
|
||||||
|
// P1: 交互中忽略移动输入
|
||||||
|
if (bIsInteracting)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetController() != nullptr)
|
if (GetController() != nullptr)
|
||||||
{
|
{
|
||||||
// find out which way is forward
|
// find out which way is forward
|
||||||
@@ -120,14 +159,18 @@ void AChildHoodCharacter::DoLook(float Yaw, float Pitch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AChildHoodCharacter::DoJumpStart()
|
void AChildHoodCharacter::SetInteracting(bool bValue)
|
||||||
{
|
{
|
||||||
// signal the character to jump
|
bIsInteracting = bValue;
|
||||||
Jump();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AChildHoodCharacter::DoJumpEnd()
|
bool AChildHoodCharacter::IsInteracting() const
|
||||||
{
|
{
|
||||||
// signal the character to stop jumping
|
return bIsInteracting;
|
||||||
StopJumping();
|
}
|
||||||
|
|
||||||
|
bool AChildHoodCharacter::IsRunning() const
|
||||||
|
{
|
||||||
|
return GetVelocity().SizeSquared() > 100.f // 速度 > 10 cm/s 阈值
|
||||||
|
&& GetCharacterMovement()->IsMovingOnGround();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,10 +33,6 @@ class AChildHoodCharacter : public ACharacter
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** Jump Input Action */
|
|
||||||
UPROPERTY(EditAnywhere, Category="Input")
|
|
||||||
UInputAction* JumpAction;
|
|
||||||
|
|
||||||
/** Move Input Action */
|
/** Move Input Action */
|
||||||
UPROPERTY(EditAnywhere, Category="Input")
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
UInputAction* MoveAction;
|
UInputAction* MoveAction;
|
||||||
@@ -49,6 +45,21 @@ protected:
|
|||||||
UPROPERTY(EditAnywhere, Category="Input")
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
UInputAction* MouseLookAction;
|
UInputAction* MouseLookAction;
|
||||||
|
|
||||||
|
/** Interact Input Action (E key) — delegates to interaction system */
|
||||||
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
|
UInputAction* InteractAction;
|
||||||
|
|
||||||
|
/** Cancel Input Action (ESC key) — delegates to interaction system */
|
||||||
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
|
UInputAction* CancelAction;
|
||||||
|
|
||||||
|
/** Switch Interact Target Input Action (Tab / Mouse Wheel) — delegates to interaction system */
|
||||||
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
|
UInputAction* SwitchInteractAction;
|
||||||
|
|
||||||
|
/** Whether the character is currently in an interaction */
|
||||||
|
bool bIsInteracting = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
@@ -67,6 +78,15 @@ protected:
|
|||||||
/** Called for looking input */
|
/** Called for looking input */
|
||||||
void Look(const FInputActionValue& Value);
|
void Look(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
/** Called for interact input (E) — placeholder, delegates to interaction system */
|
||||||
|
void OnInteract(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
/** Called for cancel input (ESC) — placeholder, delegates to interaction system */
|
||||||
|
void OnCancel(const FInputActionValue& Value);
|
||||||
|
|
||||||
|
/** Called for switch interact target input (Tab/Wheel) — placeholder, delegates to interaction system */
|
||||||
|
void OnSwitchInteract(const FInputActionValue& Value);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Handles move inputs from either controls or UI interfaces */
|
/** Handles move inputs from either controls or UI interfaces */
|
||||||
@@ -77,13 +97,17 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category="Input")
|
UFUNCTION(BlueprintCallable, Category="Input")
|
||||||
virtual void DoLook(float Yaw, float Pitch);
|
virtual void DoLook(float Yaw, float Pitch);
|
||||||
|
|
||||||
/** Handles jump pressed inputs from either controls or UI interfaces */
|
/** Set interaction state — called by interaction system */
|
||||||
UFUNCTION(BlueprintCallable, Category="Input")
|
UFUNCTION(BlueprintCallable, Category="Interaction")
|
||||||
virtual void DoJumpStart();
|
void SetInteracting(bool bValue);
|
||||||
|
|
||||||
/** Handles jump pressed inputs from either controls or UI interfaces */
|
/** Query: is the character currently interacting? */
|
||||||
UFUNCTION(BlueprintCallable, Category="Input")
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Interaction")
|
||||||
virtual void DoJumpEnd();
|
bool IsInteracting() const;
|
||||||
|
|
||||||
|
/** Query: is the character currently running (moving on ground)? */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="Interaction")
|
||||||
|
bool IsRunning() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -93,4 +117,3 @@ public:
|
|||||||
/** Returns FollowCamera subobject **/
|
/** Returns FollowCamera subobject **/
|
||||||
FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
|
FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,19 @@ void AChildHoodPlayerController::BeginPlay()
|
|||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
// C3: 设置摄像机俯仰角限制(垂直旋转 +45°/-30°)
|
||||||
|
if (PlayerCameraManager)
|
||||||
|
{
|
||||||
|
PlayerCameraManager->ViewPitchMin = -30.0f; // 向下看最多 30°
|
||||||
|
PlayerCameraManager->ViewPitchMax = 45.0f; // 向上看最多 45°
|
||||||
|
}
|
||||||
|
|
||||||
|
// C1: 初始俯角 -15°(摄像机默认略向下看向角色)
|
||||||
|
if (GetControlRotation().Pitch == 0.f)
|
||||||
|
{
|
||||||
|
SetControlRotation(FRotator(-15.0f, GetControlRotation().Yaw, GetControlRotation().Roll));
|
||||||
|
}
|
||||||
|
|
||||||
// only spawn touch controls on local player controllers
|
// only spawn touch controls on local player controllers
|
||||||
if (ShouldUseTouchControls() && IsLocalPlayerController())
|
if (ShouldUseTouchControls() && IsLocalPlayerController())
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user