Player Controller – Get Controlled Pawn – Client delayed

As I am new to UE4 engine, I ran across a problem casting to players controlled pawn. At first, I was completely puzzled why a component reference variable I was using was not being set. Because this worked fine on server and not on a client, I was certain this was a replication issue (I am still sorting that logic out).

After many trials, I found that issue was not replication but that Event Begin Play was being fired on client before character object was accessible to its controller (client side). To figure this out, I did a quick test controller and linked its Event Begin Play to a character cast (getting self-controlled pawn); it failed every time. Next, I added a delay function and had cast re-fire every tick for up to 5 delta seconds and sure enough, after 1 failed attempt, it casted perfectly.

LogBlueprintUserMessages: Server: Event Begin Play: Received valid character cast after (0.0) delta seconds! LogBlueprintUserMessages: Client 1: Event Begin Play: Received valid character cast after (0.147438) delta seconds!

It likely makes sense that server fired event on client after server had spawned and linked that controller’s character with no regard to client’s pawn state. Is this a correct assumption?

Ultimately, my questions are:

  1. is this working as intended and I am just misusing it?

  2. If this is a “bad” place to modify controller pawns, where is best place?

I would like to set up multiplayer input controls and functions to be casted/executed on a player’s character without having to duplicate them on every character (movement, camera controls, etc.). I chose to try controller as it would remain same throughout but character may change. Given this sync concern, I am a bit lost.

Thanks!

Edit:

I have done some more testing. further I go down this rabbit hole more confused I get! I added some logic for controller to tell me via string print exactly which controller each message was referring too and exactly how many times it tried. I also set it to run two clients on a dedicated server in same instance and this is what it had to say:

*LogBlueprintUserMessages: Server: TestController1 Failed cast attempt 1.

LogBlueprintUserMessages: Server: TestController1 Event Begin Play: Received valid character cast after (0.0) delta seconds!

LogBlueprintUserMessages: Server: TestController2 Failed cast attempt 1.

LogBlueprintUserMessages: Server: TestController2 Event Begin Play: Received valid character cast after (0.0) delta seconds!

LogBlueprintUserMessages: Client 1: TestController3 Failed cast attempt 1.

LogBlueprintUserMessages: Client 1: TestController3 Event Begin Play: Received valid character cast after (0.283715) delta seconds!

LogBlueprintUserMessages: Client 2: TestController4 Failed cast attempt 1.

LogBlueprintUserMessages: Client 2: TestController4 Event Begin Play: Received valid character cast after (0.283715) delta seconds!*

I am very puzzled as to why TestController1 and TestController2 are printing out failed cast attempt and then a success attempt at 0.0 which would mean it never hit a cast failure?… facepalm. only thing I can figure is that this has to be some type of instantiation order in engine (i.e Controller → Pawn) that is causing desync; but that begs to question why server is innately looping cast but client does not.

I’m still interested in anyones input, even if not a solution.

It’s annoying in my opinion. I solve it that way:

Probably not best solution, but it works.

Yeah, with no breakout though I would be concerned about creating an infinite loop. I’m really curious about logic behind way it is working. Moreover, if it is supposed to work that way, if it is just an innate behavior of system, or if it is a bug in general.

Thanks for reply!

It’s not an infinite loop. After you enter reset, execution stops as far as I know.

But yeah, it’s a nuisance. That’s why I subscribed to question, maybe someone finds a better way / explanation for current situation :slight_smile:

By infinite I meant that if controller, for any reason, never receives a valid pawn attachment it would loop infinitely, or at least potential to run every tick for a very long time. This could be solved by putting an incremental check or time-out on IsNotValid Exec. And I agree, I’m very interested in an explanation. I hope that one of these C++ gurus know code well enough; I do not.

I moved this question to C++ section as this is likely where answer is.

Bumping for thoughts/solutions.

Still bumping - If this is a bug I would be happy to move it. If it is not, then I would like to know what proper procedure is. Thanks!

I’d like to know this as well.

Especially since relationship between player controller and player pawn is not some obscure unkown feature you have to deal with, but is basically used by everyone.

Bumping…

Perhaps I should move this to bug reports.

Hi Purecyn,

This is caused, as you suspect, by instantiation order. You were essentially casting to something that didn’t exist yet, so it failed until you put delay node in there. A safer way to handle this is to take advantage of Event Post Login in GameMode. This event fires after a player has successfully logged in and has been assigned a player controller (which it handily gives you as a node). From here, you can then cast to any functions in other Blueprints that you need to wait for clients to be logged in.

Take a look at GameMode BP in Multiplayer Shootout project, available in Learn tab of Launcher, for an excellent example of how this works.

Hope that helps!

this helped a lot!

I struggled with this one for days, until find this thread. I was weary of using a Event Tick so, created a Custom Event and used a SetTimerbyFunctionName BP Node.! Thank you.

A little bit more elegant