OnRepNotify doesn't work!

Hello.

I have a projectile class and I need to let the CLIENTS know whenever an Explosive Projectile explodes.

To do this, I decided to use a RepNotify variable bExploded and a OnRep_Exploded function

Here is the code:

.H

UPROPERTY(Transient, ReplicatedUsing = OnRep_Exploded)
	bool bExploded;

UFUNCTION()
	void OnRep_Exploded();

.CPP

void AProjectile::Explode(const FHitResult& HitResult)
{
	
	const FVector NudgedImpactLocation = HitResult.ImpactPoint + HitResult.ImpactNormal * 10.0f;

	if (ExplosionParticle)
	{
		FTransform const SpawnTransform(HitResult.ImpactNormal.Rotation(), NudgedImpactLocation);
		AExplosionEffect* const EffectActor = GetWorld()->SpawnActorDeferred<AExplosionEffect>(ExplosionParticle, SpawnTransform);

		if (EffectActor)
		{
			EffectActor->SurfaceHit = HitResult;
			UGameplayStatics::FinishSpawningActor(EffectActor, SpawnTransform);
		}
	}
        
        // THE OnRepNotify VARIABLE HERE!
	bExploded = true;
}

void AProjectile::OnRep_Exploded()
{
        // DEBUG MESSAGE FOR TEST PURPOSES
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("OnRep_Exploded()!")));

	FVector ProjDirection = GetActorForwardVector();

	const FVector StartTrace = GetActorLocation() - ProjDirection * 200;
	const FVector EndTrace = GetActorLocation() + ProjDirection * 150;
	FHitResult Impact;

	if (!GetWorld()->LineTraceSingleByChannel(Impact, StartTrace, EndTrace, COLLISION_WEAPON, FCollisionQueryParams(TEXT("ProjClient"), true, Instigator)))
	{
		Impact.ImpactPoint = GetActorLocation();
		Impact.ImpactNormal = -ProjDirection;
	}

	Explode(Impact);
}

The problem is that the function OnRep_Exploded doesn’t seem to be fired, since the DebugMessage inside of it doesn’t get displayed!!!

Any ideas?

Yes. I destroy the Actor after the Explode() function.
In fact, not destroying the Actor made that work!

Ok but… I actually need to destroy it.

ps: oh thanks anyway, you made me figured out what I had been trying to understand for hours!

Is the AProjectile destroyed after the Explode call?
If the actor is destroyed, I don’t think the variable will be replicated. Instead, server will tell client to destroy the actor.
If you destroy the actor, try not destroying it and see if OnRep works then.

Thanks! Yes, I already tried before with a NetMulticast function and it worked. But I wanted to understand why the OnRepNotify didn’t work.

Thanks!

You probably destroy the AProjectile after Explode is executed. In that case, further replication is not performed, the server tells the client to destroy its copy of the actor and that is all.

Potential alternatives:

  • Spawn the effect in a multicast RPC
  • Make the AExplosionEffect actor replicated
  • Do not destroy the AProjectile immediately, but destroy it on a timer after 1s
  • Spawn the effect in AProjectile::EndPlay

I had a similar problem and I solved it by replicating explosions on a multicast RPC on the GameState. This makes the explosion position exact (because if you do it on EndPlay, the destroyed actor will not have its last position update).

I don’t know which solution is best in terms of performance though.