Network connection structure and communication processing structure
Let’s start by learning about the network structure in the Unreal Engine
First, let’s discuss the network connection structure
The network connection structure can be represented in two main forms
The first form is the local multiplayer setup
where multiple inputs are connected to a single PC, as shown in the diagram above
When you go to places like arcades, there are arcade game machines, right?
Or console gaming systems
In such setups, multiple users can play together using keyboards, joysticks, or other input controllers
connected to a single gaming console or arcade machine
However, there are times when you want to play games online
with other users
Commonly seen in genres like battle royale or MMORPGs
For example, games like StarCraft, League of Legends, and Lineage
fall into this category
In Unreal Engine, as shown in the diagram below
it provides a server-client model for online game modes
It represents a service structure
where multiple clients are connected to a single server
Let’s now explore different types of game servers
In online gaming, the type of server varies
depending on the service being provided
For example, there are games like LoL or StarCraft
where a small number of players enjoy the game together
There are also games like Lost Ark or Lineage
where a large number of players play together
These can be categorized into listen servers and dedicated servers
based on the types of server used
A dedicated server
as shown in the diagram above is
a structure where multiple users connect to a single server
to synchronize data for gameplay, ensuring consistency
This is a structure commonly used for online game servers as we commonly know them
This dedicated server structure involves
clients connecting to a server that is installed remotely
Since it only handles server-side logic
there’s no burden of rendering anything on the screen
Therefore, it can allocate PC resources
entirely to logic and communication processing
ensuring reliable data management
It’s a structure where it’s impossible for another client
to manipulate data in the middle
However, there are drawbacks, such as increased hosting costs
due to the need for remote installation
Also, downloading and installing the Unreal Engine source code for production can be time-consuming
often taking more than 10 hours
which can be inconvenient during learning
Next, a listen server can be seen in games
like LoL or StarCraft’s Battlenet structure
As you can see in the diagram
there’s a central server coexisting with clients
In a listen server setup
both the server and clients physically coexist on the same PC
And since server logic and rendering are handled together
it can impose speed constraints
Also, because the server doubles as a client
there’s a drawback where that client can manipulate data
which can lead to reduced data reliability
However, it offers the advantage of no hosting costs
allowing multiple users to play together
on a local network
Let’s now explore the communication processing structure
in the Unreal Engine’s network architecture
There are various methods available
beyond automatic synchronization of data
for characters in Unreal Engine
These methods are collectively referred to as Actor Replication
Alright, let’s first discuss these methods
Clients simply send their intentions to the server in this method
The client’s intention refers to the actions based on user inputs they receive
It includes actions such as pressing buttons, clicking with the mouse
or other types of input generated by the user
Then, the logic here refers to creating the flow of the game
rather than handling the input itself
Creating the game’s flow is
typically not done on the client side
Because if the client handles this
all client’s data needs to be synchronized
which becomes challenging
if each client manages it independently
Therefore, clients typically do not handle this themselves
Instead, they request the server to process their intentions or logic
like saying, “I want to do this; please handle this logic”
In this case, clients send requests to the server in the form of RPCs
The server then receives these requests
and executes the game logic based on them
understanding what the client wants to achieve
After executing the game logic
the server needs to send the resulting data
back to the clients
There are broadly two main methods to send this data to the clients
One method is using NetMulticast, and the other is using Client functions
Users receive that data
and it’s replicated as discussed - essentially duplicated
Users don’t generate data themselves; they request it from the server
Once the server creates the data
it replicates it to the clients
This replication structure has two main methods
one is using RPC
and the other is using Property Replication
In addition to simple data replication
clients can also perform other actions
besides that
Users typically can’t handle game logic themselves
but there are certain cases
where clients need to handle
specific aspects
We shoot a gun
“bang”
Then the effect would appear like this
The actual visual processing like this
can’t be handled by the server
The server simply receives inputs like
“I pulled the trigger”
Then the server will use that input
to send back the result, like who got shot
Then users receive that result
and handle the visual processing accordingly
Do you understand?
Rendering something on the screen, in this form
is something that the server can’t do
it must be done entirely on the client side
Effects are a prime example of visual processing
that’s solely handled on the user’s side, not on the server
Effects such as fire effects, flowing water, or splintering shards when hit
are handled by the client
not the server
The server informs the client where impacts occur
and then the client displays effects accordingly
Another example is user interfaces (UI) that are also managed by the client
These UI elements can’t be managed or processed by the server
The server only sends data like “What is your current HP?”
Right?
The client is responsible for receiving this data
and displaying it on the screen
We’ve covered the communication processing structure to this point
Let’s explore the network game framework
this time
The structure of a network game framework
isn’t fundamentally different
but typically includes classes and components tailored for multiplayer functionality
unlike the single-client focus we’re used to
There are classes that make the game framework function
and depending on how these classes operate
we can view the network structures differently
On the client side, you didn't really need to use Game Mode, Game State, Player State
and similar components much
Let's start by
discussing the lifecycle of these classes
like Game State, Game Mode, and Player State
and explain
how they are created
and operate
When you press the play button
or run the editor
the game starts running
When the game starts
Unreal Engine needs to create a world
This world is the virtual environment where you play and explore
So, a world gets created
But for that world to be created, the game needs to be in play mode, right?
So
when you first press
the play button
a Game Instance object
is created
The Game Instance can be seen as the manager
that oversees the entire game
It can be viewed as the entity that manages the start and end of the game altogether
In terms of its lifecycle
it begins by being instantiated
as the Game Instance when the game starts
So, now that the game has started
the Game Instance's role includes
creating the necessary virtual world
or world inside it
Remember "Get World" to retrieve the world?
The Game Instance will proceed to create a world
Once the virtual space is created
necessary resources will be loaded into this space
This includes creating all the Actors
that are needed and even spawning players
within this environment
During this process, as the Game Instance creates the world
it also loads and instantiates the Game Mode class
to determine what kind of data and rules will govern this world
This creates an instance of the Game Mode class
So, the Game Mode is created to
define the fundamental rules of the game, as listed here
So, we ran the game, created the game itself
and even set up a virtual space
So, within this game, who are the participants
and according to which rules does the game end?
The manager responsible for these overall aspects
can be considered the game mode
This game mode even handles the login process
The player logs in
Then, the game mode also controls
whether or not to allow the player to participate in the game
So, if I don't want to let this user participate
the game mode will send an error message saying, "You can't join"
Then, the user cannot enter the room
When the user requests to enter the room and logs in
the game mode gives the okay
allowing the user to join
From that moment, the user participates in the game
The participating client is then spawned
and will enter the game
Then, what this participant becomes is
the PlayerController
So, this PlayerController represents you or me in the actual reality
acting as the intermediary between the user and the game
The PlayerController acts as an intermediary
representing actual users like you and me
and to move around and perform actions in the virtual space
this typically requires a Pawn
That's precisely what a Pawn is
The PlayerController possesses
the Pawn
Possess might sound different but typically 'Pawn' is a term used in chess
What does it mean to have a piece here in chess?
We have a pawn like this, and we want to move it
We can capture it and control it
We'll be able to control it
forwards and backwards
So, what do we call
the act of the user capturing this pawn?
We call it 'possessing' the pawn
So, what about if there are multiple Pawns? What does the PlayerController do?
You can switch
possession of these Pawns
allowing continuous control
Managing the overall rules of the game is actually quite high-risk
when you think about it
It's because they wield considerable authority
What kind of authority?
It's a structure that allows them to end the game and even determine the outcome
Who? It's the game mode itself
Now, in the context of networked games, whether it's a dedicated server or a listen server
there's always a server
and there are clients
Even though clients are connected like this
physically
they're separate entities logically
This is how it's set up
So, the server and clients are
communicating bidirectionally like this
and each of them has their own game mode
If each client has its own game mode
what might happen?
They might each independently determine the game's outcome
They could manipulate the outcome, so that wouldn't work
They could also kick players out at will
This would lead to excessive abuse of authority
So, giving such authority to all clients would obviously not be feasible
Only the server can have the game mode
Clients follow rules
determined by the game mode
Where does the game mode exist?
It exists only on the server It's dependent on and tied to the server
Clients cannot
directly access the game mode
So, you bring the game mode
but if the game mode exists
it's on the server
And within the game mode class, you carry out various tasks
This structure operates exclusively on the server
That could lead to issues like this
We start the game, right?
We start, then we'll do things like end the game and stuff like that
After these parts
they operate as teams
This one also exists like this, so it's a team
So, if I want to know about information
regarding teams performing scores or missions
Meaning, I want to know how the overall state of the game progresses
If the server manages all the rules
the client simply receives and processes the corresponding actions
Since only the server knows the current state of the game
it would be challenging for clients
to handle those aspects
So, an instance called GameState is created
This game instance, as described here
monitors the overall state of the game
Here, if the game needs to be played
for 10 minutes
you would need to know how much time has passed in the current game session
Since you can't directly get these things from the game mode, how do you do it?
You do it through GameState
So, next, each client may encounter these kinds of inconveniences
Okay, you understand about each team in the game's state
but what about their HP values?
Or what about when they send me a private message in chat
or how many kills they currently have?
How can we handle these kinds of things?
GameState clearly refers to the overall state of the game, not the individual states of each player
So, we put PlayerState separately
So, we store information here to control
and manage each player's state separately
You understand that the game mode exists only on the server
So, the game state
should exist on all clients
so that they can know each team's score
current status, how much time has passed in the game
and so on
So, each client in the game world
can have access to the game state
They would each have one
The server needs to know the game state
to handle things like how much time has passed
and whether to end the game
The game mode can use this information to make decisions
So, the game state exists on both the server and the clients
I mentioned that the game mode exists only on the server
However, the game state exists simultaneously on both the server and the clients
What about the player state?
The player state should contain information for all clients
So, they will all be visible on this screen
Here, this is labeled as client
but let's call this C1, and we'll call this one C2 and this one C3
In the C1 screen, C2 and C3 will be visible together, right?
To display their HP and kill counts
we need to know their information
In other words
the player state will naturally be held by all clients
Alright, let's look at the PlayerController
It is stated that in the Pawn's possession
the Possess function plays a role in conveying the user's intent
according to their intentions
In other words, as I mentioned, when there is a specific character
the PlayerController is what allows the user to Possess the character
and convey their intentions
When the game starts, it was mentioned that a game instance is created
and a world is created within it
A virtual space, the world, is created
Then, within this
we create the necessary game mode and various other things
Actors will all be placed within this
Actors are placed inside the world space
Anything outside this world space is not considered an Actor
In this context, the game instance is not considered an Actor
So, it would be like this
If there's an entity visible on this screen that represents the player
what do we call this entity?
We call it Pawn
We call that entity
a Pawn
But these Pawns, they'll be placed inside here
and let's consider that there are multiple Pawns
So, do they all receive control from every user, or not?
They can receive control from just one use
What did we call the entity that can control this Pawn?
It's called the PlayerController, which acts as the user's intermediary
We have this PlayerController
This PlayerController possesses the Pawn to control it
Alright, let's look at user C1
This is me, user C1
Over there, we have user C2
C2
Let's just focus on these two for now
Then, how many PlayerControllers are there on this C1 screen?
If there are multiple PlayerControllers, who will be in control?
It's quite ambiguous. In my case, PlayerController naturally corresponds to me
on a one-to-one basis
By "me," I mean either you or me, referring to actual people
The PlayerController serves as the entity
that connects you and me to this virtual space
So
when I want to exert influence on this Pawn
through inputs or other means
the entity that represents me is the PlayerController
and there's only one of it
In the client context
there is only one PlayerController
There is only one, without exception
Then, it is the one
that is remote, right?
That PlayerController over there will control it
I shouldn't have control over what belongs to others
In the remote context, this would be C2, then
C2 user would be there, and C1 user would be here
Right here
there will only be a PlayerController for C2 user
This PlayerController is what represents you
It's what mediates between you and it
This PlayerController is what connects them
There's only one here and one over there as well
It's the server, and then there are clients
Alright, each client has one PlayerController like this
Usually, they have it indexed as zero
Then how about from the server's perspective?
It should be able to communicate with them too, right?
It should be able to communicate with both of them
Clients only need to handle their own, right?
So, I have a PlayerController here
If I want to control it and send inputs like this and that
based on our communication structure as we discussed
when I send inputs, the server receives the corresponding logic
processes it, and responds accordingly
So, to communicate between them
we need a structure that involves the PlayerController
corresponding to each of them
That way each one can control the other
A structure is created for them to communicate with each other
Here, a PlayerController
corresponding to this one is also created
So, if we call this one P0 here, then let's arbitrarily label this one as P1
and we'll call this one P2
But they represent the same entity; only the names are different
So, when this one makes a request to the server
it processes it accordingly
involving the relevant subsystems
The dedicated handlers for each client are precisely the PlayerControllers
and the server also has corresponding content for each of them
We can label
what game framework classes exist together
between the server and clients
So, what exists only on the server side is the game mode
This game mode defines the rules of the game
so it's very important, and it resides on the server
You can just think of it as the server itself
Then, what must exist both on the server and all clients are the GameState
followed by PlayerState, and Pawns
How about PlayerController?
Clients have their own PlayerController, right? What about the server?
Everyone has it
so what exists only on the server and client
is called PlayerController
All clients have the same thing like this
and PlayerController isn't something that all controllers have
Each one has their own, that's how it's differentiated
Next, HUD and UMG exist only on the client side
On the local client, do they exist on the server? They don't
Player Controller and Connection
Okay, let's now delve into PlayerController
and Connection
I've also talked about the communication structure before
I mentioned that this structure involves clients making requests to the server
the server executing the corresponding logic
and then sending the results back to the clients
PlayerController plays a very important role
PlayerController doesn't exist
on all clients and servers
The server has all the PlayerControllers
The server has all PlayerControllers 1, 2, and 3
The client only has its own PlayerController
They only have their own respective ones
So, when they communicate with each other
on the server side
if they make a call to all clients
Where do you place the ARS phone call?
When I make a call
someone at the reception will answer
Then someone specific will be designated to answer the call
That someone is the dedicated staff member directly assigned to connect with me
Here, PlayerController corresponds to that role
So, we have PlayerController on the client side
and PlayerController on the server side
both representing the same entity in this context
The server has the corresponding PlayerController for this
and it also has PlayerControllers corresponding to all clients
while each client only has its own
This is the primary purpose of PlayerController
in this network context
Then what is a connection?
It directly pertains to communicating between the client and the server
using PlayerController
This PlayerController
internally holds an object
called UNetConnection
As the name suggests
it handles tasks related to network connections
The UNetConnection
handles tasks related to TCP or UDP communication
ensuring connections are established and facilitating the exchange of communication data between them
It manages basic setup values necessary
for sending and receiving communication data
That's how it works
Users exist
and when there's a server, they connect to communicate with each other
Internally, think of it like socket communication
Once connected
a channel is established between them to exchange data
Like this, a channel is created
It's created like this
We commonly refer to this channel as a stream
We call it a stream
Through this stream or channel
data flows back and forth between them
Creating and managing this flow of data, sending and receiving
is handled by the UNetDriver below
So, handling the sending and receiving of data is done by UNetDriver
while tasks like connecting clients and servers are handled by
its underlying operations managed by UNetConnection
When the connection is established
the channel is created, and within this stream
data is exchanged back and forth
much like saying 'hello' to each other
When they say "hello" to each other like this
they respond with "yes, hello"
By doing so
they establish these as communication protocols
We commonly refer to this as a protocol
We call it a protocol
This protocol is a communication agreement
We call the rules for how we talk like this, 'I'll say this'
'Oh, then I'll take it like this'
making up the rules for conversation, a protocol
So, UNetDriver creates the data processing flow
based on this protocol
Then, what do we call these flowing data units?
We call them packets
It's called a packet
You can think of a packet as a unit of bundled data
So, when bundled like this
how does UNetDriver handle these packets?
It groups them further into sets of eight packets
It bundles the packets one more time
When you handle data, you're dealing with bits, right?
Bytes exist, and then there's Short, and ShortInt
Then there are Int32, and so on, including 64-bit variants
Those are divided into different sizes
They increase gradually from the smallest
Characters and similar types like char exist
Creating data units
progressively from smaller to larger sizes
Similarly, in network communication
data isn't just sent as individual minimal units
but often in bundled units
So, byte data is bundled into packets, forming several units of bundled data
These packets are also grouped into several units of bundles
We call those bunch
In English, we say 'bunch'
You can consider this 'bunch' as a unit of bundled data
This 'bunch' data can be divided into several types
to facilitate processing
When sending data from the client
UNetDriver bundles it into bunches
If the server receives data
and applies it without filtering
problems like unchecked data
could arise
What problems?
It's mainly an issue of processing speed
They would have to analyze each one individually
That's why in Unreal Engine
they typically categorize this data into three specific types for handling
They call this channels
They call it channels
namely control channels and then voice channels
They categorize it as actor channels
to enable voice communication
Taking actor channels means
categorizing data
internally for tasks
like controlling data or sending voice data
and handling things like character movement
Doing classification work and decide
"So, you're dealing with Actor data"
"and you're using the Actor channel to flow through the processing"
so, you push only that Actor channel here to proceed with the work
Alright, that's how it goes
This is configured in the PlayerController
In this case, these are all class names
After that, it's structured with UNetDriver followed by UNetConnection
Alright, let's talk about the Owner that has the connection this time
Okay, as you can see in the picture
both the client and the server coexist together like this on the screen
But I mentioned that
we can communicate using PlayerController
If you look here, you can see the PlayerController
The PlayerController internally uses UNetConnection
for data communication
So, it means that we can communicate through PlayerController
In other words, when a game instance is created in the world
and the world is created, these characters are inside it
With this setup
we aim to establish communication between the server and the clients
We're trying to establish communication between the server and clients like this
and PlayerController is necessary for this
Because PlayerController exists on both the server and clients
they can communicate using it
Currently, as seen in the diagram
communication is structured using PlayerController
Alright, so in this case
the PlayerController here directly possesses a Pawn
Then, how is this Pawn structured internally?
It's structured so that they communicate with each other
using the UNetConnection object within the PlayerController
So, the idea is that they communicate
through the PlayerController that owns themselves
Then, it happens automatically
Well, then, there could be issues like this
Let's say we have a gun here
The user grabs and moves the gun like this
So, what happens next?
The gun
should also appear to be moved in this direction
on other clients' screens
To ensure synchronization, the server needs to receive data
indicating that the gun has been moved
and then inform others accordingly
However, there can be a problem here What problem?
Someone owns the Playercontroller
They directly possesses a Pawn
However, in the case of this gun
the PlayerController doesn't directly possess it
Right now, it's not being possessed
In chess, "possess" means you can only capture one piece at a time
We're grabbing and moving this one piece
We can't grab this gun
Right now, I'm grabbing and moving just this one PlayerController Pawn
in this structure
But suddenly grabbing and moving any other Actor here
wouldn't work
So, furthermore
because it's not a Pawn
the PlayerController also can't possess it
It's just like a regular terrain feature, similar to a chessboard piece
The PlayerController cannot possess it
Possessing is only possible for characters of the Pawn type, such as character classes
Only this object can move
That means it cannot do it, for regular Actors
So, in this case
how can we ensure that
when it moves like this
it synchronizes identically on other clients?
That's where the concept of ownership comes into play
Alright, if you set the Owner
between this Actor and this Pawn
what happens?
Through this Owner, you can directly communicate
with the server contents from the right
Alright, you've set the Owner to be the Pawn
So, because this Pawn is possessed by the PlayerController
it creates a structure where they can communicate with each other
If this doesn't exist, what happens if the Owner isn't set?
The Actor wouldn't be able to communicate
So, it can be done through the Owner
But what's the issue?
If the Owner is here instead of there
did you set the Owner on the client?
The server wouldn't know
So, communication wouldn't be possible
So, the Owner setting must be done on the server
so that the server can communicate
and coordinate all these settings based on the owner
Alright, let's move this part
to the NetTPSCharacter header file for testing purposes
I'd like to see
how this Owner with the connection behaves
by printing a log message at the bottom
In the public section
let's print out
the network-related members to see
First, to continue printing
let's add the Tick function in the Lifecycle Functions
Add the virtual void Tick function for printing
Place the virtual void Tick function like this
and then I'll create a function below for printing network logs
I will name it printNetRog as void
So, shall we create two functions?
Let's implement Tick first
Then, let's implement
the printNetRog function right below
The two functions are registered in NetTPSCharacter.cpp, right?
And in the Tick function, be sure to call super.tick first
And to ensure that this Tick function continues to be called
Tick needs to be operational
By default, this is turned off in the constructor of NetTPSCharacter
So I'll set this to true to turn it on
Let's put this up to the constructor function
I'll add it right at the top of NetTPSCharacter
Here, I'll set the property bCanEverTick
from PrimaryActorTick to true
Setting bCanEverTick to true ensures that the Tick function will continue to be called
And now let's move back to Tick
Here, I'll just put the code to call the printNetRog function
Then Tick will continuously output some log values
Here, I'll add the content
so that I can continuously output this network log
to the console debug log window
I'll first print
the connection-related information here
Let's see
how well the current output of the user's connection is working
I'll set it as const FString.connectionString for the string
GetNetConnection
If you look at it
GetNetConnection returns a UNetConnection object
if that value exist
If it's not a null pointer, what would we do if it exists?
I'll put ValidConnection in the text
That means I have the connection
Otherwise, I'll use the ternary operator
to put InvalidConnection
So what happens if data comes
through the GetNetConnection function?
We want to output ValidConnection if it exists
and if not
output InvalidConnection
and let's print this conStr value below
We'll use the drawDebugString function to output the debug string
getWorld and then the position is printed at the actor's location
Print the string conStr at this player's position
Put 'actor, baseActor are null' at the end
And let's set the color to white
for FColor
And let's set the value at the end to 0
Then let's put true, and the value as 1
Now let's build it
I want to display the screen with conStr value set to white
It's built now
Let's move to the Unreal Editor
Let's delete
the test object we placed here
for testing purposes
Alright, done
Alright, go ahead and press the play button
How is it then?
The "InvalidConnection" message is being displayed
on the user's screen right now
Do you see it?
I see 'InvalidConnection' printed here in front of me
Why does it say 'InvalidConnection' on mine right now?
Is the connection not there?
That's because it's a dedicated listen server
A listen server means the server and client
are physically in the same space
Logically they are separate, right?
But physically being in the same space, how does that work?
There's no real need to have a connection object
internally, it's just itself, right? The connection doesn't really matter
So this means there's no actual connection itself
There's no meaning to being connected with oneself
It's about connecting with other users
So, in this form created by the server
does it currently need a connection or not? It does not
Since it's both
the server and the client itself
there's no need for a connection here
Alright, next let's add another play button
I'll add an 'Add Client' button at the top
Where is it located? It's right here
By pressing this button
you'll be able to add the button located here
It's right here
Let's click this button
So now a popup should appear, right?
So then another player will appear
Right now, you can see this newly added one, and it's my player
And in this client window, it says 'Client'
In the client window, this is currently the main character of the client
and it's a character on the server
Alright, let's see
Your own character here is valid, indicating it's yours
The character on the server is invalid
and the newly added one needs a valid connection
for communication between them
In reverse, when you look at it from this side
your own character shows a valid connection
while the server's character shows
an invalid connection
Let's print out the current owner states of these characters
to see how they're assigned
Alright, print
Here, let's add it
inside the NetLog function
This time, let's name const FString as ownerName
If there is GetOwner in ownerName
if there is owner, I will put the name in GetOwner
Use GetName to put the name in
If not
I will display that owner does not exist in TEXT like this
If owner exists, put the name of owner into ownerName
If owner does not exist, place 'owner does not exist' like this
Alright
Then, I'll combine these two sentences
and make it into one sentence
n const FString, insert logStr
and FString printf, and here TEXT
connection with
%s newline for line break
Then, append conStr at the end
Next, insert
ownerName
By doing this, create logStr using printf
and then use logStr
instead of conStr in draw debug string
Alright, then the two variables
conStr and ownerName, that we want to output will both be included
If you want to print this to the console
you can do it using UE_LOG
For now, to visually see it on the screen
we will use draw debug string to output it
Built it
Shall we go back to the Unreal Editor and try playing it again this time?
So, how is it on the server now?
Player controller 1, player controller 0
all of this gets printed out, right?
But it doesn't work on the client
Why is that?
Because the server has
all the player controllers of all the clients
so it can print them out
Role and Authority
Now, let's learn about role and authority
Role means role, and this refers to authority
It's the networking structure
provided by Unreal Engine that facilitates communication between server and client types
It's the structure where the server and clients communicate together
So, why does this concept of role, or role-playing, become important?
It's because of this aspect
In a listen server, it can act both as a server and as a client
So, this becomes very important for us
This entity is currently a client
but because it's also together with the server
these clients can physically be together
with multiple clients at the same time
However, logically, how is it?
It's in a dropped state
However, physically, since they are together
there's a need to distinguish between them
Since they are together in one place in the code
we need to distinguish this part
So, currently, whether my role is the server
or whether it's here together in this way
because it's a listen server
there's a need to distinguish
whether I'm currently serving as the server or not
Because if I'm the server, I should be fulfilling the server's role
If I only have client permissions
then I shouldn't be taking on server roles
recklessly, right?
That's why having this concept of roles is necessary
There are three types or forms of roles
Let's distinguish between authority and proxy roles
'Proxy' generally refers to a representative, substitute, or delegate
It's not done directly, you could also say it's a replication
Let's just say it's a replica or a duplicate
Let's just interpret it as a proxy
Then, how is it?
Authority is the server itself, so it's the entity directly generating the data
It's the entity that directly creates or generates the data
How about clients?
They are not the ones creating or generating data
Clients request data from the server and simply replicate or duplicate it
That's exactly what we call a proxy
So, the two below immediately become clients
The one above becomes the server
Right?
Let's take a look at
how these roles are
currently structured
Shall we switch over to Visual Studio and navigate to the print log function?
Let's print out the roles we need right here
We can use roles extensively throughout various parts
so let's create a macro
to print out these values
Alright, in the Solution Explorer, on the right
under 'nettps,' besides 'private,' you should see header files in 'public
You have the nettps header file, right?
Let's open it up
Let's open that file up
I'm going to create a macro here
to print out the roles
So, I'll use #define
and I'll consider two things: local role and remote role
This concept of roles can be seen in two different modes
like this
Alright, on the screen, there are clients like this, and there are several of them
The 'local role' refers to
how this entity appears on my screen right now
As I look closely
oh, you're asking
what role you are within my local screen view, right? In that case, you're the authority
So, what is it then?
You can realize that I'm currently the server
We can tell that it's a server
And also, I'll check again
This one's local role is
autonomous proxy
So, what can I do?
I can receive input
I'm a client, not a server, I'm a client
And I can receive input. That's how you can find out
You can do it like this
So, since I can receive input
I can then send data to the server
and make requests like that
Then, when I analyzed my local role here
I found out that I'm simulating
So, can I receive user input?
No, I can't
I shouldn't handle those kinds of things
This differentiation is necessary because of reasons like this
So, why is remote role necessary?
When I looked at Remote Role
I found out
it's simply a simulated proxy
Or rather, it's autonomous; the authority
So you're the authority Then, what does that mean?
It means that on the remote side, you're in the server role, right?
In server mode, when you look at the others, 'simulated' usually appears, right?
let's see it like this
In server-client mode, when it's like this
I'm here as an autonomous proxy
So, what should I show to this one here?
Locally, I currently appear as an autonomous proxy to myself
but how would I appear to this one?
Since this entity is created by the server itself
it has authority
So, from this entity's perspective, its local role is authority
I'm the server, right?
So, it's authority
However, what is it on the remote side?
It would become an autonomous proxy on the client side
You can see it divided into these two modes like this
Local Role
and then Remote Role
We can view it divided into local and remote roles
However, when you're actually working
explicitly distinguishing between Local Role and Remote Role
saying this is authority
and this is autonomous proxy
can sometimes be challenging to manage
So, there's a function
that provides whether I'm the server
or controlling it locally
We'll look into those things a bit later
First, let's check the current status of the Local Role
and Remote Role
When we get there
I'll try to check the Local Role
Here, leave a space
and then open parentheses
(UEnum GetValueAsString)
Through this function
you can get a value called ENetRole
Next, you can simply call GetLocalRole on this actor
In other words, you can get GetLocalRole here and use it directly
This means you can also print it this way
Right now, we're trying to print this
in NetTPSCharacter here
This means we can print it like this
const FString
So here, if it's a role like
Local Role, you can attach it like this
If you go there, you'll see that it returns the role
What role is it currently set to?
GetLocalRole is currently set like this
It's currently designed to fetch
and return the role I'm assigned in the network
We're trying to convert that value, which is an Enum
into a string so we can print it
But since we keep using these terms frequently
it ends up being used in various places
I'm trying to make a macro out of this
Now, coming back to nettps.h, I've set it up like this
Next, let's change it to remote role
instead of local role this time
Here, instead of GetLocalRole
you should put GetRemoteRole
In the NetTPSCharacter.cpp file
you're going to add this content to DrawDebugString in PrintNetLog
So, you'll place logString
followed by ownerName
and a newline character
You'll add a newline here
and print both the local role and remote role
You'll place local role
%s here
followed by a newline
and then remote role %s
Then you can add Local Role
followed by remote role at the end
So now, Local Role and Remote Role should appear in red
You need to include it
So, at the top
include nettps.h
with a #include directive here
I'll go ahead and add #include
"nettps.h" at the top of NetTPSCharacter.cpp
Let's go check to make sure everything is working properly, and then I'll build it
Let's go ahead and try playing to see how it works
So currently, it shows 'Connection: Invalid Connection' here
and Player Controller 0 is set as the owner
Local Role is set to 'Role: Authority'
and Remote Role is 'Role: Autonomous Proxy'
Since it's a client, it acts as both server and client
So, on the server side, it's a server, so what about the Local Role?
It's set as 'Authority'
and since it's also a client
because it can receive input
Remote Role is set to 'Autonomous Proxy'
Alright, let's run one more test
Alright, now for clients
it shows the connection and owner
Next, what about the Local Role?
Since this is the server, it's a server window here
So, here it shows that the Local Role is set to 'Authority'
And the Remote Role is set to 'Autonomous'
It's a client
Let's go over to this client window and take a look
In the client window
the connection is currently valid
The Local Role is set to 'Autonomous Proxy'
Right?
So, this means it can receive user input
The Remote Role, for the server-side, becomes 'Authority', correct?
The two roles are reversed
On the server side, it's 'Authority', and on the remote side
it's 'Autonomous'
Alright, from the client's perspective
its own local role is 'Autonomous Proxy'
What can we do?
It means it can handle user input processing
It means it can make requests to the server, like saying, "Hey, do this for me"
It means it can request the server to perform certain actions
although the logic itself must be implemented locally
Where does the logic execute?
It runs on this server
and Remote Role indicates it's the server
Alright, let's take a look at the server-side experience
Let's switch to the client window to see how it looks when it's acting as a server
Here
this character is the server character
What is the Local Role set to for the server character?
It's set to simulate physics
So, on the server
this character is set to simulate physics
meaning when the server-side character moves or performs actions
the clients can simulate data related to it
Of course, the Local Role can only be set to simulate physics
When the character moves on the server
since it's not me, I just replicate this data
So, it's simulated physics
and since it's on the server
it means
the server is currently handling this
Do you understand?
So, I've analyzed
how each character's role is determined
when created on both the server and client screens
It's done
And as I mentioned
in development, the current role itself isn't usually critically important
Why?
We're mainly concerned with
whether it's the server or if I can receive input locally
So, I can receive input
and then I can request the server to process this data as needed
That's what matters
Actually, being an Autonomous Proxy
these things might not matter much
So, there are functions that provide these checks
such as HasAuthority
and IsLocallyControlled
So, if you look
there's a function like NetTPSCharacter
I'm going to delete this function right away, HasAuthority
This function exists
It provides itself
If you look into HasAuthority
it basically means 'do you have authority'
in other words, 'are you the server?' It's the same thing
Let's take a look
Let's go see how it's implemented
How is HasAuthority implemented internally?
What is the Local Role set to?
Is it authority? In other words, is it the server? That's what it's asking
If the local role itself is set to authority, then it means it's the server
So HasAuthority essentially asks 'are you the server?'
It analyzes the role itself to determine
whether it's the server or not
If we're talking about a real implementation of HasAuthority in development
then yes, it typically means "if it's the server"
Next, I want to send the input from the user
saying they shot a gun
to the server
so that the server can handle that game logic
In that case, how would I know
whether I can shoot the gun or not?
So, I need to know whether I am the Autonomous Proxy
There's a function called IsLocallyControlled that helps with those things
Since this is a Pawn
it operates with the IsLocallyControlled function from the Pawn
If it's a player controller
then there's a function called IsLocalController
Let's go ahead and try using it to learn more about how that function works
Let's go ahead and take a look first
When you see IsLocallyControlled
it means checking how it's implemented inside
When you have a controller, you use IsLocalController
So, on the client side
how many player controllers are there?
I mentioned there's only one
There will be only one, then
So, since there's only one, why bother checking if I'm local?
Because the server also has the same client player controller
it needs to check whether it's local or not, because it could be either the server or a client
How?
So, since there's a controller
it means there's a player controller
that can handle input
That's why it checks again here
because you could be both a client and potentially a server, depending on the context
If you go into IsLocalController, you can see how it's implemented
There's NetMode
as you scroll down, you'll come across sections like this
If NetMode indicates that it's currently running on the client
what is the Local Role set to?
AutonomousProxy
It's the client window
NetMode indicates that it's running in the client window
And what is the Local Role?
AutonomousProxy
So, what does that mean?
It means the user can receive input and request actions from the server
So, what exactly does IsLocalController refer to or do?
It means checking whether it's currently controlling locally
It checks whether on the client side, it's controlling itself Am I able to receive input?
That's what this is about
So, here "AutonomousProxy" is not the case on the remote side
But here it says it has Authority
So, even in the case of a listen server where the client and server are together
how does it work when the client is controlling itself?
It should still be able to receive input
So, here it's true, and the rest are false
AutonomousProxy
In cases where the client can receive input
it returns true like this
So, you don't need to manually distinguish between Authority, AutonomousProxy
and such things like that
You can use functions like HasAuthority, IsLocalController, or IsLocallyControlled
to differentiate between these roles
Alright, we were able to cover roles and understanding Authority through this discussion
In our class, we proceed with creating network games
using a listen server
Let's summarize the concepts we’ve covered in this lesson
Network connection structure and communication processing structure
Network Connection Structures Comparing the connection structure between users on a single PC (Standalone) and the Server-Client model types
Communication Processing Structure Communication between clients and servers
Client-side processing logic and server-side processing logic Two methods of sending logic execution results to users, NetMulticast RPC and Client RPC
Player Controller and Connection The structure where Player Controller handles communication between clients and servers
Player Controller It possesses an object called UNetConnection
For a general Actor that exists identically on both the client and server, communication is possible through its owner The working structure of how an Actor communicates through its owner
Role and Authority In a listen server setup, where the server includes clients, it's necessary to differentiate between the server and clients within the running environment
Types of Roles There are Authority, AutonomousProxy, and SimulatedProxy roles, with Authority representing the server
Proxy: A replica of an actor that exists on the server AutonomousProxy: Refers to a proxy through which a user can send control inputs to the server
SimulatedProxy: Performs the role of simply replicating values from the server
The End