- Home /
Physics.Simulate taking a long time
A bit of background: My game is an "infinite runner" of sorts where the player races through an infinite world made up of very simple objects - sometimes a few hundred at a time are visible. To get an idea of what's going on with the scene, here's my latest devlog with a playable build:
http://flippfly.com/news/weekly-dev-journal-2-race-the-sun-progress/
The player uses a Character Controller. The buildings you fly past are pre-spawned from prefabs, each of them with a single box collider (one type uses a simple mesh collider,) and re-located during play from a recycled pool to a place out in front of the player.
Now, I'm having an issue where about every-other frame, Physics.Simulate is taking around 4-6 ms, on a "New Ipad." This seems extreme to me, given that the player's ship is the only object in the scene that's actually moving. It would appear on closer inspection that this time corresponds to my calls to my character controller's .move function.
One thing I have done is to disable the colliders on the buildings as I recycle them into my pool, and then just re-enable them when I place them out in front of the player. Before this, I was spiking to more like 8ms on average.
A typical scenario has around 500-600 "static colliders", 1 "active rigidbody" (which I assumed was my Player Controller? I've not placed any rigid bodies in the scene) and one Dynamic Collider (Or maybe this is my player controller?)
Additionally, I've setup the collision layers in the physics settings such that the buildings won't collide with each other and the ground - the only collisions actually allowed are player-building, and player-powerup.
Any suggestions on how to improve this situation, or profile this further? Physics.Simulate seems to be a pretty massive black box... Perhaps there's someway to tweak Unity's spacial partitioning further - or do I need to manually disable collision on objects until the player gets close to them?
Answer by Matt-Downey · Jul 12, 2012 at 01:24 AM
My best guess would be to add a co-routine that is called every 1-5 seconds that sorts through the nearest objects and either enables or disables the collider based on whether or not they are within a certain distance.
This would be a global co-routine, so the script can be separated for organization sake.
Although this is not sorting, I'm sort of referencing tonyd's post here:
http://forum.unity3d.com/threads/136097-sorting-arrays
var thisTrans : Transform;
var allObjects = GameObject .FindObjectsOfType (GameObject );
for (var obj in allObjects)
{
var v3 : Vector3;
var m : float; //magnitudeSquared
v3 = obj.transform.position - thisTrans.position;
m = v3.magnitudeSquared;
if(m > 9000) // if the magnitude is greater than 30 root 10, or approx 95 meters
{
obj.collider.enabled = false;
}
else
{
obj.collider.enabled = true;
}
}
Thanks $$anonymous$$att. I can probably accomplish something like this for my game without sorting, since the player only moves one direction and I know his speed. I will give that a try today.
However I'm really interested in why a scene like this can take 4-6 ms for a single character controller to move. The extents of any single movement are fairly small - the potential number of collisions should be somewhere less than 10 just based on the distribution of where the colliders are. It's almost as if the engine is considering my player's bounds to be 100 times bigger than it is, or there's something more sinister going on here with one of the colliders.
$$anonymous$$aybe physX uses a spatial partitioning that's optimized for a particular scale, and we're an order of magnitude off from that? ($$anonymous$$y player ship is something like 2 units in radius...)
$$anonymous$$ainly I'd like to know how to debug/optimize this kind of thing going forward!
For one thing, try going into the edit-->proj settings-->physics, toggle every unused checkmark in the matrix off, increase the $$anonymous$$imum collision distance to 0.05 or maybe greater, potentially turn down the solver "iteration count" from 6 or 7 to maybe 4 or 5
Before I comment any more, both me and my friend like your game over music.
I remember someone else was using triggers for ai, and the game lagged hardcore if there were a lot of spaceships (i seached for it with unity and google (custom time range and site:answers.unity3d.com) to no avail.
I think the physics system still has to do a lot of calculations using collider.bounds, to find out if anything is nearby, so just being far away isn't enough. No matter what a calculation is going to be made. If you turn off certain colliders, then you shouldn't put a large strain on the computer. What you can probably do is:
//Coroutine (once every 1-5seconds) //for(ss in spaceships) //if ss.transform.z > you.transform.z + 100 //disable collider of ss //else if ss.transform.x > you.transform.x + 100 //dito //else if ss.transform.x < you.transform.x - 100
which would run faster (maybe) since it's literally just addition subtraction and it only needs to make the first check for the majority of the calculations.
it's hard to say, but I'm doing a fps, and i also have a 2unit (2m) character, which isn't ridiculous. Just one more thing you should make sure of: are you sure it isn't the GPU or something? maybe the draw calls aren't getting batched together right?
Do you have a fixed number of obstacles at any given time? because if you do you could put together an array of Vector3 positions and Gameobjects (fixed array, and sort through which is closest using that, Unity says it themselves, you can render a million tris in about a ms using fixed arrays, the only thing is, you'd have a little extra work on your hands.
one last thing to mention, its a stretch, is your vsync enabled or disabled? edit-->proj settings-->quality-->vsync count-->you want "don't sync" (i say this because it is odd that it's VERY! stable in game around 60), can't believe i didn't mention this sooner