Announcement

Collapse
No announcement yet.

A Crash Course In Blueprint Replication

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    A Crash Course In Blueprint Replication

    Hey guys! Lead programmer Dave Ratti has put together a post for you on blueprint replication. You can view the original post over on our blog.



    Blueprint classes can replicate the same way as native C++ classes can. This is a crash course on getting started, though is not a full tutorial on networking gameplay code.

    Making a blueprint replicate

    A class must first be marked to replicate. Without doing this, a blueprint actor spawned on the server will not spawn on clients. This is done in the blueprint defaults, under replication:



    Testing multiplayer in the UE4 Editor

    The UE4 Editor provides a built in way for testing multiplayer games. To use this, simply set Number of Clients to a value greater than 1 in the Play In Editor Network settings. Then use the Play In Editor feature - by selecting the New Editor Window mode. This will launch a separate editor window for each player, and automatically connect them into a multiplayer game. This is the easiest way to test and iterate on multiplayer gameplay.



    Authority checks

    It will be important to only run certain parts of your blueprint logic on the server. For example, the server should be authoritative over the health value of each actor. Only the server should handle changing health. Clients should be free to run cosmetic logic, but should not run gameplay critical code on their own.

    Doing this check in blueprints is simple; just use the Switch Has Authority macro:



    Replicating Variables

    Replicated variables are used to replicate state. Replicated variables are sent from server to client only. That is, the server's value of a replicated property is sent down to all clients. Only the latest/current value of a property is sent. To make a property replicated, simply select the Replicated or RepNotify from the Replication drop down in the variable details panel.



    'RepNotify' means the variable is replicated down like normal, and a notify event is called on both client and server when the variable changes. This is useful when you need to do additional work based on a replicated variable. For example, you may replicate Health down as an integer. In Health's RepNotify event you may look at the health value and apply cosmetic damage effects (swap mesh, apply damage decals, play sounds, etc). It is more efficient to apply the cosmetic damage in a RepNotify than to replicate each cosmetic effect down individually.

    If you select RepNotify, a function will automatically be added to your blueprint. It will be named OnRep_YourVariableName. Just implement a body in this function and will be called automatically.

    Replicating Events (RPCs)

    Events can also be replicated as RPCs (remote procedure call). An event can be called on one machine and replicate to another where it is executed. To use this feature, create a new custom event in your event graph. Click on the custom event and edit the Replication settings in the details view:



    There are three types of replicating events:

    Multicast events are called on the server and are executed on the server and all connected clients. These can be called on any replicating actor. Multicast events are best for replicating transient events (e.g, not state) to everybody.

    The Server RPC type (‘Run On Server’) is needed for blueprints to communicate client to server. A Server RPC is only executed on the server. When the client reaches the node to call the custom event, he will send a packet to the server telling it to execute the event on the actor. The client himself will not execute the event locally.

    Server RPCs can only be called by a client who owns the actor executing the event graph. For example, a PlayerPawn is owned by the client who controls it - only that client can send Server RPCs on that pawn. The pawn also may own weapons, abilities, inventory items, etc (this is game specific). This can be a hard concept to communicate directly in blueprints. It is something we will work to improve as time goes on.

    A client RPC (‘Run on owning client’) is only sent from the owning client. In the same way that only the owning client can send server RPCs, only the owning client will receive Client RPCs sent by the server.

    Finally, blueprint RPCs can also be checked to be reliable. By default, blueprint RPCs are unreliable and should almost always be unreliable. You should only make a function reliable if you are sure it needs to be.

    Do you guys have any questions about blueprint replication? Sound off below and let us know!
    Attached Files

    #2
    Couldn't spawn pawn

    Hey,

    Thanks for the tutorial!
    Here I tried many times to start the game with multiple clients from the FPS Template project, but I keep get this warning information:

    "LogGameMode:Warning: Couldn't spawn Pawn of type MyCharacter_C at PlayerStart"

    Seems it's a bug from unreal engine 4, because I saw some other developers also posted the same issue.
    https://answers.unrealengine.com/que...pawn-pawn.html

    He solved by port the code from ShooterGame example, could you tell me, is that really necessary to do that, because I found maybe when did this step " SpawnInfo.Instigator = Instigator; " but Instigator is NULL cause that, if not, any advice to solve it ? Thanks!

    Comment


      #3
      I've been stuck on a replication problem. I'm trying to create a super simple chat system.

      You can have any number of clients.
      Each client has a HUD widget where they can enter in a text string and press a button to submit it.
      When a client enters in text, every other client should see a text area get updated with their entered text.

      Implementation:
      Clicking the submit button will take the text message within the clients widget and send it to the game state.
      From the game state, it gets sent to a "ChatSystem" actor which contains an array of strings.

      [Client X HUD] ---> [Game State] ---> [Chat System] ---> [String Array]

      Both the chat system actor and its array are replicated.

      The chat data should only be updated on the server and all clients should update their HUD when the chat data changes.

      The issue:
      If a client submits a chat message via Server RPC, it doesn't get sent to the server.
      If the server sends a message to the chat system, all clients get the update.


      What should happen:
      The server is the owner of the chat system actor and only the server can update it. The clients can send message requests to the server, but the server can decide whether to process the message. If the server decides to process the message from the client, it should be the one updating the chat system and its internal array. Once that happens, all of the clients get the new chat system replicated to them and they can refresh their chat windows to view the updated text.

      [Client 1 HUD] --RPC--> [Server Game State] ----> [Server Chat System] ---> [Add String Array]
      |
      \|/
      [Client 2 HUD] <---- [Server Game State] <--- [Server Chat System] <---- [Replicated Array Data]



      What I think is happening:
      The server is the authoritative owner of the game state. The game state is being replicated to all clients.

      Server - [Game State*]
      Client 1 - [local Game State]
      Client 2 - [local Game State]

      If Client 1 sends a message to the game state, the message is being sent to its local game state instead of the server game state. The local game state doesn't have ownership of the chat system, so it fails to send an RPC (why is the message going to the local game state and not to the server?). It's not even trying to send an RPC message to the server and the server isn't getting it. What am I doing wrong and what do I need to do to fix it?



      Comment


        #4
        I do my chat in my gamemode - my controllerl sends my game mode a message, it then adds it to my message list - then loops through all of the controllers and adds to to their replicate list of chats - then on my clients, the rep notify for that list is where it updates the UI

        I'm going to add chat to my multiplayer game sample here this weekend https://github.com/bitporters/RC_TRAINER
        ZOMBIE TOWN AHHH (ANDROID/STEAM) | RIDE SHARE EMPIRE (ANDROID/GAME JAM) | NEVER NOT KNIGHT (ANDROID/GAME JAM) | TWITTER | MY UE4 TUTORIALS | ANSWERHUB

        Comment


          #5
          I've updated this simple project to include a basic chat - https://github.com/bitporters/RC_TRAINER uploading a build and might do a quick youtube vid later

          <- showing the chat & quick overview of how I set it up in blueprint, you can download the sourcecode from github too (i go really fast)
          Last edited by BPANDREW; 02-15-2015, 05:43 PM.
          ZOMBIE TOWN AHHH (ANDROID/STEAM) | RIDE SHARE EMPIRE (ANDROID/GAME JAM) | NEVER NOT KNIGHT (ANDROID/GAME JAM) | TWITTER | MY UE4 TUTORIALS | ANSWERHUB

          Comment


            #6
            Originally posted by BPANDREW View Post
            I do my chat in my gamemode - my controllerl sends my game mode a message, it then adds it to my message list - then loops through all of the controllers and adds to to their replicate list of chats - then on my clients, the rep notify for that list is where it updates the UI

            I'm going to add chat to my multiplayer game sample here this weekend https://github.com/bitporters/RC_TRAINER
            This confuses me a bit. Isn't this supposed to be taken care of by replication? You shouldn't have to go through and manually update each clients chat structure, right? If the chat array is replicated, then as soon as the server updates the chat data, the data gets replicated to the clients. All the clients would need is a "RepNotify" event so that they can refresh their GUI with the latest chat data with the latest replicated data from the server. That's how I've got it working on mine...

            I guess I'm trying to wrap my head around how the server/client relationship works. The chat system is just a test of my understanding here.

            To my understanding, the server is the authority on the whole state of the game and their actors. In "model-view-controller" terms, the server hosts the definitive model. Clients are viewers of the server model and they can interact with the model by using controllers. Clients will build a *copy* of the model on their local machine, but the copy is not the definitive model. If the client wants to interact with the model and make a change to it, they send a message to the server via RPC. The server then gets to validate that message and decide if the client request is legit. Such as, "Move my character forward by 10 feet.". If the request is validated, the server then processes the request by making a change to the authoritative game model. That change then gets replicated to all clients, and they update their local copy of the game state.

            Sometimes the server will want to send out a message to all connected clients, such as "This bomb has exploded, play a particle effect at its location.". This is when a non-reliable multicast message would be handy.

            In the case of my chat system, here's where UE4 replication gets funky:
            -In order for an object to be replicated, it MUST be an actor.
            > "What?! What if I don't want any of the memory overhead which comes with actors? I just want to have a replicated array of strings."
            > "Too bad, put it into an actor. Besides, don't worry about it."
            -You can only make a change to an object if you are the network owner of it.
            > "Okay, fine. The server owns everything and clients have to ask the server to change those objects." Except the server says, "I own this object, you can't change it! your RPC request is denied!"



            Here's what should happen:
            Server: "Hey clients, here is the current list of chat messages! I'm maintaining and replicating its data to you."
            Clients: "Thanks, we'll refresh our gui to display them to players!"
            Client X: "Hey Server, I'd like to add a message to the chat with the following string: 'hello world'".
            Server: "Okay, that sounds legit. I'll add it to my array of chat messages."
            Server: "Hey all clients, the chat messages have been updated! Make sure you refresh your GUI to display the updated info! It's already been automatically replicated to your local copy."
            Clients: "Thanks! Got it! Refreshing GUI now."
            Client X: "Hey, I'd like to add this spam message to the chat."
            Server: "Whoa, hold on there. It's been 0.1 seconds since your last chat message and this is the same one as last time. Denied!"
            Client X: "Dang "

            Instead, here's what happens:
            Server: "Hey clients, here is the current list of chat messages! I'm maintaining and replicating its data to you."
            Clients: "Thanks, we'll refresh our gui to display them to players!"
            Client X: "Hey Server, I'd like to add a message to the chat with the following string: 'hello world'".
            Server: "..." (didn't get the message)
            Client X:
            Server: "I feel like adding a message to the chat queue! let's say, 'Server rocks your socks!'."
            Server: "Hey clients, the chat messages have been updated! Make sure you refresh your GUI to display the updated info! It's already been automatically replicated to your local copy."
            Clients: "Thanks! Got it! Refreshing GUI now."


            Anyways, I'm not new to network coding but I am new to UE4 networking. I may be totally wrong on my understanding of the architecture and interactions and would like some clarity.

            Comment


              #7
              I've provided complete source to a working example - how I got the ability to do this was stitched together from discussions on this forum - I am very eager for more networking samples from Unreal. My solution is a little foggy to me too because I agree with what you are saying.

              All I'm providing is "this is what works for me"
              ZOMBIE TOWN AHHH (ANDROID/STEAM) | RIDE SHARE EMPIRE (ANDROID/GAME JAM) | NEVER NOT KNIGHT (ANDROID/GAME JAM) | TWITTER | MY UE4 TUTORIALS | ANSWERHUB

              Comment

              Working...
              X