Announcement

Collapse
No announcement yet.

OnRep callback function is not called from server RPC

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

    OnRep callback function is not called from server RPC

    Hey,
    I have the following code:

    Header:
    Code:
     UPROPERTY(ReplicatedUsing = OnRep_Explosion)
     class UParticleSystemComponent* Explosion;
    CPP:
    Code:
    void ABatteryCollectorCharacter::OnRep_Explosion()
    {
     FVector OldLocation = Explosion->OldPosition;
     UParticleSystem* Particle = Explosion->Template;
     UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), Particle, OldLocation, GetActorRotation(), true);
     UE_LOG(LogTemp, Warning, TEXT("This is called on all clients only"))
    }
    //===========================================================
    void ABatteryCollectorCharacter::ServerCollectBattery_Implementation()
    {
     TArray<AActor*> OverlappedActors;
     GetCapsuleComponent()->GetOverlappingActors(OverlappedActors);
    
     if (OverlappedActors.Num() > 0)
     {
      UE_LOG(LogTemp, Warning, TEXT("Overlapping"))
      ABatteryPickUp* Battery = Cast<ABatteryPickUp>(OverlappedActors[0]);
      if (Battery)
      {
       Explosion = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), Battery->ParticleSystem, OverlappedActors[0]->GetActorLocation(), OverlappedActors[0]->GetActorRotation(), true);
       PlayerState->IncreaseNumberOfPickUps();
       Battery->SetLifeSpan(0.1f);
       UE_LOG(LogTemp, Warning, TEXT("Number of pick ups: %d"), PlayerState->GetNumberOfPickUps())
      }
     }
    }
    my problem is when the Server RPC is being called the
    OnRep_Explosion() is not called, I don't know why, my Explosion pointer doesn't seem to be replicated over the network, the ABatteryCollectorCharacter is set to replicate and the GetLifeTimeReplicatedProps is filled with the variable that I want to replicate,
    Please help

    #2
    I am somewhat new to RPCs, so if anyone needs to correct me, please do so. I have found that this type of replication:

    Code:
    UPROPERTY(ReplicatedUsing = OnRep_Explosion)
    Class UParticleSystemComponent* Explosion;
    can be a little unreliable (no multiplayer pun intended). I'll use this for simpler properties like int32 or FString, but not so much on pointers for objects. Yes, technically the memory address could be changing under the hood, but it may not. It's a pointer to a memory address for an object of the size of a UParticleSystemComponent. So, each time you spawn one your emitters, the same address could be getting reused, meaning no change to the pointer's value, meaning no replication taking place on the clients. You'd be better off making a NetMulticast function to fire off on the server and all clients instead.

    In .h

    Code:
    UFUNCTION(NetMulticast, Unreliable)
    void FireExplosion(FVector Location, FRotator Rotation);
    In .cpp

    Code:
    void ABatteryCollectorCharacter::FireExplosion_Implementation(FVector Location, FRotator Rotation)
    {
       UParticleSystem* Particle = Explosion->Template;
       UGamplayStatics::SpawnEmitterAtLocation(GetWorld(), Particle, Location, Rotation, true);
    }
    Then, instead of spawning the emitter on the server and then hoping replication will be called based off a change in the Explosion UParticleSystemComponent pointer, you can just call FireExplosion() and it should be called on both the server and all clients at the same time. I hope this helps.

    And if anyone knows better, please comment. I like to learn from people setting me straight when it's obvious to someone else that I'm wrong.

    Comment


      #3
      Originally posted by Ed.Kaminski View Post
      I am somewhat new to RPCs, so if anyone needs to correct me, please do so. I have found that this type of replication:

      Code:
      UPROPERTY(ReplicatedUsing = OnRep_Explosion)
      Class UParticleSystemComponent* Explosion;
      can be a little unreliable (no multiplayer pun intended). I'll use this for simpler properties like int32 or FString, but not so much on pointers for objects. Yes, technically the memory address could be changing under the hood, but it may not. It's a pointer to a memory address for an object of the size of a UParticleSystemComponent. So, each time you spawn one your emitters, the same address could be getting reused, meaning no change to the pointer's value, meaning no replication taking place on the clients. You'd be better off making a NetMulticast function to fire off on the server and all clients instead.

      In .h

      Code:
      UFUNCTION(NetMulticast, Unreliable)
      void FireExplosion(FVector Location, FRotator Rotation);
      In .cpp

      Code:
      void ABatteryCollectorCharacter::FireExplosion_Implementation(FVector Location, FRotator Rotation)
      {
      UParticleSystem* Particle = Explosion->Template;
      UGamplayStatics::SpawnEmitterAtLocation(GetWorld(), Particle, Location, Rotation, true);
      }
      Then, instead of spawning the emitter on the server and then hoping replication will be called based off a change in the Explosion UParticleSystemComponent pointer, you can just call FireExplosion() and it should be called on both the server and all clients at the same time. I hope this helps.

      And if anyone knows better, please comment. I like to learn from people setting me straight when it's obvious to someone else that I'm wrong.
      Thank you my friend for your reply,
      After some digging in engine code and studying some documents related to Networking I found the following:
      1. If
        Code:
        UObject::IsSupportedForNetworking()
        returns false then the thing you are trying to replicate will not replicate, as a rule anything that is derived from AActor class can be replicated and the UParticleSystemComponent is not an actor and it should be set to replicate for networking using
        Code:
        AActorComponent::SetIsReplicated(true)
        , that way this component can now be replicated.
      2. When you put an RPC call like
        Code:
        ServerExplosion()
        this function will not be called until the original one is finished executing on the calling Client, so if there is some code after this RPC, the code will be executed first and finish everything in the client then it will call the server version, this also means that the RPC is just a way of telling the server :Hey I also want to execute this on the server, and the RPC call just registering this for server call.
      3. The following links from documentations helped a lot for understanding things:
        1. https://docs.unrealengine.com/en-US/...ces/index.html
        2. https://docs.unrealengine.com/en-US/...nts/index.html
      Thanks again

      Comment


        #4
        Oh wow, I didn't know that about component replication. Thank you for sharing your findings and the doc links. it is greatly appreciated. So, after you set replicated to true for the particle system component, did everything work as expected?

        Comment


          #5
          Yes worked, but it is a waste to replicate a pointer to a class, this will reserve lots of bandwidth for nothing, it is better to replicate small things like bools or anything that gives the client the indication of something happened on the server, but UParticleSystemComponent contains lots of things inside this class which will not be good when replicating it, another thing I want to say to clear what replicates mean, replicate means make a copy of this class on all clients but wait at this point it just makes a copy to all clients without any ability to update data to clients until you programmer specify them in the GetLifetimeReplicatedProps() function, the function name is really descriptive it says I want the following properties(Props) to be alive(LifeTime) when copying(Replicated) them to all clients so that clients can see them, so the replication thing must happen on server which means if you want all clients to see this, it must happen on server and if client want to tell others about something happened on his/her machine then this is the best situation to call RPC to make this happen on server and tell others hey something happened on client 1 machine do this to your machines.

          Comment


            #6
            It's important to point out that you are replicating a pointer to an object here, not an object directly. UParticleSystemComponent does not replicate by default, and they can't replicate if you spawn them directly in the world anyway. Even if they did, the internal properties of the component are not replicated either. They are not designed to be used directly over the network.

            Typically, VFX and SFX are something that clients should handle themselves locally. There is rarely ever a valid case for using up bandwidth to do this. If you absolutely need a replicated effect - you should create a replicated actor class, which contains a particle component, and spawn it Server-side.

            You should really study the ShooterGame Template if you haven't already and see how Epic handles this. It might be dated, but it's still important and will save you a lot of trial and error.

            Comment


              #7
              Originally posted by TheJamsh View Post
              It's important to point out that you are replicating a pointer to an object here, not an object directly. UParticleSystemComponent does not replicate by default, and they can't replicate if you spawn them directly in the world anyway. Even if they did, the internal properties of the component are not replicated either. They are not designed to be used directly over the network.

              Typically, VFX and SFX are something that clients should handle themselves locally. There is rarely ever a valid case for using up bandwidth to do this. If you absolutely need a replicated effect - you should create a replicated actor class, which contains a particle component, and spawn it Server-side.

              You should really study the ShooterGame Template if you haven't already and see how Epic handles this. It might be dated, but it's still important and will save you a lot of trial and error.
              Thanks, I noticed that when I tried to replicate the UParticleSystemComponent the internal data are not replicated after some digging and some trials I figured out that this is not the best way to do it, VFX and SFX thing is new to me really thanks for that

              Comment

              Working...
              X