Search Unity

Question Raycast based projectile can't hit moving objects

Discussion in 'Scripting' started by Qriva, May 21, 2023.

  1. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    I wonder if there is some smart solution to the following problem:

    There is projectile based on raycast - custom velocity intergration
    velocity * deltaTime
    then it raycasts forward and moves or stops on hit.
    upload_2023-5-21_19-42-37.png
    It works perfect on static targets, but it fails if object (black square) moves at the same time, because after projectile update, the object might "eat" the projectile and next raycast starts from inside the black square
    (or worst case: behind).
    upload_2023-5-21_19-49-13.png
    The result is obviously no hit as raycast can't detect hit inside colliders. Is there some low performence cost solution to this? Other than checking overlap sphere every frame?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    I assume you are not using the physics system and trying to do your own collision? If you are using physics, enable continuous dynamic collisions and it should Just Work(tm).

    Some other ideas;

    - keep a previous AND a current collider for the black (or the orange) object, chasing it along with a one-frame delay. This would only up your raycast count to 2: either 2 raycasts from 2 orange positions, OR two raycasts against two target colliders.

    You can actually raycast against the two specific colliders directly with Collider.Raycast (or Collider2D.Raycast() ) to further simplify the problem, or use layering to keep the ghost object from interacting with anything else.

    Raycasting, colliders, planes, Plane, etc:

    https://forum.unity.com/threads/hel...s-are-hitting-an-object.1058393/#post-6840296

    https://forum.unity.com/threads/kee...within-the-view-frustrum.936209/#post-6117173

    - another way is forego raycasting and just iterate the "enough" steps between the orange object's move frames, checking with either Overlap() calls or just checking coordinates for closeness. The term "enough" would be approximately one plus the maximum movement magnitude divided by the smaller collider's size.
     
  3. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    Thank you for the input, but I am really not sure I am able to understand this description.
    I am using one raycast per projectile (per update).
    This is custom, job based system using raycast command.
    I can't do this check in job and I want this to work for all colliders, not just 3 selected objects.
    I am not sure I get this one, but tracking all possible colliders on scene in custom system sounds like a lot of coding.
    If there was only one projectile in the game then maybe, but it will be a looot of overlaps for fast moving projectiles and it would be way cheaper to start with single overlap to see if something overlaped the projectiles between updates.
     
  4. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    Maybe I used bad wording, it's not like raycast misses, it is simply unable to register hit from inside the object.
    It does not miss because it's fast, but because you can't update all objects at the same time. In fact, because they are fast it decreases chance to go trough object, slower projectles do miss way more often (it is easier to "eat" it).

    Yes, I can try to check previous frame, but very fast projectiles will create strange results as it can hit something 5 meters behind for example.
    Spherecast has the same problem, it can't register hits inside colliders.
     
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    Keep a hold of it's previous location, so you can do a 'double check' between the previous position and where it is, before it moves again. Ergo, 'if nothing is in front of me, and nothing has entered my previous path, I'm good'.
     
    mopthrow and orionsyndrome like this.
  6. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    If you have perfect control over this you can also manipulate the order of execution.
    Or alternatively use OverlapSphere (not casting) to detect presence of objects.

    I mean the tricky part is this
    Is it at the same time? Try analyzing your problem a bit better.

    I like spiney's solution above, but I'm afraid it won't get you anywhere if the object is moving faster than the projectile.
     
    mopthrow and spiney199 like this.
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    Honestly in such a scenario with moving targets, if you're not explicitly relying on physics, I believe it makes more sense to make the system aware of a point of impact.

    You can't just scan the frame and consider every object as static, no, you need to evaluate the velocity of the target (by computing delta between the frames) and estimate a point of impact. Which is fairly trivial, you just subtract the estimated delta from the raycast hit.

    Now you can leverage your situation better, because when you clearly had an estimation going on, but the conclusion is suddenly "wow the object vanished" you can immediately turn this into a mode of finding the appropriately translated point of impact (by reusing the same delta), and resolve the collision.

    Likewise there is no relevant situation where the object was to vanish but the estimation was very distant, so that's your test: 1) has the previous last recorded target vanished, 2) is the estimated point of impact sufficiently close (to satisfy the principle of getting "eaten" it should be within reach of target's velocity * Time.deltaTIme).
     
    Last edited: May 22, 2023
    MaltsGangfoot likes this.
  8. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    No need for a timer. I don't have time right now to make a mockup, but it's super simple and super efficient, though there are some limitations, namely the distance check assumes a relatively convex shape, and these shapes must not be moving at ludicrous velocities. If these limitations are a problem, then this is a hard physics problem and people have spent a lot of time thinking through and refining physics libraries to solve this, and you still need to juggle dozens of parameters to custom-tailor everything to fit your project.
     
    Kurt-Dekker likes this.
  9. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    This sounds good, but there are two downsides, first one is if projectile moves very fast it might hit object way behind it, because it moved into way, and the Second (and worse) problem - there is no guarantee that the other object (black square) will not "eat" both points what could actually happen if projectile is slow.

    I can't change execution order, I mean "at the same time" was shortcut to say that other object also moves. Everything in unity updates in sequence anyway, so I don't think there is any solution related to changing "order".

    Yeah, actually it looks like I need to check if it's inside anyway, as I found out another problem, what if some longer object "slides in" into path:
    upload_2023-5-22_3-12-21.png
    This scenario is less problematic in my game I think, but it expands the problem. The "early collision check" solution will fail in this scenario, as there is nothing obstructing the path, so I guess I need to first check if point is inside some collider and if it is, then I need to do longer raycast from previous position direction. Actually if I wanted, I could ignore all hits except collider with the same instance ID as the one in sphereOverlap check.

    Does anyone see a better solution?
     
  10. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    You can either change the default execution order in the project settings, or with the similarly named attribute.

    Or you can introduce some top-level manager that runs all these physics jobs, which should allow you to define the order things happen. I've done this approach in a turret defence project, where I wanted each category of entity to update in a certain order to maintain determinism.

    Which can also bring performance benefits too.
     
  11. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    There is one manager that runs job for all projectiles, but I don't understand how execution order can fix anything here. Whatever you do you need to update all rigidbodies at some point and the same thing for projectiles and it does not matter what goes first as you run A-B-A-B-A-B... anyway.
     
  12. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    I mean if you can guarantee all projectiles update before other objects, then you can guarantee that when they check for collisions you are doing so before anything has potentially moved over them.
     
    orionsyndrome likes this.
  13. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    I can guarantee projectile simulation and raycast to be "at the same time" and also that they are updated+raycasted before physics update, but I can't guarantee that nothing moved into them after that (for the next tick), as it is simply not possible to ensure that.
     
  14. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    I believe objects should update before the projectile. This is because you want de facto state of your objects and a projectile to arrive late in that picture.

    In this case your projectile simply wouldn't have this object recorded and would end up being engulfed (but otherwise intact). But this is a very weird fringe example that assumes that objects themselves can hit into your projectiles. No raycasting can save you from that, you need a scene-wide collision checking to resolve many objects hitting each other simultaneously.

    So let's focus on what you're trying to solve -- again, if you need physics, simply use physics, don't reinvent wheels.
     
    spiney199 likes this.
  15. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,860
    Good point.

    In either case, a top level system that lets you flexibly change the order of things on a whim would be useful to get the right - or best possible - behaviour you want.
     
    orionsyndrome likes this.
  16. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,307
    Sorry, but I am really confused by the last part of conversation about update order. I fail to see how this affects the problem in general. I mean obviously execution order changes how things work, but in my scenario it is not product of desync or order, but result of the fact that physics and simulation is processed in steps and every frame (or rather fixed tick) we need to deal with things that happened in the previous one.
    Am I missing something obvious? Or perhaps it comes from the context and different conceptions of the problem?