Projectile Spawns Rotated Wrong for Only 1 Frame, Then Corrects Itself

Update: With John’s help I have now succeeded in resolving this issue entirely, meaning no initial frame of incorrectness due to the bRotationFollowsVelocity and the bouncing of projectile still works correctly

Solution I used is to initially set the RotationFollowVelocity to false, and then set it to true on a timer via the local postinit component

so it runs on both client and server automatically and independently (no chance of server calling this too early)

AVictoryProjectile::AVictoryProjectile(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
  MovementComp->bRotationFollowsVelocity = false;
}
void AVictoryProjectile::CorrectRotationFollowVelocity()
{
	MovementComp->bRotationFollowsVelocity = true;
}
void AVictoryProjectile::PostInitializeComponents()
{
	Super::PostInitializeComponents();
	
	//correct rot follow vel
	GetWorldTimerManager().SetTimer(this, 
		&AVictoryProjectile::CorrectRotationFollowVelocity, 
		0.1,
		false
	);
}


Dear Friends at Epic,

I was instructed to make this a new bug report :slight_smile:

One Interesting Replication Issue I Cant Solve

When a projectile is initially spawned, it faces wrong direction, but on the next frame ( I know its one frame cause it was really hard to get this screen shot) the projectile corrects it orientation.

the odd thing, is that on the listen server (top left) the projectile shows up correctly. And this issue only occurs in multiplayer context. Single player is always correct.

so its some sort of initial replication issue, but I dont know how to fix it :slight_smile:


Entire Source and Game On Drop Box

My entire game and code are on drop box right now in Nathan Lyer/VictoryGameMultiplayerTest, if you want to check out this issue in depth. However you might want to run a multiplayer game via 127.0.0.1 as Alexander reported issues with other multiplayer setups.

I spawn the projectile from Private/Character/VictoryDragonHumanCharacter.cpp Line 192

AVictoryDragonHuman::ServerFireProjectile_Implementation

Projectile class is VictoryProjectile

//SERVER
void AVictoryDragonHuman::ServerFireProjectile_Implementation(
	FVector_NetQuantize10  Origin, 
	FVector_NetQuantizeNormal ShootDir)
{
	//no current projectile class to spawn?
	if(!CurrentVictoryProjectileBP) return;
	//~~~~~~~~~~~~~~~~~~~~~~
	
	
	//Spawninfo
	FActorSpawnParameters SpawnInfo;
		
	//SpawnInfo.bNoCollisionFail = true;
	SpawnInfo.Owner = this;
	SpawnInfo.Instigator = this;
	//spawn creature
	AVictoryProjectile* Projectile = 
		GetWorld()->SpawnActor(
			CurrentVictoryProjectileBP, 
			Origin, 
			ShootDir.Rotation(),
			SpawnInfo 
		);
	
	if(Projectile) Projectile->InitVelocity(ShootDir);
}

:slight_smile:

Quick question: when you see this issue, are you Client, Server, or does it not matter?

Sorry I missed your comment :slight_smile:

The issue only occurs for the client, the listen server is fine :slight_smile:

and it never ever shows up in single player :slight_smile:

and

its only for 1 single frame on the client, but it is quite glaringly obvious for that 1 frame :slight_smile:

Well, unfortunately if it’s not simulating, then it’s probably not what I thought it was. Simulating doesn’t control whether it replicates or not. It just means it does something different with how it replicates positions internally. I was actually hoping it was simulating in your case :frowning:

Does your repro happen in the shooter example?

By the way I am happy to be the recipient of your first answers John :slight_smile:

Thanks for the help!

It’s not very easy to tell in the shootergame example, because the projectile rocket is very circular

its only obvious in my case because of the elongated mesh particle im using :slight_smile:

Do you think you could test shootergame on your side with an obviously elongated mesh particle like the editor tube and see if you see the issue?

it only shows up on the client machine, even when locally hosting

:slight_smile:

I’d test myself right now but I’m hosting the shootergame stress test and I cant change the code to make sure connections work :slight_smile:

Rama

I’ll look into either replacing the mesh or inspecting the positions at spawn and check to see if the rotation is wrong.

Thanks John!

Again it’s only for 1 single frame, which is what makes the issue quite puzzling, but its too glaringly obvious gameplay-wise to just ignore and I dont know how to fix it :slight_smile:

Rama

Actually, can you set bRotationFollowsVelocity to false? That could also be the problem. The velocity may be wrong on spawn, which would set its rotation to be wrong as well.

I did so, thanks for the idea!

but I cant test in local hosting game because my shootergame instance for the stress test is using the port :slight_smile:

I will let you know soon as I can though :slight_smile:

Rama

wooohoooo!

Thank you John!

setting

bRotationFollowsVelocity = false;

to false solved my problem!

Now the projectile is always correct even on first frame!

yaay!

By the way,

this does mean though that bounces do not look correct, as the rotation doesnt change on bounces

So I am going to implement a timer that is triggered in constructor/post init to set the bRotationFollowsVelocity to true, shortly after spawn

hopefully the innerworkings of this can be addressed so this step is not necessary

but thanks again John, now solutions are possible since we know the issue!

Rama

Can you put a quick check inside ServerFireProjectile_Implementation:

        UPrimitiveComponent* RootPrimComp = Cast(Projectile->GetRootComponent());
        bool bIsSimulating = RootPrimComp && RootPrimComp->IsSimulatingPhysics(); 

And check to see if bIsSimulating is true?

Woo hoo you found it!

Thanks for your help John!

The projectile root component is NOT simulating, neither in single player, listen, or on client do I get a report of anything but NOT simulated


So I guess the reason the projectile looks right after a single frame is because the velocity, which IS replicating, takes over the orientation of the projectile.

MovementComp->bRotationFollowsVelocity = true;

I copied over and modified my projectile class from the shootergame example,

what do I need to do to make the root component replicate?

Here’s the code I ran:

//Spawninfo
	FActorSpawnParameters SpawnInfo;
		
	//SpawnInfo.bNoCollisionFail = true;
	SpawnInfo.Owner = this;
	SpawnInfo.Instigator = this;
	//spawn creature
	AVictoryProjectile* Projectile = 
		GetWorld()->SpawnActor(
			CurrentVictoryProjectileBP, 
			Origin, 
			ShootDir.Rotation(),
			SpawnInfo 
		);
	
	if(Projectile) Projectile->InitVelocity(ShootDir);
		
	//show effects
		//rep
	DoFireCurrentPower = !DoFireCurrentPower;
		//server
	OnRep_FireCurrentPower();
	
	//~~~~~~~~~~~~~~~~~
	//testing
	if(!Projectile) return;
	if (!VictoryPC) return;
	
	MostRecentProjectile = Projectile;
	
	UPrimitiveComponent* RootPrimComp = 
		Cast(Projectile->GetRootComponent());
	bool bIsSimulating = RootPrimComp && RootPrimComp->IsSimulatingPhysics();
	
	//server side reporting this
	if (bIsSimulating) 
	{
		VictoryPC->Optimize("Yes Root Comp is simulating!");
	}
	else
	{
		VictoryPC->Optimize("NO Root Comp is NOT simulating!");
	}