ue4-玩家控制器APlayerController

通过 APlayerController 可以让输入设备控制游戏,可以直接在蓝图中设置,不过我比较喜欢折腾c++(逻辑代码都是用c++写)


1、创建一个 AMyPlayerCtrler 继承自 APlayerController,重写一些方法

AMyPlayerCtrler.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "MyPlayerCtrler.generated.h"

class UMyInput;
class UMyCameraComp;
class AMySpectator;
class AMyChar;

UCLASS()
class AMyPlayerCtrler : public APlayerController
{
GENERATED_BODY()

public:
AMyPlayerCtrler();
virtual ~AMyPlayerCtrler();

protected:
/** True if the controlled character should navigate to the mouse cursor. */
uint32 bMoveToMouseCursor : 1;

// Begin PlayerController interface
virtual void PlayerTick(float DeltaTime) override;
virtual void SetupInputComponent() override;
virtual void ProcessPlayerInput(const float DeltaTime, const bool bGamePaused) override;
// End PlayerController interface

void OnLeftMousePressed();
void OnRightMousePressed();

void OnReadAtk();

private:
TArray<AMyChar*> mSelectedVec;
bool mIsReadyAtk;

AMyPlayerCtrler.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
void AMyPlayerCtrler::SetupInputComponent()
{
// set up gameplay key bindings
Super::SetupInputComponent();

//LeftMouse 和 RightMouse 就是等下要在Editor中绑定按键用的,
InputComponent->BindAction("LeftMouse", IE_Pressed, this, &AMyPlayerCtrler::OnLeftMousePressed);
InputComponent->BindAction("RightMouse", IE_Pressed, this, &AMyPlayerCtrler::OnRightMousePressed);

//按A键,准备攻击
InputComponent->BindAction("ReadyAtk", IE_Pressed, this, &AMyPlayerCtrler::OnReadAtk);
}

//一下几个方法只是部分代码
void AMyPlayerCtrler::OnLeftMousePressed()
{
FVector2D pressPos;
this->GetMousePosition(pressPos.X, pressPos.Y);
UE_LOG(GameLogger, Warning, TEXT("--- AMyPlayerCtrler::OnLeftMousePressed, pos:%s"), *pressPos.ToString());

bool isAtk = false;
FVector WorldPosition(0.f);
AActor* const HitActor = GetClickTarget(pressPos, WorldPosition);
AMyChar* tarChar = Cast<AMyChar>(HitActor);
if (mSelectedVec.Num() > 0)
{
if (mIsReadyAtk)
{
//如果有人就锁定目标, 没人就移动

if (tarChar != nullptr)
{
AtkTarget(tarChar);
}
else
{
MoveDestination(WorldPosition);
}

isAtk = true;
mIsReadyAtk = false;
}
}

if (!isAtk)
{
TArray<AMyChar*> dstCharVec;
if (tarChar != nullptr)
{
dstCharVec.Add(tarChar);
}
SetSelected(dstCharVec);
}


}

void AMyPlayerCtrler::OnRightMousePressed()
{
FVector2D pressPos;
this->GetMousePosition(pressPos.X, pressPos.Y);
UE_LOG(GameLogger, Warning, TEXT("--- AMyPlayerCtrler::OnLeftMousePressed, pos:%s"), *pressPos.ToString());

FHitResult HitResult;
this->GetHitResultAtScreenPosition(pressPos, CurrentClickTraceChannel, true, HitResult);
if (HitResult.bBlockingHit)
{
MoveDestination(HitResult.ImpactPoint);
}
}

void AMyPlayerCtrler::OnReadAtk()
{
mIsReadyAtk = true;
}

2、Editor 中绑定按键事件 LeftMouseRightMouse

这里写图片描述

这里写图片描述

3、这里是真相

LeftMouse 是选中对象,RightMouse是选中对象奔跑到目的点(gif录制实在太大,只能截图了)
这里写图片描述

这里写图片描述

这里写图片描述



应要求贴部分代码

1
2
3
4
5
6
7
void AMyPlayerCtrler::MoveDestination(const FVector& DestLocation)
{
for (AMyChar* selChar : mSelectedVec)
{
selChar->MoveToDst(nullptr, DestLocation, false);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// class AMyChar : public ACharacter, public IBehavInterface, public IMyInputInterface //继承了输入操作的方法

void IMyInputInterface::MoveToDst(AMyChar* _target, const FVector& _loc, bool _isShift /* = false */)
{
if (mOwnChar->GetCharacterMovement()->Velocity.Size() > 0.f)
{
mOwnChar->GetController()->StopMovement();
}

UNavigationSystem* const NavSys = mOwnChar->GetWorld()->GetNavigationSystem();
if (NavSys != nullptr)
{
NavSys->SimpleMoveToLocation(mOwnChar->GetController(), _loc);
}
}