Download

Networking Problems C++

Hi everyone, im doing a 3D side scroller game, that mechanics are quite similar to a shooter. I already implemented some classes but till now was just implemented like a single player game. Now im trying to add networking features to my implementations but Im having several problems with the network flow. All that Im trying to do right now is Spawn a projectile to the mouse position. Im trying to separate the network responsabilities giving to client the heavy calculations of convert mouse position every frame to a FRotator that I can use later in a spawner function executed from server. THIS IS THE MAIN PROBLEM, I cant calculate first the FRotaror based on the mouse cursor position on the client, and after that, call a server function passing the result of the client calculations. I tried everything but nothing seems to work. This are the main implementations:


void AConceptCharacter::FireMainAbility( ) {
	if (HasAuthority( )) {
		UE_LOG( YourLog, Warning, TEXT( "FIRE SERVER" ) );
		ClientUseAbility( AbilityInUse, 0 );
	}
	else {
		UE_LOG( YourLog, Warning, TEXT( "FIRE CLIENT" ) );
		ClientUseAbility( AbilityInUse, 0 );
	}
}


void AConceptCharacter::UseAbility( AAbility* Ability, int32 Type ) {

	if (HasAuthority()) {
		UE_LOG( YourLog, Warning, TEXT( "ABILITY SERVER" ) );
	}
	else {
		UE_LOG( YourLog, Warning, TEXT( "ABILITY CLIENT" ) );
	}

	if (Type == 0) {
		Ability->SetMainPressed( true );
		if (!Ability->MainActivated) {
			Ability->MainActivated = true;
			Ability->SetInstigatorOfAbility( this );
			Ability->MainUse( );                                           ///////////////////// IMPORTANT FUNCTION, SEE BELOW
		}
	}
	else if (Type == 1) {
		Ability->SetSecondaryPressed( true );
		if (!Ability->SecondaryActivated) {
			Ability->SecondaryActivated = true;
			Ability->SetInstigatorOfAbility( this );
			Ability->SecondaryUse( );
		}
	}
	else {
		GEngine->AddOnScreenDebugMessage( -1, 5, FColor::Red, TEXT( "Ability type not recognized" ) );
	}
}

void AConceptCharacter::ClientUseAbility_Implementation( AAbility* Ability, int32 Type ) { ////////////////////////////////UFUNCTION(Client,......
	UseAbility( Ability, Type );
}

bool AConceptCharacter::ClientUseAbility_Validate( AAbility* Ability, int32 Type ) {
	return true;
}


void AA_AssaultWeapon::MainUse() {           /////////////////////////// AA_AssaultWeapon is a child class of AAbility
	if (MainClipAmmo == 0) {
		BaseTimeToFireMain = MainReloadTime;
		GetWorldTimerManager().SetTimer( TimerHandleMain, this, &AA_AssaultWeapon::MainUseFinishing, MainReloadTime, false );
		MainClipAmmo = MainClipSize;
	}
	else {
		MainUseBehavior();
	}
}

void AA_AssaultWeapon::MainUseBehavior() {
	FVector StartLocation = (InstigatorOfAbility->GetActorLocation( ) + (InstigatorOfAbility->GetActorForwardVector( ) * 100));

	if (HasAuthority( )) {
		UE_LOG( YourLog, Warning, TEXT( " MAIN SERVER" ) );
	}
	else {
		UE_LOG( YourLog, Warning, TEXT( "MAIN CLIENT" ) );
		CalculateRotToCursorPosition( StartLocation );                                    //////////////////////////////////// UFUNTION(Client,.....)
		SpawnProjectile( StartLocation, RotationOfProjectile );                          //// NOT EXECUTED //////////////////////////////// UFUNCTION(Server.....)      
	}
}


void AA_AssaultWeapon::SpawnProjectile_Implementation( FVector StartLocationParam, FRotator RotationParam ) {

	if (HasAuthority( )) {
		UE_LOG( YourLog, Warning, TEXT( "SPAWN SERVER" ) );
	}
	else {
		UE_LOG( YourLog, Warning, TEXT( "SPAWN CLIENT" ) );
	}
	FActorSpawnParameters SpawnParams;
	SpawnParams.Instigator = Cast<APawn>( InstigatorOfAbility );

	AProjectile* ProjectileSpawned = GetWorld( )->SpawnActor<AProjectile>( MainProjectileClass, StartLocationParam, RotationParam, SpawnParams );

	if (ProjectileSpawned) {
		ProjectileSpawned->SetAbilityWhereProjectileComeFrom( this );

		if (!--MainClipAmmo == 0) {
			BaseTimeToFireMain = MainCadency;
			GetWorldTimerManager( ).SetTimer( TimerHandleMain, this, &AA_AssaultWeapon::MainUseFinishing, MainCadency, false );
		}
		else {
			MainUseFinishing( );
		}
	}
}

The result of execute this is this logs: FIRE CLIENT -> ABILITY CLIENT -> MAIN CLIENT - > CALCULATION CLIENT (not shown method log)

And I understant that the logs should be: FIRE CLIENT -> ABILITY CLIENT -> MAIN CLIENT -> CALCULATION CLIENT (not shown method log) -> SPAWN SERVER

In fact, I implemented something similar in blueprints that works perfectly, but in code… seems imposible. The test blueprint that I implemented is:

dbd4e41df83d18763ad136f0beb8f0b16441743b.png

And this blueprints prints Start Client -> Before Client -> Calculation Client -> After Server (And replicates “test” variable perfectly that was calculated on the client side)

Please, some help here! I cant understant anything… :frowning: Thanks!

Im still with this problem, I guess that is some issue with cross class RPC’s… Help please!

I found the problem! Seems that my Ability actors hadn’t settled the owner actor! Just using SetOwner(this) after spawn them fix all replication problems!