Shooting from fast moving player, stuck on bug for few months

first, sorry for my bad english and for such long post, just adding as much info as i can, im stuck on this problem for few months now… soooooo…

i know this question were asked and problem raised for hundreds of times by now, but it seems none of solutions from other posts helped me and im kind of having it in unique way, probably… idk…
this video explaining exact issue

i had old version of my game where i moved my spaceship forward with rb.linearVelocity, and rotated ship with rb.rotation = Quaternion.RotateTowards();, moved bullets with rb.AddForce(,ForceMode.VelocityChange).
this way i had no bugs, back then i avoided rb.addForce() because of same bug im having now

i didn’t like spaceship physics when rb.linearVelocity were used to move forward, it felt fake and not fun, it was ok but i want better, so i redo all the code hoping to solve this bug. now i move my ship forward with rb.AddForceAtPosition(ForceMode.Impulse); using single thrust point in the back of spaceship, and rotate it using multiple points simulating real world physics (newtonian) using same rb.AddForceAtPosition(ForceMode.Impulse). basically bunch of small thrusters rotating spaceship, you can see few of them in video, it has particle effect that looks like spray of air in vacuum of space (placeholder graphics)

shooting works by pooling bullets, bullets have trailRenderers as only graphical elements. i add movement force to bullet from weapon script using bulletRb.AddForce() with ForceMode.Impulse,i call function only once where all logic happens - perform bullets pooling tasks and add force to selected bullet, since its vacuum of space, bullet has no drag and just keeps flying on its own afterwards without needing to continuously add force in fixedUpdate()

all works and feels great but as you can see in video, whenever i move forward while turning/steering, my bullets appears to spawn in future position… yeas future, not past, not present, future :flushed_face:
the harder i turn and faster i go forward, the further in future my bullets spawns.

by my testing, it seems this bug happens regardless of method im using for steering, the root cause of problem is adding forward momentum to a ship… just like i said, im using rb.AddForceAtPosition(), but same happens if i do rb.AddForce();, but while using rb.linearVelocity bug disappears together with that very nice feel of physics

///////////////////////////////////////////////////WHAT I TRIED PART////////////////////////////////////////////////////////////

while googling, i found several solutions, i come with some solutions myself, in the end none worked, this is what i tried, at least what i still remember trying:

  • using different unity versions, currently using 6000.0.12f1

  • i tried messing up with bullet and ship rigidbody none/interpolation/exterpolation, tried variations of settings between both rigidbodies.

  • i tried passing ship momentum/inertia to bullet, rb.linearVelocity and rb.angularVelocity, i tested with both at same time and then each individually… even if i have multipliers for inherited linear and angulat velocities, bug persists unfazed. [if lazy no need to read further] ---->
    i did like this (bulletRb.linearVelocity = spaceshipRb.linearVelocity * multiplier) in a shoot function that i call only once where i perform pooling tasks and add all forces in question. how i understand for 1 frame bullet is pushed with addforce + inherits inertia spaceship has at that frame, then in next frames bullet behaves according to all the forces it received at first frame…///////////////////////////////////////////////////////////////////////////
    linearvelocity seemed to work as should, but rb.angularVelocity did weird thing where each bullet shoots straight how it supposed to, but after certain, seemingly constant/fixed time it changes trajectory with sharp turn. the sharpness of turn gets harder/sharper when i increase multiplier
    (bulletRb.angularVelocity = shipRb.angularVelocity * theMultiplier)////////////////////////////////////////
    i might be wrong how rb.velocity works, im not sure if inheriting velocity works as i believe it does, need to do testing… either velocity value gets passed at first frame and then actively effects bullet trajectory (bullets holds that velocity value/energy) for remaining lifetime, or it gets passed at first frame, effects bullet trajectory at that frame only, and at next frame velocity(energy) gets lost.

  • i tried to do spawn position prediction, basically when pooling, instead placing bullet at a gun position, i calculate different position taking in account player, (or gun barrel) movement speed and rotation, then predicting where barrel will be after set number of frames. tried same but reversed, position where barrel was number of frames ago… system failed, i think im just not that good at coding, even chatGpt was useless generating working code for this.

  • i tried to place pooled bullet to gun location with
    -transform.position
    -transform.SetPositionAndRotation()
    -NetworkTransform.Teleport() //game is multiplayer, netcode NGO
    -rb.MovePosition();
    -rb.position();

  • i tried several different attempts writing gun and bullet scripts, i deleted all code and tried again several times. i tried adding force to bullet from bullet script, then i tried to do it from gun script or just simply completely restructure scripts…

  • i though maybe somehow when i enable bullet, set its position to gun position and add force, there is some delay or something and its gets enabled to late or to early… so i attempted to preselect future bullet in advance and set its position with SetPositionAndRotation() to gun position inside Update(), and when player finally fires that preselected bullet, i do typical pooling tasks where one is setting bullet position to gun position for the one last time… then i preselect new next bullet and repeat. this way the bullet im going to shoot next is always attached to gun barrel, yet it did absolutely nothing…

//most of my shooting function code, it only gets executed once

//this one is different attempt to calculate not ship angular velocity, but gun barrel
//Vector3 angularVelocityLinear = Vector3.Cross(rb.angularVelocity, currentGunPos - rb.worldCenterOfMass); 

//this is quick, dirty and lazy patch while transitioning from gun barrel angularvelocity to ship angularvelocity 
 Vector3 angularVelocityLinear = rb.angularVelocity;
 Vector3 angularInherited = angularVelocityLinear * angularVelocityMultiplier;
 Vector3 linearInherited = rb.linearVelocity * linearVelocityMultiplier;


 bulletsList[bulletId].SetActive(true); // first enable
 bulletsList[bulletId].transform.SetPositionAndRotation(currentGunPos, currentGunRot); // then reassign position

 if (inheritAngularVelocity)
 {
     bulletRb.angularVelocity = angularInherited;
 }
 if (inheritLinearVelocity)
 {
     bulletRb.linearVelocity = linearInherited;
 }
 if (scaleMaxSpeedWithPlayer) //i cap bullet max speed, so when i move forward i increase that cap by current ship forward speed
 {
     bulletScript.inheridedforwardVelocity = Vector3.Dot(rb.linearVelocity, rb.transform.forward);
 }
 
 bulletRb.AddForce(bulletsList[bulletId].transform.forward * bulletLaunchForce, ForceMode.Impulse);

while writing this post, i thought for one more solution I haven’t tried it yet, it just hit me, but at this point i doubt it will work, i tried to many times for each to fail :sweat_smile:. im thinking instead moving bullet with rb.AddForce(), move it with different method, maybe with rb.linearVelocity() since it worked when i moved spaceship with it… ??? its late night and i wont be able to write all the new code for bullet tonight, at same time i put to much time and effort writing this post just to toss it out for small hope that tomorrow changing bullet movement method will fix this bug, so i publishing this post anyway, even if tomorrow’s magic will succeed in all the fixing, maybe this post and my experience will be useful for someone else :sweat_smile:

Try pausing playmode when shooting using EditorApplication.isPaused = true;

Then use a debugger or Debug.Log to find out the position of the bullet.

Try to find out if the bullet is initially positioned in the wrong place, or if it’s move there in the next frame. Whether it is an error in your SetPositionAndRotation call or if it’s in subsequent movement code. Then you can narrow down the cause of the error.

Add a Debug.DrawRay (or Gizmos) to see the bullet path ignoring the trail renderer, in case it’s just the trail renderer being behind.

There are a number of common things that could go wrong. Update order could matter, moving the ship then spawning the bullets, not vice versa. Applying the wrong delta time, or not applying it, or applying it incorrectly. FixedUpdate vs Update mismatch. Physics interpolation ie Rigidbody.position differs from transform.position. Flipped sign. A Vector that isn’t normalized. The object hierarchy, and that Rigidbody objects ignore it. World space vs local space mismatch. Just to name a few.

In any case, it’s not a problem to be stuck on for months. This tells me you should look up the general process on how to debug issues. Simplify. Analysis. Form a hypothesis. Test it.

The obvious thing to log and or visualize would be the ships position and the bullets spawn position. How do they relate to each other? What is their relative offset? Does this somehow match some values that you use, for instance the input velocity? If they are close, perhaps you shoot first and then move the ship, causing the offset.

so i fixed it. i will explain why bug happened and how i fixed it, so others could use it for learning, everything i say is based on my observation :sweat_smile: and its not facts, but its rather insterresting…

after using someone suggestion, i debugged bullet frame by frame, pausing editor after each frame, then unpausing manually for that one single frame to see its travel and spawn point. this didn’t helpe all that much-
-when pausing editor after each frame, it were showing me perfect frame with no visual artifacts, probably because as later i theorised, unity rendering engine had enough time to render it with in sync of physics engine.

so my best guess was that physics were run in fixed update which is based on time step, by default 50 times a second, and everything else inside update which is used to render a frame, so in my case more than 50 per second since i had 100+ fps. but it didnt helped even if i set time step and fps to match

Application.targetFrameRate = 60;
 Time.fixedDeltaTime = 1f / 60;
 Time.maximumDeltaTime = 0.05f; 

even if i call void responsible of adding force to a bullet from within Update(), physics will be calculated and will actually happen inside FixedUpdate() time, physics is independent from FPS… it doesn’t matter if you actively adding force to a rigidbody or this rigidbody moving on its own, for example when knocked by other object or when falling because of gravity

problem i had was so visible because my bullets is extremely fast, in 1 or 2 seconds bullet travels 8000+ game units (meters). i need this speed since all other players supposed to see all the bullets across the map + player them selves arent so slow either. so those milliseconds between physics and rendering probably caused this weird rendering artifact

how i fixed it is:

  1. using LateUpdate() as substitute for Update(), happens after fixedUpdate()

  2. using kinematic rigidbody on gun barrel and getting its position with gunbarrelRB.position, then bulletRB.position = gunbarrelRB.position; avoid using transform.position for teleporting an object. rb.posion is realtime position and transform.position is position object was last at frame. its also works with:transform.SetPositionAndRotation(gunRB.position,gunRB.rotation); since we are getting teleport(destination) position from gunbarrel rigidbody and not transform

  3. instead trailrenderer im now using stretched capsule mesh, temporal solution, but works. this solution have other graphical artifacts in my case, but as of now its 100x better than trailRenderer or lineRenderer. trail renderer should work if i set trailrenderer time correctly. as i noticed if time value is to big, trail start point/tail is erased with noticeable delay causing my player to pass it so quickly that it looks like bullet is spawned behind player.

so these 3 reasons individually contributed enough for bullets to artifact and only fixing all 3 solved my issue. leaving any one reason unfixed would introduce same artifacts again. :smiling_face_with_tear:

In that case you don’t really need any traveling objects. Simply use a raycast, and a particle effect / line or trail renderer / shader to show the bullet (trail) visually. You could also do staggered raycasts, like one raycast each FixedUpdate that’s 100 units long and continues to cast from there another 100 units in the next FixedUpdate.

At 100 units per FixedUpdate this raycast bullet would travel 5,000 units in 1s.

This begs the question: anything beyond 1,000 units is almost certainly out of reach, respectively not relevant to the shooter (ignoring snipers for a moment). This begs the question if it wouldn’t make sense to simply raycast once end-to-end in a single swipe. Because whether that bullet takes 0.2s to impact something at 1,000 units distance (which the player maybe can’t even see) or 0.0s makes no real difference for gameplay.

Most games with standard firearms weapons would just do that: raycast once per bullet. We cannot perceive objects traveling at that speed.

Even if it were to matter, you could still simply raycast and merely “tag” the target telling it to “get hit” in 0.775 seconds - calculated as a fraction of distance traveled until impact ie this object would be at 775 units distance given a bullet that travels 1,000 units per second. Now whether that shot might have missed only really matters if the target is also travelling fast, and in PvP multiplayer.

The update order is:

  • FixedUpdate (every fixed timestep)
  • Update (every frame)
  • LateUpdate (every frame)

There may be frames where you only get:

  • Update
  • LateUpdate

And other frames with:

  • FixedUpdate
  • Update
  • LateUpdate

And even frames like this can happen (ie during periods of low framerate):

  • FixedUpdate
  • FixedUpdate
  • FixedUpdate
  • Update
  • LateUpdate

yes its multiplayer pvp game and bullet speed even with 8000 units per second is perceived in my case, the objects in the map is separated with great distance, player can clearly see bullets traveling in other side of the map for 1 or 2 seconds.
this is old version of game as reference for you to understand my use case

current version have diferent spaceship physics, so as i explained in my original post, old method of shooting bullets wasnt working anymore.
anyway as you can see in video if a opponent player shooting near by you, bullets looks like simple flashes of light that still hass sense of movement and direction, but if you are far away from him, you can clearly perceive bullet traveling trough the map. :upside_down_face: