How can I replicate PlayerStart in C++ without adding a PlayerStart to my level?

That probably seems like an odd, somewhat vaguely directed question, so let me give some context. Most of the projects I work on don’t require a PlayerStart (or shouldn’t), as there’s no in-game object that the user is directly controlling. But I’ve noticed if you don’t have a PlayerStart in your scene, some odd behavior happens, usually in the form of missing functionality, for example:

  • GetHitResultUnderCursor() doesn’t
    return anything (although, as Doug
    helpfully pointed out,
    GetHitResultUnderCursor is
    deprecated)
  • It seems like mouse over events don’t fire either, e.g. if you add a function to an actor’s OnBeginCursorOver, you won’t see the results unless you have a PlayerStart in the level

So what exactly does PlayerStart do “under the hood”, and is there a way to replicate whatever it provides to the level, or otherwise enable said provided functionality without placing a PlayerStart in the level? I know this is a super specific case, and to be honest, having a PlayerStart in my level isn’t totally egregious, but I’d like to learn as much as possible, just for myself if nothing else. Cheers!

I don’t use PlayerStarts in my game, and I don’t have these problems. You aren’t actually required to have a PlayerStart, but you’ll need to override certain methods in your GameMode subclass to get your desired custom behavior. If you haven’t done that, I can show you what to override.

If you’re already done that, let’s try to find something obviously wrong.

If you’re using UE4’s game framework (and I’m pretty sure you are), then the PlayerController needs to be possessing some kind of pawn. Do you know what class the PlayerController is possessing? Is it a spectator or a regular pawn? Has the possession happened correctly, or is some state messed up?

Aha! No, I haven’t messed with the GameMode, so any hints there would be greatly appreciated, many thanks!

Ok. It depends on what you’re doing and what behavior you want to implement. The easiest way is to override FindPlayerStart_Implementation on AGameMode. Note that this method won’t appear in the header file because it’s declared as a BlueprintNativeEvent. However, you should still be able to override it in your own GameMode subclass. It’s a bit odd, because you are returning any AActor* whose transform is used to spawn the new pawn in for your incoming PlayerController. You’d expect it to return an FTransform, but you return any kind of AActor* instead.

You could also override ChoosePlayerStart_Implementation (yeah, the names are pretty confusing) instead, is called from within the default implementation of FindPlayerStart_Implementation (oh man these names) if the PlayerController isn’t already tagged to use a specific start spot. FindPlayerStart_Implementation lets you preempt more the existing behavior, ChoosePlayerStart_Implementation lets you only override the part where it falls back to looking through the list of APlayerStart actors in the current level.

APlayerStart is just a marker for AGameMode, the real spawning code is inside AGameMode and it using APlayerStart to know where to spawn. It can be disabled or overriden as cancel explained :stuck_out_tongue: