Hello, this is Youngho Lee
In this unit, we'll learn take pistol and release pistol actions
Unlike single play
we'll use actor replication
when character takes or releases pistol
on network, and how to sync the data between players
The first thing we'll study is taking pistol
To do this
you'll use owner setting, server RPC and NetMulticast RPC
And to sync the take pistol animation
we'll learn how to use property replication
Secondly, we'll learn release pistol
Similarly, we'll use RPC
and separate the logic that the server will process and
the one that the client will
Take pistol
First is take pistol
Let's see
We'll first learn Standalone
that is, single player, and then multiplayer
We'll divide it into these two situations
The one on the left is Standalone
single player
On Standalone, you'll get an input
for take pistol
then you'll set the owner
and will actually take the pistol
With the take pistol input
owner setting takes place
and lastly attaching
so that the pistol is attached to me
This is what we'll do on Standalone
single game situations
But in network
when there are server and client coexisting, take pistol can
have errors if it uses this flow
What might happen is the client took a pistol
but other clients
or the server might not be able to know
that this client took a pistol
This is Standalone
Then let's expand this
to multiplayer
network mode where many players can join
It's the diagram on the right
Client, similar
to Standalone, gets input
They get input first
and then with this input, they'll request
the server using server RPC to take a pistol
Different right?
On Standalone,
they just set owner and took the pistol themselves
but here, the client isn't taking the pistol themself
but requesting the server to do that
Then the server will receive the request from the client
and do owner setting
and after that's done
tell's them that they can take the pistol
so they will attach
the pistol to the hands of
the client which is done
by the client
Why? Because that's a visual aspect
This part, the server can't do
and the client must
So the server's role is
to get the input from the client
and to test range
and set owner
Owner setting must be done in the server
I've been telling you this
but if owner setting is done by clients
the server or other client can't know about that
so communication is impossible
Owner setting must be done by the server
so that the owner's
net connection object can communicate
The server receives request and sets owner
then to all clients
it will send take pistol request saying 'this person's going to take a pistol'
Then all clients will
get this message
and do the logic that makes that client take a pistol
The overall flow is like this
Then let's make this using codes and
Unreal Engine editor
First let's go to Visual Studio
On Visual Studio
until now, we used this NetActor for RPC
and property replication
but now we'll
learn about NetTPSCharacter multiplayer
So first, on Visual Studio
let's go to NetTPSCharacter
We'll go to the header file
Go to NetTPSCharacter header file
and on the very bottom
It says network related member here
Here, to separate
I'll add public
We're going to add the part that sends the take pistol message with a server RPC
UFUNCTION, and we needed to put server option for server RPC
Then take pistol must be performed
So we'll put reliable
void, ServerRPC, TakePistol
You can put an underscore between the serverRPC
and TakePistol or not, it doesn't really matter
You can do as you want
For the function name, we just need to say that
it's a server RPC function
Then when we build
on the generated header file
server RPC function implementation is added
And what we actually need to implement
is not the ServerRPC TakePistol
but ServerRPCTakePistol_Implementation
This is the one
So on NetTPSCharacter.cpp, ServerRPC TakePistol_Implementation
We need to put the function name like this
Then internally, ServerRPC TakePistol function is implemented
and in that function, this implementation
will be called
Like this, implementation is added
Then, with this ServerRPC TakePistol part
we need to move the take pistol parts
I'll move this function's placement first so that it can be close to
TakePistol function
I'll move it next to the TakePistol function
I'll put it under it here
so that it's easier to see
Here, this part down here
If we have a pistol or not
can be checked here
This doesn't need to be given to the server
That could waste packets
So under here, if one has a pistol
we return and not perform anything
and when one doesn't
this part down here is subject to checking
So it will be the part of taking a pistol
This part all moves to where?
To ServerRPC TakePistol
I'll cut this part
from TakePistol
and paste it here on ServerRPC TakePistol
Then it will be moved to
ServerRPC TakePistol Implementation
Then on TakePistol
This is a function that is called when input is received
It requests to the server when that happens
Like I explained with the diagram
now we're on request to server
so it has to request to the server saying
'I'm going to take a pistol'
This is ServerRPC TakePistol
So the request code here
will be ServerRPCTakePistol
If we directly call using Implementation
This isn't from client to server
but when it is the server, calling itself
it being the server itself
Server can call with its own function
But when this is a client
when processing an input from a client
it isn't the server itself so it can't call this function
If it's called
internally
if server RPC interally works
calling this function
then this function will be
internally called
so if we call it here directly
from the client
this can cause a problem, why?
Because this isn't the server
This is a client, so it can't call a server's function
It has to be using an RPC function to call
and this function being called inside the RPC
Now, the client has sent
a request to the server
We're here
Client requesting the server
This part just took place
Then the server must do the logic of
setting the owner and
sending message to all clients
Then take pistol
the attach part
must be done in the client
The server only requests to attach
Right?
Great
Then let's first build
and see how it turns out
We can easily guess what that would be
Input comes in
Then it requests to the server
It'll say 'I want to take a pistol'
Then the server will call this function internally
and the take pistol will take place
Then let's think about the case where there are two clients
Let's say one's here
and another one's here
Then
This client is
in the server
We'll call this one C1
and this one C2
This one is in the server
Here, let's say that C2
requests ServerRPCPistol
Right, then this screen
where these two are in, no matter the server or client
will show both of them
When in this situation
ServerRPC is requested
For C1, taking pistol code
will be performed
So it will take a pistol
But for C2
this thing is perfromed in the server
but it hasn't sent the request
to other clients yet
so this guy, even though
this C2 is going to take the pistol can it take it or no?
It can't
The re-request hasn't come yet
The server will already have
performed the things down here
so it will take the pistol
But the client, even though
it requested to the server
hasn't received the request from the server
telling it to take a pistol
so it can't take the pistol
So when we run it
the character in the server will take a pistol
but will client's screen show it taking the pistol?
It won't
Let's check that
Let's run two of these
Great
First, look at the server screen
To perform both of them
I'll check on New Editor Window
Not Selected Viewport
Let's do New Editor Window
Then, on the window
it says server
This is the server window
and let me open a client window
next to it
Let me do that
The one on the left is the server
and the right is the client
Let me take the pistol from the server screen
Then to the client, it should show the server character taking the pistol
but as I told you
client doesn't receive any RPC
so the server character taking a pistol
will show on the client's screen or no?
It won't
On the other hand on the server's screen
you can see it
Right
But the client
can't see anything
The server shows taking the pistol
but on the client window on the right
it doesn't show the server character taking anything
Why? On the server
the take pistol logic was performed
but a request to the client to take a pistol
was not sent
so this problem occurs
So now let's solve that
For that, for every character to take pistols
we'll use a
NetMulticast RPC
Go to NetTPSCharacter's header file
and under server RPC
we'll put NetMulticastRPC
This time, instead of server, we'll have NetMulticast
and then void Multicast
Then MulticastRPC_TakePistol
And here, const a actor pistol actor
I'll put that here
Why? This part needs to tell the clients
what pistol to take
so we're going to have a parameter here
We'll add implementation under the server RPC
Under server RPC, NetMulticastRPC TakePistol is implemented
There's also _implementation as well
for the same reason
Great
Then the server RPC calls this MulticastRPC
and MulticastRPC
needs taking pistol part
As you see in the screen
the taking pistol part
isn't here but in the server
So like in this diagram
after the owner setting part
and the taking pistol part
actually attaching the pistol to the actor
and such must be done by the clients with Multicast
We'll move those here
So on MulticastRPC, we'll add
attach pistol, this part
We need this part not here, but under here
We'll do that
Attach pistol
Above here, owner setting
and data setting will be done where?
On the server
Under here, MulticastRPC TakePistol
and we'll put what's to be attached
That will be Pistol actor
Put the pistol to be attached
and the message will be sent to clients
It looks like simply calling a function
but communication happens internally
So the server sends to clients
MulticastRPC with the message telling
to take pistol, TakePistol is internally sent
Then the function is called in the client
Let's build
This is an RPC function
so it's the server and a client
It's both
I did all this in the server and did Multicast
It's the server and a client at the same time
but they are logically separate
Physically the server and client is together
but logically, C1 and C2 are separate
So now, C2 has RPC requested
to the server saying 'I want to take a pistol'
Then the server
does all this
and sends a Multicast
How? It sends this
to all clients
Although this is physically here together
but this is ultimately like this logically
So from server to client
message is sent with Multicast
Got it?
Then the client will perform take pistol
Let's build
And we'll run
but let's think about what problem might happen
when we run it
Play
Server open, and client as well
I'll take the pistol from the server screen
Then what will happen
It suddenly stops
and the editor shuts off
Why? Analyzing the error message
Here, it says NetTPS Crash Repoter
Don't skip this
It shows what errors happened
Here, it says exception error
Access violation, reading access, and then null
A null subject
There's no value in the pointer
I entered that place so an error occured
Look
There was an error in show crosshair of mainUI
and on the ninth line of mainUI cpp
this occured
Let's go to ninth of mainUI
Go to ninth line of mainUI cpp
Let's see what it is
show cross needs to show this but
there are no image crosshair
Then we'll need to move to where it called these show crosshair
That being nonexistent
There was no problem here
Where it called this
That's AttachPistol
It's this part
It was going to receive Multicast, attach pistol and when doing that
attach all these onto component
and do this on the mainUI and show crosshair
But looking here, mainUI
is null so this part caused the error
I'll put a breakpoint here
Then we'll perform it on debug mode
When working with Unreal
performing debug mode on Visual Studio
is pretty useful on finding runtime errors
I'll play it again
and also a client window
I'll go forward and take with F, it says this
Here, the error happened
here on the Net Nulticast TakePistol
On Net Nulticast TakePistol
Right here
This part was where the error happened
So the mainUI
there's no memory here
which means it's null here
so we need a code here
Then why does this problem happen?
Why is there nothing in here?
That's because of these
Let me use this picture to explain
So here
PC means player controller
and this one also means player controller
NetMulticast will be sent
It will call
I said that NetMulticast is Actor Replication
This literally means actor
It means that when the same object is in a world they can communicate
with each other
It means communicating using actor
Actor replication
Then looking at the mainUI
what were the conditions of this being made
Let's take a look at the code
It says InitUIWidget
From here
Do not process if player is not controlling
So if there's no player mainUI is not made
Right? Do not process if player is not controlling
Going back to the screen
We sent a NetMulticast
But the mainUI must have a player controller on that phone
Only then the code logic runs
We're saying that there are these two clients
Both will show on the screen
The top is
what will show on the client's screen
and the second like this
The one below is the server
From the server point of view, how would it look
From the server, since the server has all player control
Right? It has all player control
so this problem will not happen there
But from the client point of view
Do I have player controller?
I have mine but what about the other one's?
No, it only has it's own player control
So the other one
Here, this SimulatedProxy
character, the other one
Not mine
Does this one have player controller?
On the client window, no
Do you get it?
I have player control over my character
but for the other one
is there player controller on the client's window? No
Only the server has all player control
the client only has its own player controller
Then for this character which is a SimulatedProxy
can there be a mainUI?
No because there is no player controller
but from our code logic
when doing MulticastRPC
It says attach pistol
Up to here, it doesn't matter
but here, it wants to call mainUI but
mainUI is only made when there is player controller
Right, but the counterpart
Can there be a mainUI or no?
No
Why? Because there's no player controller
So this attach pistol part
can have a mainUI only when?
When I'm controlling
that is, when there is a player controller
When there is player controller
Because only then, mainUI can be made
Using network terms
autonomous
Only when it is autonomous proxy
it is possible
Do you get it?
So we need to test calling this mainUI
What that is is
if autonomous proxy, when I'm controlling
This ultimately means is locally controlled
Internally, when i'm the one locally controlling
That's what if is for
And when there is mainUI
we'll call this
Let's build
and play
Server window
and a client window
Let's see how it goes
From the server, it takes a pistol
On the client, it doesn't
but let's see here
Going closer
on the client window
you can see that the server character has the pistol in its hand
Here, the server animation shows the animation too
but the client just shows
the pistol attached and the animation isn't synced
So attach pistol is working properly
but the animation isn't being synced
Let's solve that
Let's see how we sync animation
On netpscharacter.cpp, bHasPistol
it changes the pistol posession
and puts this value to sync animation
But look here
ServerRPC function must be performed only where?
Only in the server
It's a code that's only performed in the server
So it was true in server
There's no way for the client to receive that this value is true
So this value needs to by synced
using property replication
Let's go to bHasPistol implementation
On netpscharacter.h bHasPistol is declared
We'll add this option so that this part is
synced on network
u property, replicated
We did this when we were doing property replication
Then you'll know that
to do this, the cpp file needs
a function that starts with get lifetime
void ANetTPSCharacter is already implemented
GetLifetimeReplicatedProps function
This function needs to be definedd
Super, GetLifetimeReplicatedProps
Call this and you need to do what?
Register. Do
REPLIFETIME
and show the source. What from ANetTPSCharacter?
Sync bHasPistol
And this one has a red line, so on the very top
we need to add include
We have to put include the unreal network.h under net folder
Let's build
and see
Just now, it was attached but the animation didn't show
but now, both on the server and the client
Look at the server screen
The animation is showing
and on the client screen as well
the animation is playing properly
Great
Moving with the pistol
the animation all works properly
This was on take pistol
Release pistol
Next is release pistol
For release pistol, similar to take pistol
we will use RPC to
sync on network
As I mentioned, take pistol
follows this flow
On release pistol as well
instead of TakePistol input
a ReleasePistol input will come in
and with the input it will request to server with server RPC
Then the server will work on the owner setting
and tell the client to put the pistol down
by sending another request
Then let's make that following that flow
On Visual Studio
go to NetTPSCharacter header file
On the very bottom, this was take pistol
and now we're going to add release pistol down here
UFUNCTION, we'll make the same thing
UFUNCTION, void ServerRPC_ and this time
ReleasePistol
It's the same as take pistol
On release pistol as well, I'll add implementation
I'll cut ServerRPC ReleasePistol
and put it under the ReleasePistol function
just to make it easier to work with
If on this ReleasePistol, one doesn't have a pistol attached
or reloading it, the logic is not performed
and this is done by the client
The server only changes data
Where is that? It's right here
When one has a pistol
Where should we put this
We'll cut this and paste it here on ServerRPC
And on ReleasePistol
the request will be ServerRPC ReleasePistol
Do you get the flow?
Here, client
ReleasePistol is client
On the client side
only the input is here
Only the input
And then after that, from here to where?
To the server
It requests using server RPC
It sends a ReleasePistol request
Then the server receives that
and does this part
This is not done by the client but where?
On the server, this logic
And the action of releasing the pisstol
DetachPistol is done where?
On the client side
So the server again
sends a message to the client
That's how it goes
So we implemented this on the server
And when the server does this
This DetachPistol is not done in the server
but by the client
So to make that happen
I'll add a code that sends NetMulticastRPC to clients
Let's make a funciton
Go to NetTPSCharacter header file and on the bottom
copy this function we made on take pistol
and paste it
Then instead of TakePistol we'll make it
ReleasePistol
Then on the parameter, the code that
detaches the pistol from the hand will perfrom
We declared one function
and now let's implement NetMulticastRPC
On the cpp file, we'll add that function's implementation
then there's ServerRPC and NetMulticastRPC
DetachPistol goes where?
It goes to MulticastRPC
and then MulticastRPC call is done by ServerRPC
Then there will be internal communication as I told you
Then the client
requested to the server using server RPC
After the server has done its job
it will use NetMulticast to request back to the clients
and make them perfrom this code
Do you get it?
Great
Then we need to put the parameter value for NetMulticastRPC
Which one? ownedPistol
Then the owned pistol is sent to network
and it will receive this and the pistol will be detached
The server will send that
and reset all owner settings
Great
Again, if we play this it will crash
Why?
Because again on DetachPistol, it calls ShowCrosshair
On mainUI, it will be there for the client itself
but it also shows to other characters' screens
That character has mainUI or no?
It hasn't, why? Because it is made only under the condition that player controller exists
So here, we make it not happen when there's no mainUI
if IsLocallyControlled
and only when there's a mainUI character
we need to change this part so that it will be performed only in that case
This is the same as AttachPistol
Let's build
Then let's run the server
and a client
Take a pistol, it works, and let me release it with Z
Then there's another error, Null Point Exception
There's an error on the character's 227th line of ReleasePistol
What is it?
I didn't put pistolActor
put just copy pasted DetachPistol
so it says ownedPistol
We'll put pistolActor here
Why? Because if it says ownedPistol
this one needs to release the one it got from the server
so it might try to release the ownedPistol which it doesn't even posess
which might cause an error
So we need to make it detach the data it got from here
Only then this value will be processed properly
Let's build again
and play with a client added
F, take pistol
Z, release
You can see the pistol falls to the ground
Again, F, maybe release it here
I released it here on a hill
Here's the pistol
From the client side, let's see if the pistol is indeed there
Aha, it's here
Let me try the same thing on the client side
Put it down here
It's being synced well
But there's something I want to show you
Let's see the pistol placement on the client's screen and the server screen
On the client's screen, the one on the left
It shows that the pistol is here
And let's see the right screen
On the server screen, where is the pistol?
It's at a different spot
So in the server, the pistol is here
but it's somewhere different for the client
This is an error
So even when the server wants to take the pistol
when performing that logic
it's here for the client so even if it tries to take it
if it's somewhere random
then it can't take it
because on the server, it says that it's here
The location data isn't being synced
Then what should we do
We can activate Actor Replication that we learned
There's this BP Pistol
There's BP Pistol on NetTPS Blueprint
Open this
and let me search Replicate on BP Pistol's detail window
Search Replicate
and you'll see Replicate Movement
and Replicate
These aren't activated
so it is not being synced
So check on Replicate option
and Replicate Movement as well
and then the values on movements, within Unreal Engine
will be synced
If you say that you'll replicate, network sync
on Blueprint, it automatically does that
'Then on C++, not only that but
property value needs to be synced
and Get Lifetime Replicated, all these need to be done too'
Right
These parts too
But on Blueprint, that part ins't needed
It's simpler on Blueprint
But when making these network codes and logic
it's more efficient to work on C++
It helps with management too
but Blueprint has an easier structure
Of course, when working on RPC and such
if you keep going back and forth with Blueprint
you can get very confused with the logic
So usually, C++ does all of the network
But here, the pistol ins't being synced
so I just used these two Replicate options in the detail window
to sync this pistol actor
Let's go back and play
Go, and Z, released
Then for the server, it's on the ground
From the client as well
it's on the ground
F, let's drop it somewhere else
and the two on network
are being synced
The same location
You can test this further
and Blueprint can very simply
sync movement
and location value
by activating Replicate options
on network
That will be it
This was release pistol
Let's summarize what we've learned in this unit
Take pistol RPC communication
User only performs input and the logic is performed in the server using server RPC
NetMulticast is used together to perform animation and visualization on all clients
UI It must work only on clients Needs a logic to separate UI
Animation Uses property replication
Release pistol RPC communication
Requests to server to release pistol using server RPC Uses NetMulticast RPC to send result to all clients
The End