Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Need an efficient way of handling a projectile passing through a large number of objects

Discussion in 'Physics' started by alexobviously, Apr 23, 2020.

  1. alexobviously

    alexobviously

    Joined:
    Feb 23, 2014
    Posts:
    7
    This is in 2D.

    - To keep this simple, let's say there are two classes: unit and projectile. Units have a circle collider, projectiles also have a circle collider but it's small enough that we can just say they're a point.\
    - Units and projectiles have an 'owner' property that corresponds to a player. There are potentially many players and their alliances are flexible, but for the purpose of this post lets say there are two players: red and blue.
    - A projectile should have no effect on units belonging to its owner, but when it hits a unit belonging to the enemy, it is destroyed and causes damage (etc). So a red projectile will pass through red units and hit blue units and vice versa. Projectiles do not interact with each other (physics collision turned off between layers).
    - Projectiles have trigger colliders and units have regular colliders, so I'm using OnTriggerEnter2D to trigger the interactions. All that happens in OnTriggerEnter2D (on the projectile) is: check if other collider is attached to a unit (CompareTag), check owner (compare ints), if it's not the same owner deal damage etc.

    The problem I'm having is that when many red units are bunched up and fire at a blue unit, the game lags into oblivion. According to the profiler, the problem is in Physics2D.FindNewContacts; i.e. there are too many trigger collider interactions, as far as I understand. There are hundreds of projectiles and units, and most of the projectiles pass through several friendly units on their way to their target, so it does kind of make sense. My question is: what is an efficient way to handle this situation?

    Right now I have disabled physics interaction between units and projectiles and am manually range checking every projectile-unit pair (naive approach). It is significantly faster but still slow (obviously). I'd prefer to use the physics engine, but I need to find a way to get it to perform properly. It's a fairly simple scenario, and I feel like it should be quite common. Am I missing something obvious? I've been chatting with some people on the gamedev discord and tried changing some physics settings but nothing has really yielded any significant improvements.

    The strange thing is that what I'm making is a recreation of something I already developed in Processing (Java based programming environment for visual art), and in that I'm doing a similar naive approach scanning through every unit on every projectile every frame and measuring distance, and with far more units than I've tried so far in Unity and that runs orders of magnitude faster.

    Thanks in advance :)
     

    Attached Files:

  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,563
    Make sure you're using the Layer Collision Matrix so stuff you don't need gets quickly culled i.e. projectiles cannot contact projectiles. If you're doing this with script then you're letting the physics system create contacts then you're ignoring them etc. Get the physics system to do this before it has to do more expensive narrowphase detection (shape/shape intersection tests).

    Look at the profiler in the Physics 2D area, it'll show you contacts count which is where you're probably hitting issues if you've got too many things overlapping. 10 overlapping things produces approx 100 contacts so you better ensure you need them otherwise it's a waste.

    You might consider using queries to determine hits such as raycast, circle-cast, generic collider cast etc. Or if these projectiles are not too fast then a simple overlap test which is less expensive.
     
  3. alexobviously

    alexobviously

    Joined:
    Feb 23, 2014
    Posts:
    7
    Thanks for the reply. Yeah I am using the layer collision matrix - projectiles don't interact with other projectiles.
    And yes, you're right - it gets up to like 20-50k contacts.

    So you're saying don't use the physics system to control projectiles? (make them kinematic?) I suppose a circle cast would work. If I circle cast from a projectile that's overlapping/completely contained within a unit, will it return that unit?
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,563
    That's a lot. I don't see how you're getting that many contacts if (presumably) the most numberous thing (projectiles) are not producing contacts. Unless you have 50,000 projectiles then it sounds like you need to double-check your assumptions on what you've got set to contact each other.

    Maybe provide some numbers on things here: Dynamic bodies, how many things you expect to be contacting. Two bodies contacting is a single contact so if you're seeing 50,000 contacts then wow, lots of things happening that sounds like it shouldn't.

    I'm not making any statements like that. All I'm doing is guessing what's going on. Looks like you need to get those contacts under control as something is going seriously wrong before you consider alternate ways.