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. 

Started Replicating Properties. Now Clients can't move. Don't understand why.

Hello all,

TL;DR Set Up Replication on the first of my character variables, suddenly client characters are not able to move. Server (Host) character can move just fine.

I didn't realize how difficult it was going to be to convert a single-player game to a multiplayer game since I started producing one. So.. basically, I've been working on a multiplayer game but treating it as a single player game in terms of code. I have a few core systems in already, but nothing really serious. I recently realized that almost nothing in my game will work as a multiplayer experience without setting up replication and RPCs, so I have been trying to modify my code to support my originally intended multiplayer functionality.

The first thing that I tackled in this was to make sure that all of my game play relevant projectiles are replicated to clients. To do this, I renamed the OnFire() function (I started this project from a C++ 1st Person Template) to ClientOnFire(), and moved the logic from this function into a ServerOnFire() function (which is called only on the server. This allowed all projectiles to be spawned on the server.

This was working all fine and good. So I decided to tackle some player variable replication next. I started with the Equipped_Ammo_Remaining variable. I successfully set this up to replicate (ie. It compiles successfully). However, upon testing the game, I now have a fairly serious problem. After making this change, my player controlled characters can no longer move on clients. The server character can move just fine. but no client characters can. When using a listen server, the server character moves properly, but the client characters cannot. When using a dedicated server, none of the characters (all on clients) can move.

I'm really stumped here. I am certain that the change to Equipped_Ammo_Remaining (including the addition of "void AMonkeyNutsCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const" ) has caused my client characters to be unable to move, but I honestly have no idea why.

I'd appreciate any help with this that I can get. Thanks in advance for any response.

Code for my Character Class is shown below.

MonkeyNutsCharacter.h

 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 #pragma once
 #include "MonkeyNuts.h"
 #include "UnrealNetwork.h"
 #include "WeaponTypes.h"
 #include "MNPickup.h"
 #include "MNWeaponPickup.h"
 #include "MNCharacterMovementComponent.h"
 #include "MonkeyNutsProjectile.h"
 #include "MonkeyNutsCharacter.generated.h"
 
 UCLASS(config=Game)
 class AMonkeyNutsCharacter : public ACharacter
 {
     GENERATED_UCLASS_BODY()

 
 //////////***************Component Properties*******************//////////

........//Insert Component initialization stuff //////////**//////////

 //***Turning Variables**
     /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
         float BaseTurnRate;
 
     /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
         float BaseLookUpRate;
 
 //***Weapon and Projectile**
     /** Gun muzzle's offset from the characters location */
     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
         FVector GunOffset;
 
     /** Projectile class to spawn */
     UPROPERTY(EditDefaultsOnly, Category = Projectile)
         TSubclassOf<class AMonkeyNutsProjectile> ProjectileClass;
 
     /** Sound to play each time we fire */
     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
         USoundBase* FireSound;
 
     /** AnimMontage to play each time we fire */
     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
         UAnimMontage* FireAnimation;
     
 //**********Function Prototypes**********
 
 //////////***************Return Player Var Methods**************//////////

///Insert Get Private Variable Functions Here //////////**////////// //TICK FUNCTION Override for the player UFUNCTION() void Tick(float DeltaSeconds) override;

     //Allows the character source to receive OnActorBeginOverlap Events
         virtual void ReceiveActorBeginOverlap(AActor* OtherActor) override;
     //Allows the character source to receive OnActorB=EndOverlap Events
         virtual void ReceiveActorEndOverlap(AActor* OtherActor) override;
     //Allows the character to recieve OnBeginPlayEvents
         virtual void ReceiveBeginPlay() override;
 
     UFUNCTION(BlueprintCallable, Category = PlayerStatus)
     //Allows the character to check for interactable objects when overlapping other objects
         void CheckForInteractables(int32 OnorOff);
 
     //Returns what the character is currently looking at
     UFUNCTION(BlueprintCallable, Category = PlayerStatus)
         AActor* GetLookingAt();
     //Returns the Closest Interactable to the character
     UFUNCTION(BlueprintCallable, Category = PlayerStatus)
         AMNInteractable* GetClosestInteractable();
 
     UFUNCTION()
         void RunATrace();
     UPROPERTY()
         AActor* InteractableInRange;
 
         void PickUpWeapon(AMNWeaponPickup* WeaponPU);
 private:

 //////////***************Primary Player Variables***************//////////
     //Character Health
     UPROPERTY(EditAnywhere, Instanced, Category = PlayerStatus)
         int32 PlayerHealth;
     //The Character's Currently Equipped Weapon
     UPROPERTY(EditAnywhere, Instanced, Category = PlayerEquipment)
         TEnumAsByte<EWeaponTypes::Type> EquippedWeapon;
     //The Character's Currently Equipped Backup Weapon
     UPROPERTY(EditAnywhere, Instanced, Category = PlayerEquipment)
         TEnumAsByte<EWeaponTypes::Type> BackupWeapon;
     //Stores which carried weapon is currently equipped. 1 for Primary, 2 for Secondary.
     UPROPERTY(EditAnywhere, Instanced, Category = PlayerEquipment)
         int32 CurrentWeapon;
 //////////******************************************************//////////
 
 
     //The Closest Interactable to The Character
         AMNInteractable* ClosestInteractable;
     //The What the Character Is Currently looking at.
         AActor* ThingImLookingAt;
 
 //////////***************Player Ammunition Variables***************//////////
     //Total Amount of Ammo Stockpiled for Current Weapon
     UPROPERTY(EditAnywhere, Replicated, Instanced, Category = PlayerEquipment)
         int32 Equipped_Ammo_Remaining;
     ///INSERT OTHER Variable Properties similar to Equipped_Ammo_Remaining, bbut these are not replicated. 
 //////////******************************************************//////////
 
 protected:
     void Interact();
     void SwitchWeapon();
 
     /** Handler for a touch input beginning. */
     void TouchStarted(const ETouchIndex::Type FingerIndex, const FVector Location);
 
     /** Fires a projectile. */
     void ClientOnFire();
 
     //Server Driven Fire Function
     UFUNCTION(Reliable, Server, WithValidation)
     void ServerOnFire();
 
     /** Handles moving forward/backward */
     void ClientMoveForward(float Value);
 
     UFUNCTION(Reliable, Server, WithValidation)
     void ServerMoveForward(float Value);
 
     /** Handles stafing movement, left and right */
     void ClientMoveRight(float Value);
 
     void ServerMoveRight(float Value);
 
     /*
      * Called via input to turn at a given rate.
      * @param Rate    This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
      */
 
     void TurnAtRate(float Rate);
 
     /**
      * Called via input to turn look up/down at a given rate.
      * @param Rate    This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
      */
     void LookUpAtRate(float Rate);
 
 
     // APawn interface
     virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
     // End of APawn interface
 };
 

MonkeyNutsCharacter.cpp

 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 
 #include "MonkeyNuts.h"
 #include "UnrealNetwork.h"
 #include "WeaponTypes.h"
 #include "MNWeaponPickup.h"
 #include "MonkeyNutsCharacter.h"
 #include "Math.h"
 #include "MNWeaponInfo.h"
 
 
 //////////////////////////////////////////////////////////////////////////
 // AMonkeyNutsCharacter
 
 
 AMonkeyNutsCharacter::AMonkeyNutsCharacter(const class FPostConstructInitializeProperties& PCIP)
     : Super(PCIP.SetDefaultSubobjectClass<UMNCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
 {
     //***Basic Properties***
     bReplicates = true;
     bOnlyRelevantToOwner = false;
     bReplicateInstigator = true;
     bReplicateMovement = true;
     // set our turn rates for input
     BaseTurnRate = 45.f;
     BaseLookUpRate = 45.f;
 
     /** CharacterMovement component used by walking/running/flying avatars not using rigid body physics */
     UPROPERTY(Category = Character, VisibleAnywhere, BlueprintReadOnly)
     TSubobjectPtr<class UMNCharacterMovementComponent> CharacterMovement;
 
     // Default offset from the character location for projectiles to spawn
     GunOffset = FVector(100.0f, 30.0f, 10.0f);
 
     //***Component Properties***
 
     // Set size for collision capsule
     CapsuleComponent->InitCapsuleSize(42.f, 96.0f);
     
     // Create a CameraComponent    
     FirstPersonCameraComponent = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FirstPersonCamera"));
     FirstPersonCameraComponent->AttachParent = CapsuleComponent;
     FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 128.f); // Position the camera
     //RootComponent = FirstPersonCameraComponent;
     // Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
     Mesh1P = PCIP.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("CharacterMesh1P"));
     Mesh1P->SetOnlyOwnerSee(true);            // only the owning player will see this mesh
     Mesh1P->AttachParent = FirstPersonCameraComponent;
     //Mesh1P->AttachTo(FirstPersonCameraComponent);
     //Mesh1P->RelativeLocation = FVector(0.f, 0.f, -150.f);
     Mesh1P->bCastDynamicShadow = false;
     Mesh1P->CastShadow = false;
     //Mesh1P->AlwaysLoadOnClient;
 
 
     //Create a mesh component that will be used when being veiwed by other players.
     Mesh3P = PCIP.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("CharacterMesh3P"));
     Mesh3P->SetOwnerNoSee(true);
     Mesh3P->SetOnlyOwnerSee(false);
     Mesh3P->AttachParent = FirstPersonCameraComponent;
     //Mesh3P->AttachTo(FirstPersonCameraComponent);
     //Mesh3P->RelativeLocation = FVector(0.f, 0.f, -200.f);
     Mesh3P->bCastDynamicShadow = true;
     Mesh3P->CastShadow = true;
 
     // Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
     // derived blueprint asset named MyCharacter (to avoid direct content references in C++)
 
     //***Public Player Variables***
     PlayerHealth = 100;
 
     EquippedWeapon = EWeaponTypes::Type::Pistol;
     BackupWeapon = EWeaponTypes::Type::Unarmed;
     Equipped_Ammo_Remaining = 100000;
     Backup_Ammo_Remaining = 100000;
     Equipped_AmmoClip_Remaining = 100000;
     Equipped_AmmoClip_Max = 100000;
     Backup_AmmoClip_Remaining = 100000;
     Backup_AmmoClip_Max = 100000;
     Grenade_Ammo = 2;

}

 //////////////////////////////////////////////////////////////////////////
 // Input
 
 void AMonkeyNutsCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
 {
     // set up gameplay key bindings
     check(InputComponent);
 
     InputComponent->BindAction("Jump", IE_Pressed, this, &AMonkeyNutsCharacter::Jump);
     InputComponent->BindAction("Interact", IE_Pressed, this, &AMonkeyNutsCharacter::Interact);
     InputComponent->BindAction("SwitchWeapons", IE_Pressed, this, &AMonkeyNutsCharacter::SwitchWeapon);
     InputComponent->BindAction("Fire", IE_Pressed, this, &AMonkeyNutsCharacter::ClientOnFire);
     InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMonkeyNutsCharacter::TouchStarted);
 
     InputComponent->BindAxis("MoveForward", this, &AMonkeyNutsCharacter::ClientMoveForward);
     InputComponent->BindAxis("MoveRight", this, &AMonkeyNutsCharacter::ClientMoveRight);
     
     // We have 2 versions of the rotation bindings to handle different kinds of devices differently
     // "turn" handles devices that provide an absolute delta, such as a mouse.
     // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
     InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
     InputComponent->BindAxis("TurnRate", this, &AMonkeyNutsCharacter::TurnAtRate);
     InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
     InputComponent->BindAxis("LookUpRate", this, &AMonkeyNutsCharacter::LookUpAtRate);
 }
 
 
 
 void AMonkeyNutsCharacter::ClientOnFire()
 {
     if (Role <= ROLE_Authority){
         AMonkeyNutsCharacter::ServerOnFire();
     }
 }
 
 void AMonkeyNutsCharacter::ServerOnFire_Implementation(){
     if (ProjectileClass != NULL)
     {
         const FRotator SpawnRotation = GetControlRotation();
         // MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
         const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
 
         UWorld* const World = GetWorld();
         if (World != NULL)
         {
             // spawn the projectile at the muzzle
             World->SpawnActor<AMonkeyNutsProjectile>(ProjectileClass, SpawnLocation, SpawnRotation);
         }
     }
 
     // try and play the sound if specified
     if (FireSound != NULL)
     {
         UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
     }
 
     // try and play a firing animation if specified
     if (FireAnimation != NULL)
     {
         // Get the animation object for the arms mesh
         UAnimInstance* AnimInstance = Mesh1P->GetAnimInstance();
         if (AnimInstance != NULL)
         {
             AnimInstance->Montage_Play(FireAnimation, 1.f);
         }
     }
 }
 bool AMonkeyNutsCharacter::ServerOnFire_Validate(){
     return true;
 }
 
 void AMonkeyNutsCharacter::TouchStarted(const ETouchIndex::Type FingerIndex, const FVector Location)
 {
     // only fire for first finger down
     if (FingerIndex == 0)
     {
         ClientOnFire();
     }
 }
 
 void AMonkeyNutsCharacter::ClientMoveForward(float Value)
 {
     if (Role <= ROLE_Authority){
         AMonkeyNutsCharacter::ServerMoveForward(Value);
     }
     else if (Role == ROLE_Authority){
         if (Value != 0.0f){
             // add movement in that direction
             AddMovementInput(GetActorForwardVector(), Value);
         }
     }
     else{
         //Unhandled Exception
     }
     
 }
 
 void AMonkeyNutsCharacter::ServerMoveForward_Implementation(float Value){
     if (Value != 0.0f){
             //UE_LOG(LogTemp, Warning, TEXT("ServerMoveForward_Implementation Called. Value: %n"), Value);
             // add movement in that direction
             AddMovementInput(GetActorForwardVector(), Value);
     }
 }
 bool AMonkeyNutsCharacter::ServerMoveForward_Validate(float Value){
     return true;
 }
 
 void AMonkeyNutsCharacter::ClientMoveRight(float Value)
 {
     if (Value != 0.0f)
     {
         // add movement in that direction
         AddMovementInput(GetActorRightVector(), Value);
     }
 }
 
 void AMonkeyNutsCharacter::TurnAtRate(float Rate)
 {
     // calculate delta for this frame from the rate information
     AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
 }
 
 void AMonkeyNutsCharacter::LookUpAtRate(float Rate)
 {
     // calculate delta for this frame from the rate information
     AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
 }
 
 //////////////////////////////////////////////////////////////////////////
 ///Tick
 
 

 
 
 

 

 //Ammo Value Retrieval Functions
 int32 AMonkeyNutsCharacter::GetEquippedAmmo_Remaining(){
     return Equipped_Ammo_Remaining;
 }
 int32 AMonkeyNutsCharacter::GetEquippedAmmoClip_Remaining(){
     return Equipped_AmmoClip_Remaining;
 }
 int32 AMonkeyNutsCharacter::GetEquippedAmmoClip_Max(){
     return Equipped_AmmoClip_Max;
 }
 
 int32 AMonkeyNutsCharacter::GetBackupAmmo_Remaining(){
     return Backup_Ammo_Remaining;
 }
 int32 AMonkeyNutsCharacter::GetBackupAmmoClip_Remaining(){
     return Backup_AmmoClip_Remaining;
 }
 int32 AMonkeyNutsCharacter::GetBackupAmmoClip_Max(){
     return Backup_AmmoClip_Max;
 }
 
 int32 AMonkeyNutsCharacter::GetGrenade_Ammo(){
     return Grenade_Ammo;
 }
 
 //Other Functions

 void AMonkeyNutsCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const{
     DOREPLIFETIME(AMonkeyNutsCharacter, Equipped_Ammo_Remaining);
 
 }


 







Product Version: Not Selected
Tags:
more ▼

asked Nov 18 '14 at 04:29 AM in C++ Programming

avatar image

The7thCrest
120 14 20 22

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

1 answer: sort voted first

Hey there, When you supply the GetLifetimeReplicatedProps function you are overriding all the character replication stuff already built in to the engine.

You need to add a call at the start of your function to Super::GetLifetimeReplicatedProps like so:

 void AMonkeyNutsCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
 {
      Super::GetLifetimeReplicatedProps(OutLifetimeProps);
      DOREPLIFETIME(AMonkeyNutsCharacter, Equipped_Ammo_Remaining);
  }

more ▼

answered Nov 18 '14 at 05:15 AM

avatar image

ogrewizardninja
136 2 4 16

avatar image The7thCrest Nov 18 '14 at 05:52 AM

Thanks for that. That worked wonderfully. I feel kinda dumb that that's all it was though. Thanks for the fast response. Wasn't expecting that.

(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