x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

Server Replication Question (Spawn a Class)

Hello everyone! I am not new to programming but to UE4 and currently have some issues understanding how the interactions between clients and the server proceed.

For my current project, as an example, I have multiple players. It is kind of an RTS game, so every player can own different types of building structures. First question: Should these buildings be pawns or actors? A player should own them but never really "possess" the building, eg look through them or move with them. In fact, they are static, but belong to a specific player can do stuff with it (other players also have to have the possibility to see it and attack it, but I think you know what I mean). So, the main question(s) I have:

To realise building a base I thought about the following process:

1.) The player triggers an event, eg a click on the landscape, telling the game that he would like to build a base here 2.) A server request is send to the server, to validate all conditions for building a base for Player P at Position XYZ. 3.) If the conditions are valid, spawn a base-class-instance on the server and replicate it to all the other players. 4.) Later on, if a Player clicks on that base, send server request to validate if the base belongs to this player 5.) If yes, open building menue, if no, open attack menue

But here I have multiple questions.

If I send a server request, this request goes through the network to the server. Now he handles it and may spawn a base. But doesnt make that him being the owner of that base? And when it replicates this base to all the other players, does that mean, that he triggers all other players to also spawn a base at this position?

Also, this Get Player Controller function confuses me. What does it mean? Do the player controller 0 to X represent all X-1 players on the server? If yes, how can I, the local player, determine which player I am? I know that I have a unique ID in the player State, but to obtain the player state I have just to extract it from the get player controller output.. When I spawn a class on server, I also have to give him an input, which player controller it should spawn on. But how can I determine inside a server function who send this request? I has to be possible to just create that thingy on the server with player identifier integer and duplicate that thing to every other player, 1:1..

Soo many ambiguities.. I would virtually hug you to death if you could make things clearer for me a little bit. I think, I just have a big misconception about server replication and the interaction between clients and servers..

Best greetings!

Product Version: Not Selected
Tags:
more ▼

asked Mar 12 '15 at 01:37 PM in Using UE4

avatar image

MykonCodes
96 8 15 25

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first
 /**
  * Owner of this Actor, used primarily for replication (bNetUseOwnerRelevancy & bOnlyRelevantToOwner) and visibility (PrimitiveComponent bOwnerNoSee and bOnlyOwnerSee)
  * @see SetOwner(), GetOwner()
  */
 UPROPERTY(replicated)
 AActor* Owner;

The Actor class has an Owner that you can set which will be replicated. The owner can be anything, like an Actor or Pawn that represents your player. However, I don't know if I would recommend the owner being the PlayerController (since the PlayerController is only replicated between the server and the owning player) or even the Pawn. Instead, you should have some replicated Actor represent your player and their info. A PlayerState may actually work well for this. Everyone has a replicated copy of every player's PlayerState, and since the Owner is replicated they will be able to tell which PlayerState specifically owns the building.

GetPlayerController would only provide all the PlayerControllers to the server. For the client, as I mentioned above, they only have a copy of their own PlayerController, which is typically at the 0th index. However, I would not really rely on this method. The PlayerState's Owner is conveniently the PlayerController.

You can get the PlayerState from your PlayerController also. You shouldn't really need to "find" your PlayerController as it's logic should be to just manipulate input.

As for letting the Server know who sent the request, well the server knows "who" sent it based on who owns the object the request is being made on. The Owner of a PlayerController is a UPlayer by the way. I'm not sure how to use that class though. But anyway, if the PlayerController makes a Server RPC (message), then that RPC is called on the replicated version of the PlayerController on the Server, and so the Server knows inherently which player or actor that is (and can also access that PlayerController's PlayerState).

So basically, for what you want, the PlayerController should send a server message, which is to its replicated version on the server. The Server can then check the PlayerController's PlayerState for things like money to build (which, by the way, you should probably use a DOREPLIFETIME_COND and COND_OwnerOnly for money in an RTS), and also use that PlayerState as the Owner of the newly built building. The building, an AActor, just has to have SetOwner called on it after creation and presumably in this case we SetOwner to PlayerState.

By the way, I didn't really know most of this till you asked your question, so thank you for asking. You can find out a lot by searching the source code.

I hope this helps!

more ▼

answered Mar 15 '15 at 04:13 AM

avatar image

Cobryis
472 33 18 47

avatar image MykonCodes Mar 20 '15 at 12:41 PM

Thanks man, I think things are getting a bit clearer.

Actually I didnt got any notification that you answered my question and I only found it in google by clicking on my own asked question :D

I think you also resolved another big question of mine: Private data. So, I can store all player data like his diplomatic relationship to other players and other important stuff "enemys" shouldnt know about (because may they are hackers) in the playerState and just mark them as COND_OwnerOnly?

avatar image Cobryis Mar 20 '15 at 08:37 PM

Yup, that would make cheating more difficult and it would reduce bandwidth a bit since that data is only relevant to one client.

avatar image MykonCodes Mar 20 '15 at 09:02 PM

I hope I am not too outrageous if I ask you one more question. Hard to get some good answers these days :D

I have a class named IngameRessources. It is only a Data-Management class handling virtual ressources of a Base like Iron, Wood, and Stone. The class is not derived of any Unreal Class, so I can't maunally replicate it (I dont know why, but my compiler says it's not possible, sadly enough). But what happens when I put an instance inside a PlayerState? I can't add a Replication Condition to it, same reasons as mentioned above. Is this variable then just not replicated at all or what happens?

Aaand one last question, I promise :D If I have an actor spawned in the world and a client tells the server that he thinks that he owns that actor (on a gameplay basis). How can I implement to verify that? At the moment, I save a copy of the playerState PlayerID inside that actor-object. But couldn't a client just manipulate his own PlayerID and pretend to be another player? Do you consider this a good/safe method or are there better, maybe even inbuilt possibilities?

Thanks for your answers :)

avatar image Cobryis Mar 21 '15 at 03:45 AM

You can replicate entire structs if their properties are marked as UPROPERTY().

Simplified example from ShooterGame:

 /** replicated information on a hit we've taken */
 USTRUCT()
 struct FTakeHitInfo
 {
     GENERATED_USTRUCT_BODY()
 
     UPROPERTY()
     float ActualDamage;
 
     /** The damage type we were hit with. */
     UPROPERTY()
     UClass* DamageTypeClass;
 
     UPROPERTY()
     TWeakObjectPtr<class AShipPawn> PawnInstigator;
 
     /** Specifies which DamageEvent below describes the damage received. */
     UPROPERTY()
     int32 DamageEventClassID;
 
     UPROPERTY()
     uint32 bKilled : 1;
 
 private:
 
     /** A rolling counter used to ensure the struct is dirty and will replicate. */
     UPROPERTY()
     uint8 EnsureReplicationByte;
 
     /** Describes general damage. */
     UPROPERTY()
     FDamageEvent GeneralDamageEvent;
 public:
     FTakeHitInfo()
         : ActualDamage(0)
         , DamageTypeClass(NULL)
         , PawnInstigator(NULL)
         , DamageEventClassID(0)
         , bKilled(false)
         , EnsureReplicationByte(0)
     {}
 
     FDamageEvent& GetDamageEvent()
     {
         if (GeneralDamageEvent.DamageTypeClass == NULL)
         {
             GeneralDamageEvent.DamageTypeClass = DamageTypeClass ? DamageTypeClass : UDamageType::StaticClass();
         }
         return GeneralDamageEvent;
     }
 
     void EnsureReplication()
     {
         EnsureReplicationByte++;
     }
 };

 class AMyPawn : public APawn
 {
     ...
     UPROPERTY(Transient, ReplicatedUsing = OnRep_LastTakeHitInfo)
     struct FTakeHitInfo LastTakeHitInfo;
     ...
 }


 void AMyPawn::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
 {
     Super::GetLifetimeReplicatedProps(OutLifetimeProps);
 
     DOREPLIFETIME_CONDITION(AMyPawn, LastTakeHitInfo, COND_OwnerOnly);
 }
avatar image Cobryis Mar 21 '15 at 03:47 AM

I'm replying to my comment because it was getting impossible to edit the last one. Anyway, only Actor data is replicated, so the struct must be on an actor. The PlayerState may very well be the best place to put a struct with all your OwnerOnly.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question