首先,PlayerController自身也是一个Actor,通过它,玩家才能控制游戏中的Actor、Pawn、Character等。
UObject-+
|-AActor-+
|-AController--+
|-APlayerController
如何设置PlayerController才能绑定事件?
对于Actor
在Actor的Blueprint中,通过 Input -> Auto Receive Input 设置,Unreal中的源码如下:
void AActor::PreInitializeComponents()
{
if (AutoReceiveInput != EAutoReceiveInput::Disabled)
{
const int32 PlayerIndex = int32(AutoReceiveInput.GetValue()) - 1;
APlayerController* PC = UGameplayStatics::GetPlayerController(this, PlayerIndex);
if (PC)
{
EnableInput(PC);
}
else
{
GetWorld()->PersistentLevel->RegisterActorForAutoReceiveInput(this, PlayerIndex);
}
}
}
void AActor::EnableInput(APlayerController* PlayerController)
{
if (PlayerController)
{
// If it doesn't exist create it and bind delegates
if (!InputComponent)
{
InputComponent = NewObject<UInputComponent>(this);
InputComponent->RegisterComponent();
InputComponent->bBlockInput = bBlockInput;
InputComponent->Priority = InputPriority;
if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
{
UInputDelegateBinding::BindInputDelegates(GetClass(), InputComponent);
}
}
else
{
// Make sure we only have one instance of the InputComponent on the stack
PlayerController->PopInputComponent(InputComponent);
}
PlayerController->PushInputComponent(InputComponent);
}
}
以上代码就是Unreal Engine 4中的具体实现。
设置完成后,就可以在自己的实现类的void AActor::BeginPlay()中使用InputComponent绑定事件了,比如:
if (InputComponent != nullptr)
{
InputComponent->BindAction("Fire", IE_Pressed, this, &ABatteryActor::Fire);
}
对于Pawn
在Pawn的Blueprint中,通过 Pawn -> Auto Possess Player 中设置,Unreal中的源码如下:
void APawn::PreInitializeComponents()
{
Super::PreInitializeComponents();
if (Instigator == nullptr)
{
Instigator = this;
}
if (AutoPossessPlayer != EAutoReceiveInput::Disabled && GetNetMode() != NM_Client )
{
const int32 PlayerIndex = int32(AutoPossessPlayer.GetValue()) - 1;
APlayerController* PC = UGameplayStatics::GetPlayerController(this, PlayerIndex);
if (PC)
{
PC->Possess(this); // 此方法内会将 AController* APawn::Controller 设置成PC
}
else
{
GetWorld()->PersistentLevel->RegisterActorForAutoReceiveInput(this, PlayerIndex);
}
}
UpdateNavigationRelevance();
}
以上代码就是Unreal Engine 4中的具体实现。
设置完成后,就可以在void APawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)中使用InputComponent绑定事件了。
而SetupPlayerInputComponent方法是在如下方法中被调用的:
void APawn::PawnClientRestart()
{
Restart();
APlayerController* PC = Cast<APlayerController>(Controller);
if (PC && PC->IsLocalController())
{
// Handle camera possession
if (PC->bAutoManageActiveCameraTarget)
{
PC->AutoManageActiveCameraTarget(this);
}
// Set up player input component, if there isn't one already.
if (InputComponent == NULL)
{
InputComponent = CreatePlayerInputComponent();
if (InputComponent)
{
SetupPlayerInputComponent(InputComponent);
InputComponent->RegisterComponent();
if (UInputDelegateBinding::SupportsInputDelegate(GetClass()))
{
InputComponent->bBlockInput = bBlockInput;
UInputDelegateBinding::BindInputDelegates(GetClass(), InputComponent);
}
}
}
}
}