setRotation seriously degrades performance?
by Aaron Miller · in Torque Game Builder · 07/07/2009 (10:16 pm) · 9 replies
I'm randomly generating solar systems in script and running into a strange performance problem. TGB handles dynamically generating, moving, mounting and resizing several hundred objects beautifully. However, when I try to rotate them using setRotation or setAngularVelocity, my framerate falls from around 30 with more than 100 objects.
Each solar system is made of several sprites. Each sprite mounts a Trigger for handling gravity and each of these are in turn mounted to a SceneObject. So you might have several SceneObjects mounted to a star with planets mounted to their end to simulate orbital motion; each planet might in turn mount a number of SceneObjects to control the motions of its moons.
Here's the code that slows everything down (called after everything's been set up):
I tried getting rid of the angular velocity on the idea that I was placing too much load on the physics system, but rotating calls still causes the slowdown when total objects exceed about 100. I also disabled gravity triggers because I've heard about their drain, but it's not that. Everything works fine until I rotate.
Any ideas or thoughts on debugging strategies would be appreciated. Thanks!
Each solar system is made of several sprites. Each sprite mounts a Trigger for handling gravity and each of these are in turn mounted to a SceneObject. So you might have several SceneObjects mounted to a star with planets mounted to their end to simulate orbital motion; each planet might in turn mount a number of SceneObjects to control the motions of its moons.
Here's the code that slows everything down (called after everything's been set up):
for(%starCount = 1; %starCount <= StarSystemData.numStarsInSystem; %starCount++)
{
//For each star, get the name to access the orbitals
%sunName = "Star" @ %starCount;
%sunOrbitalCountField = %sunName @ "NumOrbits";
%numOrbits = StarSystemData.getFieldValue(%sunOrbitalCountField);
for(%planetCount = 1; %planetCount <= %numOrbits; %planetCount++)
{
//For each orbital with a planet, rotate to a random position and set in motion
%planetFullName = %sunName @ "Planet" @ %planetCount;
%orbitalObj = %sunName @ "Orbit" @ %planetCount;
%orbitalType = StarSystemData.getFieldValue(%sunName @ "Orbital" @ %planetCount @ "Type");
if(%orbitalType != $Orbital::Type::EmptyOrbit && %orbitalType != $Orbital::Type::AsteroidBelt)
{
%orbitalObj.setRotation(getRandom(0,359));
%orbitalObj.setAngularVelocity(0.01);
//Rotate any moons
%numMoons = StarSystemData.getFieldValue(%planetFullName @ "NumMoons");
for(%moonCount = 1; %moonCount <= %numMoons; %moonCount++)
{
//For each orbital mounted to a planet, rotate to a random position and set in motion
%orbitalObj = %planetFullName @ "Orbit" @ %moonCount;
%orbitalObj.setRotation(getRandom(0,359));
%orbitalObj.setAngularVelocity(0.01);
}
}
}
}I tried getting rid of the angular velocity on the idea that I was placing too much load on the physics system, but rotating calls still causes the slowdown when total objects exceed about 100. I also disabled gravity triggers because I've heard about their drain, but it's not that. Everything works fine until I rotate.
Any ideas or thoughts on debugging strategies would be appreciated. Thanks!
#2
aaron, so you're saying that if you leave that code the same but comment out setRotation() and setAngularVelocity() then your framerate is good ?
07/08/2009 (7:24 am)
but if that entire block is only executed once, eg during setup, that shouldn't matter. if it's run once per frame, then yeah, that would be a problem.aaron, so you're saying that if you leave that code the same but comment out setRotation() and setAngularVelocity() then your framerate is good ?
#3
@Ian: numStarsInSystem * %numOrbits * %numMoons can be as low as 2 (1 star sprite, 1 gravity trigger, no mounted SceneObjects) and so far as high as 300. If the number of objects is below about 100, the code I posted has no problems. Above that and the drop is sharp.
@ Orion: Yes. Again, I can understand such a huge load on physics. But when I commented out setAngularVelocity and left setRotation, I still got drop in frame rate. What's really wacky is that TGB never recovers. The frame rate stays 1 or 2. It's as if setRotation invokes some huge background process, which poking through the source code I didn't see.
I also tried loading all the objects that need a setRotation call into a large list and scheduling a callback function that updated each object once only every 500ms, just to see if it was the loop. But again, after I reach a certain threshold of setRotation calls the frame rate drops.
I'll be changing my system generation code so I can get some more reliable numbers, but at this point I'm baffled.
07/08/2009 (10:41 am)
Thanks for the responses. I should have said the code only runs at level load, not once per frame. I have another loop almost exactly like it above this code, again only called on level load, that instantiates, mounts and resizes all the sprites, triggers and SceneObjects before this loop ever runs and there's no performance drop with it. @Ian: numStarsInSystem * %numOrbits * %numMoons can be as low as 2 (1 star sprite, 1 gravity trigger, no mounted SceneObjects) and so far as high as 300. If the number of objects is below about 100, the code I posted has no problems. Above that and the drop is sharp.
@ Orion: Yes. Again, I can understand such a huge load on physics. But when I commented out setAngularVelocity and left setRotation, I still got drop in frame rate. What's really wacky is that TGB never recovers. The frame rate stays 1 or 2. It's as if setRotation invokes some huge background process, which poking through the source code I didn't see.
I also tried loading all the objects that need a setRotation call into a large list and scheduling a callback function that updated each object once only every 500ms, just to see if it was the loop. But again, after I reach a certain threshold of setRotation calls the frame rate drops.
I'll be changing my system generation code so I can get some more reliable numbers, but at this point I'm baffled.
#4
07/08/2009 (3:02 pm)
very odd.
#5
07/24/2009 (12:48 am)
You may want to look at making a "Behavior Component". There's an example game in iTGB (BehaviorShooter_Component). What it does is allow a hook into the source code (C++) for the heavy lifting of your code. It greatly improves performance if implemented correctly. When using script there are many type conversions that take place which can degrade performance. Things run at a magnitude faster when using C++.
#6
07/25/2009 (2:34 pm)
Thanks Darren. I will look into doing this. Just for the record the speed of the rotation is a factor, as well. Setting setRotation to 10 with a full system gives me trouble, but 0.1 is no problem.
#7
07/25/2009 (2:47 pm)
No idea if this is really the case, but it might fit the data: what happens if you remove physics/collision checks (if they're on)? Could the swept-poly stuff be struggling for some reason?
#8
07/26/2009 (11:48 pm)
From what I've seen if you use a do/while loop using decrements instead of the for loop with increments you'll get a performance boost as well.
#9
Oddly enough, I had already broken up the for loop so that it was called in stages, once for all the planets, then once again for each set of moons for each planet. That seemed to give me a performance boost, so I will try with do/while and see what happens.
Thanks again.
07/29/2009 (2:17 pm)
Tom and Darren just wanted to say thanks for the responses. I don't have collisions/physics enabled, but I do have some pretty huge (100k world units or more in some cases) t2dSceneObjects which I use to mount the planets to, so asking that to rotate may be an issue. Oddly enough, I had already broken up the for loop so that it was called in stages, once for all the planets, then once again for each set of moons for each planet. That seemed to give me a performance boost, so I will try with do/while and see what happens.
Thanks again.
Associate Ian Omroth Hardingham