Tips for mobile games that make heavy use out of triggers/colliders

What you’re storing is a reference to your transform not a copy.

A simple improvement could be reducing the number of times the physics code is run per second… by increasing the physics time step in the Time Manager from 0.02 → 0.05 you will reduce the number of times the physics code is calculated which over that many units should result in a noticeable difference.
Ref: Unity - Manual: Time

Thank you for all of the suggestions thus far. I’ve been busy with other stuff as this project is not my day job, but I have to address a few things…

–Doing a simple distance test doesn’t seem to help. When I have a 80 units on the screen, the frame time goes to 100 ms and beyond. It starts out at around 30. I’m using a second generation iPod Touch. Having said that, if there is anything that I should optimize, it should be my use of triggers. When I use those, the frame time climbs to the 100s when I approach close to 100 units on the screen.

Don’t get me wrong; I could optimize either. But I get the idea that I should use whatever black boxes that are available to me. Especially one that works with the GPU.

I have to say though, I thought that even a few hundred sphere colliders would be smooth. You could do distance square calculation to see if they are close enough, which doesn’t require a square root…

–I guess a hierarchical approach to detect enemies is one option. The thing is, you can never predict how the user will group their ant-like units together. This would mean that I need some scheme to group units together in real time and assign a general to each group, which would require some developing.

–I had a feeling that draw and verts counts were less of a problem. I’ve done some work to enabled automatic batching. Here’s an example where I disable all of the physics:

----------------------------------------
iPhone Unity internal profiler stats:
cpu-player>    min: 75.6   max: 87.0   avg: 79.2
cpu-ogles-drv> min:  1.4   max:  2.6   avg:  1.7
frametime>     min: 84.6   max: 128.0   avg: 90.4
draw-call #>   min:   9    max:   9    avg:   9     | batched:   220
tris #>        min:  2426  max:  2786  avg:  2736   | batched:  7938
verts #>       min:  4772  max:  5492  avg:  5392   | batched:  5300
player-detail> physx: 26.6 animation:  0.0 culling  0.0 skinning:  0.0 batching:  1.7 render:  8.6 fixed-update-count: 4 .. 7
mono-scripts>  update: 41.1   fixedUpdate:  0.0 coroutines:  0.1 
mono-memory>   used heap: 602112 allocated heap: 643072  max number of collections: 0 collection total duration:  0.0

The frame time here is comparable to when slowdowns occur when enemy detection is enabled (via physics or distance tests), BUT the vertex counts are higher here. I should note that the objects on the screen are always moving. The movements can be a bit expensive, since units essentially float and must accelerate and decelerate. They also patrol around certain areas, which require calculations of cos and sin. I realize that these things are expensive; I wanted to trim the fat starting with physics.

Here’s a snapshot of what happens when the enemy detector/trigger stuff is enabled:

----------------------------------------
iPhone Unity internal profiler stats:
cpu-player>    min: 223.7   max: 259.0   avg: 236.5
cpu-ogles-drv> min:  1.5   max:  3.5   avg:  1.8
frametime>     min: 239.4   max: 273.7   avg: 251.3
draw-call #>   min:   9    max:   9    avg:   9     | batched:   243
tris #>        min:  2942  max:  3074  avg:  3005   | batched:  8746
verts #>       min:  5804  max:  6068  avg:  5931   | batched:  5839
player-detail> physx: 108.9 animation:  0.1 culling  0.0 skinning:  0.0 batching:  2.0 render:  8.8 fixed-update-count: 12 .. 14
mono-scripts>  update: 112.8   fixedUpdate:  0.0 coroutines:  0.1 
mono-memory>   used heap: 593920 allocated heap: 643072  max number of collections: 0 collection total duration:  0.0

This is worse. The vert count here is higher than the previous example but one gets the idea that the frame time increases at a much faster pace.

Finally, here’s an example where physics is disabled and units stay still (NO idling or patrolling movements) unless they AI sends them to fight (also having the physics disabled means I can’t select units to do anything, so the AI does all of the movements):

----------------------------------------
iPhone Unity internal profiler stats:
cpu-player>    min: 41.1   max: 61.6   avg: 49.0
cpu-ogles-drv> min:  2.0   max:  4.5   avg:  2.5
frametime>     min: 51.5   max: 71.5   avg: 58.8
draw-call #>   min:   8    max:   8    avg:   8     | batched:   364
tris #>        min:  4430  max:  4466  avg:  4451   | batched: 13120
verts #>       min:  8780  max:  8852  avg:  8823   | batched:  8755
player-detail> physx: 11.0 animation:  0.0 culling  0.0 skinning:  0.0 batching:  3.1 render: 11.4 fixed-update-count: 2 .. 4
mono-scripts>  update: 19.6   fixedUpdate:  0.0 coroutines:  0.0 
mono-memory>   used heap: 790528 allocated heap: 860160  max number of collections: 1 collection total duration: 16.2

Which makes the units themselves look dead unless they are moved. So there is a lot of fat here. To summarize here’s ordering of the slowest version of the game to fastest:
3. Moving (idling) and patrolling units, enemy detection enabled.
2. Moving (idling) and patrolling units, enemy detection disabled.

  1. Moving when requested only, enemy detection disabled.

Tomorrow I guess I can describe how each unit chases enemies using triggers (it’s actually fairly simple) but it’s getting late right.

–I will try testing with the physics time step stuff. I guess it would help to optimize it as soon as possible and use the time step stuff as a next step?

So I’ve realized that this post is not in the iOS forum even though I’m talking about that topic. Should it be moved?

Anyway, I wanted to let you know how I handle the collisions. Each unit has two colliders: a small one that is close to the size of the fighter (sphere collider with radius of 0.5), and a bigger one that is much bigger and allows it to detect enemies (sphere collider with radius of 2.5).

The smaller collider is with the parent object, along with a kinematic rigid body. The larger one is in a child object along with kinematic rigid body. The larger one, which is the detector, is marked as a trigger and has a script with OnTriggerEnter and OnTriggerExit functions defined. I have a dictionary that keeps track of enemy objects that enter and exit the trigger.

The reason for the dictionary is this; if an enemy leaves the trigger zone, but there are other enemies still around, the unit should chase the next available enemy.

In this script’s update function (called from another script, which I use since apparently the MonoBehaviour inherited Update() function is expensive), I check to see if the unit is not chasing something and if there are items to chase in our dictionary. If so, the item chases the first object in the dictionary that is available.

Anyway, I realize that having a dictionary per object is expensive but each object should have some kind of autonomy.

Are you looking for a way to maintain the memory efficiency regardless to the number of colliders used or not?

late to the party but the ideal system for this is Quick Tip: Use Quadtrees to Detect Likely Collisions in 2D Space | Envato Tuts+

With precalculated buckets that only get updated. Ensure that there’s a fixed bucket size of references you can use - reference the object index or script for quick lookup and no garbage.