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. 

Modifying Environment on Server is Not Replicating to Clients even with NetMulticast

I'm building a co-op game and I'm trying to ensure that there are some tasks in the game that are achievable together. One of those tasks is lighting a fire. However, I'm having problems replicating the fire to the clients.

When a character goes to use an item. The particle effect doesn't spawn on his screen or any of the other clients. alt text

However, it is spawning on what I'm assuming is the server since it's the main window in the Unreal Engine editor.

alt text

//ShooterCharacter.h

 UFUNCTION(reliable, server, WithValidation)
 void UseItem(); 

//ShooterCharacter.cpp

 void AShooterCharacter::UseItem_Implementation()
 {
     if (Role < ROLE_Authority)
     {
         return;
     }
 
     //Code removed that gets the overlapping actors and loops through them

         AUsableItem* const TestPickup = Cast<AUsableItem>(CollectedActors[iCollected]);
             if (TestPickup && !TestPickup->isActive)
         {
             TestPickup->isActive = true;
             TestPickup->UseTheItem();
         }
     }
 }

//HiddenFire.h

 class SHOOTERGAME_API AHiddenFire : public AUsableItem
 .
 .
 .
 
 public:
   virtual void UseTheItem() override;

   UPROPERTY(EditDefaultsOnly, Category = "Particle System")
   UParticleSystem* FireSpawnFX;

//HiddenFire.cpp

 void AHiddenFire::UseTheItem()
 {
       //This code also does not work. Validated its not just particle effects. 
         //FVector NewLocation = this->GetActorLocation() + FVector(0, 0, 300.0f);
         //this->SetActorLocation(NewLocation);
 
         UGameplayStatics::SpawnEmitterAtLocation(this, FireSpawnFX, GetActorLocation(), GetActorRotation());
     }
 }


I have also tried multicast. I set the UseItem to Netmulticast and then removed the if (Role < ROLE_Authority) code from the UseItem_Implementation and it worked on just the client that called it. If I left the if (Role < ROLE_Authority) in there, it was never called at all and spawned on no clients.

Any help would be GREATLY appreciated. Even pointing me to a particular location in an example project would be helpful. Thank you for your time.

Product Version: UE 4.15
Tags:
spawningwindow.jpg (81.4 kB)
mainwindow.jpg (30.2 kB)
more ▼

asked Jul 15 '17 at 02:42 PM in C++ Programming

avatar image

FatBalloon
20 2 4 7

avatar image Vawx Jul 15 '17 at 05:50 PM

You'll need to make sure that it's only clients trying to SpawnEmitterAtLocation, as the server doesn't care about anything graphical.

Secondly, you'll need to make sure that the actor is relicated, so all the clients have a copy of it.

Personally, I would setup a repnotify to show that the AHiddenItem has been "used". The absolute most simple way to do it would be to have a bool replicated variable. Make sure it is the server setting this as true (or false) and then in the OnRep_ function, use the SpawnEmitterAtLocation.

You also have the case of if the hosted game is as a ListenServer, where that would also need to use SpawnEmitterAtLocation, but only in the case of the hosting "client" / listen server. You will only need to do this if you plan on having players hosting games and not only using dedicated servers.

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

1 answer: sort voted first

Here is some code to begin with:

Make sure you have "OnlineSubsystem" in your MYPROJECT.Build.cs, PublicDependencyModuleNames;

[h]

 #pragma once
 
 #include "CoreMinimal.h"
 #include "GameFramework/Actor.h"
 #include "HiddenItem.generated.h"
 
 UCLASS()
 class PLAYGROUND_API AHiddenItem : public AActor
 {
     GENERATED_BODY()
     
 public:    
     AHiddenItem();
     virtual void BeginPlay() override;
     virtual void Tick(float DeltaTime) override;
 
     // Replicated as notify so clients get event when toggled
     UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Unlocked, Category = "Hidden Actor")
     bool bUnlocked;
 
     // The particle system to spawn 
     UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Hidden Actor")
     class UParticleSystem *UnlockedSystemTemplate;
     
     // The collider used to know when a character has come close to the hidden actor
     UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Hidden Actor")
     class UBoxComponent *CollisionBox;
     
     // Scene component to use as a spawn location instead of relying on GetActorLocation( ) + Offset
     UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Hidden Actor")
     class USceneComponent *SpawnLocation;   
     
 private:
     
     // ParticleSystemComponent to keep reference of what SpawnEmitterAtLocation created
     UPROPERTY( )
     class UParticleSystemComponent *UnlockedSystemComponent;
     
     // RepNotify function to know if bUnlocked has been set by server
     UFUNCTION( )
     void OnRep_Unlocked( );
     
     // Function to call to create particle system
     UFUNCTION( )
     void ToggleUnlockedSystem( );
     
     // Overlap bind for CollisionBox
     UFUNCTION( )
     void OnBeginOvlerlap(UPrimitiveComponent *OverlappedComponent, 
                          AActor *OtherActor, 
                          UPrimitiveComponent *OtherComp, 
                          int32 OtherBodyIndex, 
                          bool bFromSweep, 
                          const FHitResult &SweepResult);
     
 };

[.cpp]

 #include "HiddenItem.h"
 
 // Includes for all the types we are using
 #include "UnrealNetwork.h"
 #include "Components/BoxComponent.h"
 #include "Particles/ParticleSystem.h"
 #include "GameFramework/Character.h"
 #include "Particles/ParticleSystemComponent.h"
 #include "Kismet/GameplayStatics.h"
 #include "Components/SceneComponent.h"
 
 AHiddenItem::AHiddenItem()
 {
     // Probably not needed but default
     PrimaryActorTick.bCanEverTick = true;
 
     // Create box and bind overlap / set default size and set as root
     CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("Box Collider"));
     CollisionBox->SetBoxExtent(FVector(128.f, 128.f, 128.f));
     CollisionBox->OnComponentBeginOverlap.AddDynamic(this, &AHiddenItem::OnBeginOvlerlap);
     SetRootComponent(CollisionBox);
     
     // Child component to use as location to create particle system
     SpawnLocation = CreateDefaultSubobject<USceneComponent>(TEXT("Spawn Location"));
     SpawnLocation->SetupAttachment(CollisionBox);
     
     // Replicated so other clients get copy
     bReplicates = true;
 }
 
 void AHiddenItem::BeginPlay()
 {
     Super::BeginPlay();
     
 }
 
 void AHiddenItem::Tick(float DeltaTime)
 {
     Super::Tick(DeltaTime);
 
 }
 
 void AHiddenItem::GetLifetimeReplicatedProps(TArray<FLifetimeProperty> &OutLifetimeProps) const
 { 
     Super::GetLifetimeReplicatedProps(OutLifetimeProps);
     
     // set bUnlocked to replicate
     DOREPLIFETIME(AHiddenItem, bUnlocked); 
 }
 
 void AHiddenItem::OnRep_Unlocked( )
 {
     ToggleUnlockedSystem( );
 }
 
 void AHiddenItem::ToggleUnlockedSystem( )
 {
     UWorld *World = GetWorld( );
     
     // Check for world
     if(World)
     {
         // If bUnlocked got set to true
         if(bUnlocked)
         {
             UnlockedSystemComponent = UGameplayStatics::SpawnEmitterAtLocation(World, UnlockedSystemTemplate,
                                                                                SpawnLocation->GetComponentLocation( ),
                                                                                SpawnLocation->GetComponentRotation( ),
                                                                                true);
         }
         else
         {
             // If bUnlocked got set to false
             if(UnlockedSystemComponent)
             {
                 UnlockedSystemComponent->Deactivate( );
                 UnlockedSystemComponent = nullptr;
             }
         }
     }   
 }
 
 void AHiddenItem::OnBeginOvlerlap(UPrimitiveComponent *OverlappedComponent, 
                                   AActor *OtherActor, 
                                   UPrimitiveComponent *OtherComp, 
                                   int32 OtherBodyIndex, 
                                   bool bFromSweep, 
                                   const FHitResult &SweepResult)
 {
     // Overlap only on authority
     if(Role == ROLE_Authority)
     {
         ACharacter *OverlappingCharacter = Cast<ACharacter>(OtherActor);
         
         // Check if character overlapping
         if(OverlappingCharacter)
         {
             // If not set true to bUnlocked
             if(!bUnlocked)
             {
                 // Set true
                 bUnlocked = true;   
                 
                 // Handle listen server case
                 if(GetNetMode() == ENetMode::NM_ListenServer)
                 {
                     ToggleUnlockedSystem( );  
                 }
             }
         }
     }
 }
more ▼

answered Jul 15 '17 at 06:24 PM

avatar image

Vawx
466 13 11 26

avatar image FatBalloon Jul 16 '17 at 02:15 PM

Thank you very much. This was extremely helpful. I was able to get it working with a few tweaks.

(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