3c69445d90
- 移除跳跃逻辑:删除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
177 lines
6.4 KiB
C++
177 lines
6.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
||
#include "ChildHoodCharacter.h"
|
||
#include "Engine/LocalPlayer.h"
|
||
#include "Camera/CameraComponent.h"
|
||
#include "Components/CapsuleComponent.h"
|
||
#include "GameFramework/CharacterMovementComponent.h"
|
||
#include "GameFramework/SpringArmComponent.h"
|
||
#include "GameFramework/Controller.h"
|
||
#include "EnhancedInputComponent.h"
|
||
#include "EnhancedInputSubsystems.h"
|
||
#include "InputActionValue.h"
|
||
#include "ChildHood.h"
|
||
|
||
AChildHoodCharacter::AChildHoodCharacter()
|
||
{
|
||
// Set size for collision capsule
|
||
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
|
||
|
||
// Don't rotate when the controller rotates. Let that just affect the camera.
|
||
bUseControllerRotationPitch = false;
|
||
bUseControllerRotationYaw = false;
|
||
bUseControllerRotationRoll = false;
|
||
|
||
// Configure character movement — v0.1 player controller tech design parameters
|
||
auto* CMC = GetCharacterMovement();
|
||
CMC->bOrientRotationToMovement = true; // 角色朝移动方向旋转
|
||
CMC->RotationRate = FRotator(0.0f, 720.0f, 0.0f); // 转向速度 720°/s(远快于鼠标 150°/s)
|
||
CMC->MaxWalkSpeed = 450.0f; // 跑步速度 4.5 m/s
|
||
CMC->MaxAcceleration = 2250.0f; // 起步加速 0.2s (450/0.2)
|
||
CMC->BrakingDecelerationWalking = 1500.0f; // 停止减速 0.3s (450/0.3)
|
||
CMC->BrakingDecelerationFalling = 1500.0f;
|
||
CMC->MinAnalogWalkSpeed = 20.f;
|
||
// WalkableFloorAngle 默认 45°,无需修改
|
||
// v0.1 不跳跃,不设置 JumpZVelocity / AirControl
|
||
|
||
// Create a camera boom (pulls in towards the player if there is a collision)
|
||
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
|
||
CameraBoom->SetupAttachment(RootComponent);
|
||
CameraBoom->TargetArmLength = 350.0f; // 摄像机距离 3.5m
|
||
CameraBoom->SocketOffset = FVector(0.f, 0.f, 80.f); // 摄像机高度 0.8m(头部上方)
|
||
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
|
||
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
|
||
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
|
||
FollowCamera->bUsePawnControlRotation = false;
|
||
}
|
||
|
||
void AChildHoodCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||
{
|
||
// Set up action bindings
|
||
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
|
||
|
||
// Moving
|
||
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);
|
||
|
||
// Interaction IAs — bind to placeholder callbacks; interaction system will hook into these
|
||
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
|
||
{
|
||
UE_LOG(LogChildHood, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
|
||
}
|
||
}
|
||
|
||
void AChildHoodCharacter::Move(const FInputActionValue& Value)
|
||
{
|
||
// input is a Vector2D
|
||
FVector2D MovementVector = Value.Get<FVector2D>();
|
||
|
||
// route the input
|
||
DoMove(MovementVector.X, MovementVector.Y);
|
||
}
|
||
|
||
void AChildHoodCharacter::Look(const FInputActionValue& Value)
|
||
{
|
||
// input is a Vector2D
|
||
FVector2D LookAxisVector = Value.Get<FVector2D>();
|
||
|
||
// route the input
|
||
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)
|
||
{
|
||
// P1: 交互中忽略移动输入
|
||
if (bIsInteracting)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (GetController() != nullptr)
|
||
{
|
||
// find out which way is forward
|
||
const FRotator Rotation = GetController()->GetControlRotation();
|
||
const FRotator YawRotation(0, Rotation.Yaw, 0);
|
||
|
||
// get forward vector
|
||
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
|
||
|
||
// get right vector
|
||
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
|
||
|
||
// add movement
|
||
AddMovementInput(ForwardDirection, Forward);
|
||
AddMovementInput(RightDirection, Right);
|
||
}
|
||
}
|
||
|
||
void AChildHoodCharacter::DoLook(float Yaw, float Pitch)
|
||
{
|
||
if (GetController() != nullptr)
|
||
{
|
||
// add yaw and pitch input to controller
|
||
AddControllerYawInput(Yaw);
|
||
AddControllerPitchInput(Pitch);
|
||
}
|
||
}
|
||
|
||
void AChildHoodCharacter::SetInteracting(bool bValue)
|
||
{
|
||
bIsInteracting = bValue;
|
||
}
|
||
|
||
bool AChildHoodCharacter::IsInteracting() const
|
||
{
|
||
return bIsInteracting;
|
||
}
|
||
|
||
bool AChildHoodCharacter::IsRunning() const
|
||
{
|
||
return GetVelocity().SizeSquared() > 100.f // 速度 > 10 cm/s 阈值
|
||
&& GetCharacterMovement()->IsMovingOnGround();
|
||
}
|