Search Unity

Issue with simulating projectile trajectory in a physics scene 2D

Discussion in 'Physics' started by doganaktay, Aug 28, 2020.

  1. doganaktay

    doganaktay

    Joined:
    Apr 1, 2020
    Posts:
    6
    Hey there,

    Had initially posted something that was the basis of this in the 2D forum but i've made some progress on the issue and would like to directly ask the physics people a more direct question.

    I have a procedurally generated maze in a scene who's walls are 2D box colliders with hard edges. The player will shoot a projectile, but the game is meant to display a deterministic precomputed trajectory for said projectile.

    The method:
    I copy over all the walls and a copy of the projectile that is to be shot, as well as copies of other objects that the projectile can impact into a separate physics scene in order to simulate the actual trajectory of the projectile. Information about it's trajectory (collision points and velocity vectors) are stored in lists which are then used to procedurally generate a mesh for the trajectory in the main scene so that the player can see the path the projectile will take. The trajectory terminates when the projectile hits a collider that is not a wall. In actual gameplay, multiple projectiles can collide with each other, but this is not taken into account when calculating the trajectory, so only one projectile is present in the simulation at any time. The physics scene is simulated with the Time.fixedDeltaTime of the project (which is the default 0.02)

    Now, my issue and question are rather quick and short:
    The simulated projectile trajectory does not always map to the actual trajectory the projectile follows. This divergence becomes more pronounced as the speed of the projectile increases.

    So my question is:
    Is the physics simulation deterministic with a fixed delta time and am I making calculation errors while setting up the simulation or is this expected behavior?

    I have read in Unity API that on the same CPU, same inputs should produce same results, but I wanted to confirm that this should be the case and that my simulated trajectory and the actual one should match up 100% of the time before I did a deep dive on my code to figure out what it is I am miscalculating (if that is indeed the case)

    thanks for your time,
    Dogan
     
  2. diXime

    diXime

    Joined:
    Oct 2, 2018
    Posts:
    162
    Hello Dogan,
    This is indeed a good question. This part:
    makes me think of rounding errors in angles computation (small rounding errors are barely visible at low speeds and start getting noticeable at higher speeds).
    It could also be an issue with the usage of the velocity vector. Maybe normalize it and multiply it by amount before simply multiplying by vector when drawing the trajectory. I'm not absolutely positive about that, but it would be my debugging approach.

    Unity Physics is 100% deterministic, give or take possible (I'm not certain about that one) float rounding errors.
    Havok should be deterministic, but is stateful. To produce twice the exact same result you need the whole state of the system.
    The absence of caching of PhysX may lead to differences, but it seems a little weird to me that simple elastic collisions produce different results. Have you worked out the collision based on the physics material of you walls? Velocity acts greatly in such circumstances. How much does speed affect the result? Tiny changes already produce a discrepancy or do you need to push the speed way up to get such errors?
     
  3. doganaktay

    doganaktay

    Joined:
    Apr 1, 2020
    Posts:
    6
    Hey diXime,

    Thank you for taking the time to give an educated opinion on the matter. It's helped me hone in my approach to the issue.

    After twiddling w my code for a while, I've indeed convinced myself that Unity Physics is deterministic and that I was doing not calculation, but rather timing errors in regards to feeding the direction vector to the simulation object.

    Which brings me to a new question as it will help me get a better grasp of the overall processes in play:

    I'll save the code-posting for another time as I believe my issue can be made sense of in the abstract. The projectile class is the same both for those in game and the simulated ones, they use the same launch method but with different parameters. And here's what I found to be my issue and how I fixed it, however therein lies a question for me that can be enlightening if answered.

    The initial launch force is added to the projectile inside a launch method and not trough triggering fixedUpdate. Therefore, an identical normalized vector with a speed scalar inside an AddForce method was producing different outgoing velocities on the projectile. I could click in the exact same place with the mouse button twice (projectile direction is always from player to mouse) and get different outgoing velocities. The way I have fixed it is simply by taking AddForce out of the equation and setting the projectile's velocity directly before simulation. Now, the trajectory is deterministic and it does not waver.

    But, I do not understand why. For continuous motion I take care to place rigidbody forces inside fixedUpdate, but just for adding an initial launch force, I thought I could add force in a launch method but that failed me.

    Why would this be? How is using AddForce in a public method being called from elsewhere (the simulation class) different from setting the projectile's velocity directly from elsewhere? So much so that setting velocity has (seemingly) fixed my entire issue.

    Cheers
     
  4. diXime

    diXime

    Joined:
    Oct 2, 2018
    Posts:
    162
    Glad i could help a bit.
    Instinctively, I would say that the only difference between a force and a given velocity is mass. So to answer this question
    in one word, the difference is mass.
    You may check if both situations are taking it into account. If it's really low, it explains why the difference wasn't so big at weak impulses, and start getting noticeable at stronger ones. To be honest, I'm not certain it's your issue since clicking twice gives you two different trajectories for the same kind of projectile, so I may be wrong. Do you multiply it by a scalar given by your input? It can happen that the input is a range between 0 and 1 instead of just 1 or 0.

    Now, I don't know how your rigidbody is set up nor the simulation (you've indeed explained quite well both your problem and why posting code would be a little tricky to debug by just looking at it), so I could have also guessed that the force is not reset to 0 once applied to velocity (Force is not conserved, momentum is) but first, you would have really noticed by yourself that your projectile keeps accelerating, and second, since it's not into a loop of some kind as you said, if setting a given velocity to an object gives different results than applying a force on it, the only data that differs in my mind is mass. Now, why would the simulation and the actual motion differs relies on the code.

    There may be some unity specifics coming into play, like the choice of ForceMode. [In your case, I would rather use Impulse (instant force using mass)]. You can test this supposition by setting both the simulation and the actual launch to Acceleration, since this one ignores mass. I wouldn't leave it to acceleration in your game, because it would prevent you to modulate the trajectory with heavier projectiles. EDIT: I forgot you were in 2D. ForceMode2D doesn't have such options. Leave it on impulse unless you find "force" (not instantaneous) more fun.

    Another possibility which I haven't thought of so far is Relative Force, but that last aspect shouldn't have too much effect on a character at rest launching projectiles; if you'd said to me that jumping or falling is causing weird motions, I would have pointed toward that. Although, it doesn't cost much to test or play around with these.

    I hope I could help you get a 'push' forward. :)
     
    Last edited: Sep 1, 2020