Dynamically setting Projectile Movement Component from Game State variable

Hi all,

There seem to be a number of questions on this topic, but none of them have answers so I am asking again for my specific scenario.

I am using Blueprints for everything so far.

I have a custom Character, a custom GameState (and GameMode), and a custom Projectile.

The Character fires the projectile, its location and rotation vector are calculated in a client-side function, which then calls a server-side function to perform the authoritative spawn of the Projectile.

In order to play test the proejctile, I have added a menu (Widget Blueprint) where any player can update a “Projectile Speed” variable so we can test out different projectile speeds to see what works best. This variable is stored in my GameState and is replicated.

I have tried numerous methods for using this variable to set the initial and Max Speed of the projectile being spawned, and the only way I can get it to work is if I disable Auto Activate on the projectile’s movement component, and the call Activate in Event BeginPlay. However if I do this, the projectile visuals are no longer smooth, the only way the projectile will move smoothly on server and all clients is if Auto Activate remains enabled.

So with Auto Activate enabled I have tried:

  • Setting Initial and Max Speed in Event BeginPlay of the projectile - this does nothing
  • Setting Initial and Max Speed in the Construction graph - this makes a difference but based on the visuals the server seems to be respecting the new Initial and Max Speed values but the clients are not
  • Using a cached copy of the Projectile Speed variable from the GameState but storing it in the Character
  • Using Rep Notify events for the above different set ups.

Nothing works, except for disabling Auto Activate which as I said, seems to cause the projectile to not fire smoothly.

Does anyone have any suggestions or insight here? If I need to move to C++ to make this work I will, but don’t want to go down the path of implementing that if it is going to give the same results.

I really appreciate any advice/help anyone can provide!

Cheers!

First up projectiles in multiplayer should not be replicated. You have each Proxy of the shooter do their own thing. Server should only replicate relevant data. Keep the network footprint as low as possible.

  • Client fires its own local projectile. Simple hit detection, A/V FX etc.
  • RPC the server to shoot.
  • Server determines its own values and fires it for authority. Dmg hit detection etc.
  • Multicast to SIM proxies passing the servers values.
  • Sims fire the shot, A/V FX
  • On Server hit, Multicast the loc, impact normal for SIMS and Owner to apply decals etc.

If you are using dynamic data, store it in a Data Table. The weapon class should grab the data and setup a struct (config).


If you want your projectiles dormant do the following.

  • Disable Collision by default
  • Auto Activate Off
  • Simulation Disabled

Initializing the projectile
Key is updating the root component.


I use Object Pooled projectiles. Each Proxy (Autonomous & Authority) has its own dedicated Pool. I use an Actor Component that’s added at runtime and attached to the character. It spawns N number of projectiles, makes them dormant and attaches them to itself.

Sim Proxies use a global pool that’s created on each client.

When the weapon needs a projectile it requests one from the Bullet Pool component. Production version of this would utilize BP Interface calls vs hard referencing the component.

Bullet Config provides the teleport location (Muzzle), the Aim velocity, Lifespan and Range for the projectile. My projectiles have a set life span that’s based on their max shooting range. The life span value controls no hit shots returning to the pool when they have reached their max range. This reduces wasted resources… shooting clouds etc.

If you go this route you’ll need to bind Event On Projectile Stop. This will give you the means to clear any active timers etc.

When Anything has the projectile “Stop Simulating” We need to clear timers on any running logic. e.g. (lifespan etc).

1 Like