I’m having some trouble with a first person setup when it comes to spawning projectiles. As the name implies those are gameobjects with a collider that tests against enemies and terrain. I’ve been using a pooling system and it works out fine, but I’m having some issues with getting projectiles to spawn when the player is moving.
I’m using a simple worldspace position & rotation combination to set the spawn location. I’m using the camera (which is a child of the controller) to calculate those values. Works fine but when the player moves, especially when he moves fast, the projectiles spawn a little to the side, front or rear. I’m guessing it has something to do with Update cycles but moving the code to FixedUpdate or LateUpdate doesn’t seem to help.
Projectiles move using a speed value (read: bullets) or by being physics objects to which force is added (read: grenades). Do I need to calculate where the player would be next frame? I’m guessing this is a common issue for anyone starting out with FPS mechanics so I think I’m not seeing something that should obvious.
If anyone could nudge me in the right direction that would be appreciated.
The basic idea of your description is right. Spawn the projectile at the location of the player… or gun… or barrel exit - whereever desired - facing the right direction and giving it some forwards velocity.
If it spawns offset then either the position you are putting it on is not what you think it should be, or your character moves faster than the bullet in some cases, which might cause the bullet to be behind the player a frame afterwards.
Without seeing the code i dont think i can provide further help. There can be tons of possible explanations, from the above, to parenting problems, an incomplete reset function for getting things out of your pool, or …, or, …
@Yoreki Yeah, I figured people would ask for the code but that’s a lot of code divided over a lot of classes (FirstPersonController, WeaponSystem, PoolSystem etc). So far the WeaponController did it’s thing independently from the FirstPersonController, and I’ve tried moving the code into the FirstPersonController to make sure it got executed after the Move() method on the CharacterController has run. It did not help, alas.
Question though:
What do you mean by an incomplete reset function for getting things out of your pool? The projectiles all make a callback to the PoolSystem after their lifetime has run out or when they hit a surface. This callback simply makes the GameObjects inactive and puts them back in the queue. When they are activated they are moved to the proper spot / direction and their Update method / physics properties take it from there. If the queue is empty, the request to activate a projectile simply fails.
Is there a known parenting issue that comes up often? So far I’ve just been using the camera itself, with the idea that I’ll replace it with a “gunpoint” point or offset later on.
A projectile spawned inside an Update() won’t get an Update or FixedUpdate called on the same frame it’s created. This will be more obvious if you’re using FixedUpdate instead of Update because of the tick rates. You could try manually ticking it one frame so it’s more “in sync” on the frame you shoot:
For bullets this is likely all you have to do. But imagine you had more complex objects pooled. Like enemies. Or complex projectile based weapons. When you return the object from the pool you usually call some kind of reset function which simulated the object being “newly constructed”. So for example, enemies would need to be full health again, the timer on an unexploded grenade should be reset and so on and so on.
So unless your projectiles have some other complexity, position and possibly velocity are the only things you need to consider when returning a bullet form your pool for now.
Your bullets are parented to the camera? Usually you want things to not be parented to other things that might move, unless those two movements are supposed to be related.
No no… the camera is a child of the CharacterController. The projectiles are spawned at the camera’s world position.
Projectiles are a child of the Pool GameObject they belong to. This object sits idle at (0,0,0) and makes it so I can collapse groups. Would it make a difference if I spawned them with their parent set to null?
I see what you mean by incomplete reset function. These objects are indeed simple enough to not need one.
My guess is you are placing the bullet, then moving the camera or CharacterController. So the bullet is not placed where the camera ends up by the end of the frame, but where the camera was at the end of the previous frame. You could try either spawning the bullet, or repositioning the bullet, in LateUpdate.
Unless you are already moving the camera/controller in LateUpdate. If that is the case I’d move new bullets immediately after the camera/controller movement code is called
Thank you! I thought that was the case indeed, it sure seemed that way and I was “warned” this issue might crop up in FPS games that use projectiles instead of a raycast system. I tried moving the code to LateUpdate but that didn’t seem to help.
While some offset is to be expected, mine was really extreme. The fix turned out to be far simpler… and rather stupid. I use actual 3D models as projectiles. What happens when they spawn at the exact same location as the camera? You look into the object’s interior for the first few frames. Which you won’t notice with default onesided materials due to culling! Adding a firepoint child object to the camera and using that object’s Transform as the worldpace spawn location works a lot better already. My positioning wasn’t off… I was simply not considering how the camera was culling these meshes by looking from within at spawntime.
(I did the LateUpdate thing anyway. Can’t hurt in my opinion. Thanks everyone!)