Performance Issue using Vector3.Distance - c#

I am working on a system, which is distributing Commands from a HashSet to a Player. I want to distribute a Command to the Player, who is closest to the Command.
void AssignCommand(Player player, HashSet<Command> commandList) {
//Player assigned;
float min = float.MaxValue;
float dist;
foreach(Command command in commandList) {
dist = Vector3.Distance(command.Position, player.Position);
if(dist < min) {
//check if command already assigned to another player
assigned = command.assigned;
if(assigned != null) {
//reassign when distance is smaller
if(dist < command.Distance(assigned)) {
//mark previously assigned command as unassigned
if(player.activeCommand != null) player.activeCommand.assigned = null;
player.activeCommand = command;
command.assigned = player;
min = dist;
assigned.activeCommand = null;
AssignCommand(assigned, commandList);
}
}
else {
if(player.activeCommand != null) player.activeCommand.assigned = null;
player.activeCommand = command;
command.assigned = player;
min = dist;
}
}
}
}
My problem with this code is that if there are a lot of commands in the HashSet it takes quite a while and the framerate drops from ~60 to about ~30 fps on my machine. This is no surprise, because the Vector3.Distance method is just called for (every player) * (every command), which is way too much. I am looking now for a way to reduce the number of calls somehow to improve the performance. Any ideas here?
I also tried running this code in a different Thread, but I gave up, because this is changing and using too many Thread Unsafe values. My latest try brought me to the check if assigned != null throwing an error for comparing.
I would be very grateful for any hints either improving the overall speed of this code or how to run this in a ThreadPool. If required I can also post my JobClass I created for the Thread attempt.

All the threading solutions and optimizations are fine, but the biggest thing you want to keep in mind (for this and for the future) is: Do not use Vector3.Distance or Vector3.magnitude for this, ever. They are inefficient.
Instead, use Vector3.sqrMagnitude, which is the same thing (for distance comparison), without the sqrt (the most expensive part).
Another optimization is to write your own (square) distance calculation, throwing out the y value if you know you don't care about vertical distances. My distance comparison code was slow, so I tested this pretty carefully and found this is the fastest way (especially if you don't care about vertical positions): (EDIT: this was fastest in 2015. Test yourself for the fastest code on modern Unity.)
tempPosition = enemy.transform.position; // declared outside the loop, but AFAIK that shouldn't make any difference
float xD = targetPosition.x - tempPosition.x;
float yD = targetPosition.y - tempPosition.y; // optional
float zD = targetPosition.z - tempPosition.z;
float dist2 = xD*xD + yD*yD + zD*zD; // or xD*xD + zD*zD
Edit: Another optimization (that you're likely already doing) is to only recalculate when a player has moved. I like this one because it doesn't compromise the data at all.

I wrote my own version of System.Threading.Tasks for unity and added something like this for ordering workload based on distance from the camera.
Essentially whenever a task (or in your case command) was needed it passed off a position and the task to a TaskManager that would then each frame sort the items it had and run through them.
You could probably do the same / similar but instead of passing the command to some sort of CommmandManager like I did with a TaskManager do a lookup on creation and pass the command to the player closest to the point in question.
Most people these days are pulling their scene graphs in to something like a quad tree which should make finding the right player fairly fast then each player would be responsible for executing its own commands.

Okay after hours working on the issue I finally found a solution to improve the performance on the one hand and make it threadable on the other hand. I had problems with the threading, because player is a Unity object.. Instead of using the player object within the task I only get its position in the Start() method. Thus I managed to make it threadable, although it seemed strange to me, that I represented the players by its positions using Vector3 now.
Improving the performance did happen by adding another Dictionary storing the already calculated distances for each player. So when reassigning a player the distance did not need to be recalculated again... I am not sure how much of performance this brought, because I tested it together with the Thread, but at least I got rid of some calls of Distance and am back at stabel 60 fps!
Furthermore I messed something up with the recursions, so that I got up to 100.000 recursions for each player.. This should NOT happen o.O. The fix was easy enough. Simply added a minCommand command, which I set during the foreach and only assign commands and touch the Sets AFTER the foreach.. I bet the code would now run like sugar even without threading...

Related

Unity: Problem spawning objects without overlapping at the same frame [duplicate]

This question already has answers here:
Physics2D.OverlapCircleAll not detecting other gameobjects
(4 answers)
Closed 1 year ago.
I want to spawn some balls (with CircleCollider2d and static Rigidbody2D) with this code. I use a button to see if it works and when I use it everything is ok. But when I use a loop to create a bunch of balls in a single frame, they appear overlapping. I think it is because you have to wait for the physics to be updated, but I need to spawn all balls at the same time. Any ideas or solutions?
It is my first question and I do not speak English well, but I hope I have explained it well. Thanks a lot
public void CreatePointBall()
{
Vector2 pos;
float x, y;
int tries = 0;
do
{
tries++;
x = Random.Range(MIN_POS_X, MAX_POS_X);
y = Random.Range(MIN_POS_Y, MAX_POS_Y);
pos = new Vector2(x, y);
} while (Physics2D.OverlapCircle(pos, radius, LayerMask.GetMask("PointBall")) != null && tries < MAX_TRIES);
if(tries == MAX_TRIES) Debug.Log("MAX TRIES WITHOUT A CORRECT POS");
GameObject go = Instantiate(pointBallPrefab);
go.name = "PointBall";
go.transform.parent = transform;
go.transform.position = pos;
pointBallsList.Add(go);
}
You can try to use Physics.SyncTransforms. Or Physics.Simulate
Actually, it's not a good practice to do this, it can hurt the performance a lot.
If you not need to spawn spheres immediately, in a single frame, you can put your code into coroutine, and after spawning each ball, wait for physics update: yield return new WaitForFixedUpdate();
If all of your spheres has a same scale, you can easily use a math instead of physics. For this, you need just to check the distance from current point to all other points.
It can be expensive, if you have a really large amount of points - so you can optimize it, keeping your points sorted - if your points array is sorted, you only need to compare 2 distances, next larger and previous smaller. But it can be tricky to implement.
Also, if you'll compare many distances, do not use Vector2.magnitude - use Vector2.sqrMagnitude, it's much faster.

Unity Ball Shaking as it moves

I have a ball game object that I am making bounce using explicit physics equations. I tried using unity's physics engine, but It was not exact enough. I am setting the balls position like so:
float dTime = Time.time - timeSinceBounce;
ballPosition.x -= meterOffset / sensitivity;
ballPosition.y = ballInitialPosition.y + GameConstants.Instance.GetBallYVel ()
* dTime - (float)0.5 * GameConstants.Instance.GetGravity () * dTime * dTime; //Yi+Vy*t-0.5(G)(time^2)
ballPosition.z = (-dTime * GameConstants.Instance.GetBallZVel ()
+ ballInitialPosition.z) * startConstant; //Zi + t*Vz
ball.transform.position = ballPosition;
This code runs in the Update() method. When a collision is detected the time and initial position as reset, and this works. Currently the ball bounces properly but shakes when it is moving quickly. The FPS is at 80. I don't think my equations are wrong because it bounces properly there is just a shake. What is the best way to remove the shake? Thank!
Edit 1: I decided to write my own physics because Unity's physics engine had a lot of other components like friction and roll that were making the ball's bounces vary. Also the camera's x and y is fixed the only thing that is changing is the camera's z position. It works a lot better in fixed update
As of asker's request I hereby add all the details I can, even though without seeing the actual, full and complete code along with seeing this "shake" effect it's challenging to give an exact and proper answer. I'll try and do my best though.So let's do this.
1. "Shaking" reason: most probably you set up some kind of animation, along with a forced positioning/rotation/etc and these two codes work against each other. Double-check your AnimatorController and Animator as well as your Mecanim if you have set/configure these (also a good read: "Locomotion").You can also keep the Animator Window open while you are testing from Unity UI, to see who is the tricky guy doing the "shaking" effect for you, and get one step closer to why it happens.If these don't help, start from scratch: Minimize the code you wrote to move the ball, remove every effect, etc and add them back one by one. Sooner or later "shakieness" will come back (if it persist with the cleanest possible code, see above, Animator/Locomotion issue)
2. Think again not rewriting Unity Physics... You mention for example "...physics engine had a lot of other components like friction and roll that were making the ball's bounces vary...".Now, this is something you can turn off. Completely if you want. Easiest way is to set everything to zero on Physics Material (i.e. friction and bouncieness) but if you want Unity to ignore all and every "actual physics" and let you do what you want with your GameObject, tick in the isKinematic property of the Rigidbody. The fun part of it, you'll still collide if and where you want, can AddForce, etc yet neither gravity nor friction or "anything physical" affect you.If you are not comfy with Unity (and you are not it seems), I highly recommend learning about it a bit first as it is a very good and very powerful engine - so don't throw it's features away as they don't work as you initially expected they'll do. For example, Sebastian Lague just started a great beginner series a few weeks ago. The guy is a teacher, his videos are both short, fun and full of information so I can just recommend his channel.
3. As of your code I would make these changes:
public static class GameConstants { //no monobehaviour == can be a "proper, global" singleton!
public static float GetGravity {
get { return [whatever you want]; }
//why not Physics.gravity, using locally when and where it's needed?
}
//etc, add your methods, properties and such
//use this approach if and only IF you access these values application wide!
//otherwise, instead of a """singleton""" logic you just implemented,
//consider adding an empty GameObject to the Scene, name it "GM" and
//attach a "GameManager" script to it, having all the methods and
//properties you'll need Scene-wide! You can also consider
//using PlayerPrefs (see help link below) instead of a global static
//class, so you save memory (but will need to "reach out" for the data)
}
private void FixedUpdate() { //FIXED update as you'll work with physics!
//float dTime = Time.time - timeSinceBounce; //not needed
//positioning like this is not recommended, use AddForce or set direction and velocity instead
ballPosition.x -= meterOffset / sensitivity;
ballPosition.y = ballInitialPosition.y + GameConstants.Instance.GetBallYVel ()
* Time.fixedDeltaTime - 0.5f * GameConstants.Instance.GetGravity () * Time.fixedDeltaTime * Time.fixedDeltaTime; //Yi+Vy*t-0.5(G)(time^2)
ballPosition.z = (-dTime * GameConstants.Instance.GetBallZVel ()
+ ballInitialPosition.z) * startConstant; //Zi + t*Vz
ball.transform.position = ballPosition;
}BUT to be honest,
I would just throw that code away, implement the Bouncing Ball example Unity Tutorials offer, alter it (see point #2) and work my way up from there.
Items not linked but I mentioned in code:
PlayerPrefs, Physics.gravity and Rigidbody.velocity.
Note that 'velocity' is ignoring parts of physics (speeding up, being "dragged", etc) i.e. objects suddenly start moving with the speed you set (This is why Unity5 recommends AddForce instead -linked above-)
It might also come handy you can alter the FixedUpdate() frequency via Time Management, but I'm not sure this is yet needed (i.e. just for bouncing a ball)
I hope this helps and that ball is going to bounce and jump and dance and everything you want it to do ;)
Cheers!

Unity 3d: rigidbody.AddForce(forceDirection.normalized * force) moving objects away from parent and joint

So, this seems to be a strange one (to me). I'm relatively new to Unity, so I'm sure this is me misunderstanding something.
I'm working on a VSEPR tutorial module in unity. VSEPR is the model by which electrons repel each other and form the shape (geometry) of atoms.
I'm simulating this by making (in this case) 4 rods (cylinder primitives) and using rigidbody.AddForce to apply an equal force against all of them. This works beautifully, as long as the force is equal. In the following image you'll see the rods are beautifully equi-distant at 109.47 degrees (actually you can "see" their attached objects, two lone pairs and two electron bonds...the rods are obscured in the atom shell.)
(BTW the atom's shell is just a sphere primitive - painted all pretty.)
HOWEVER, in the real world, the lone pairs actually exert SLIGHTLY more force...so when I add this additional force to the model...instead of just pushing the other electron rods a little farther away, it pushes the ENTIRE 4-bond structure outside the atom's shell.
THE REASON THIS SEEMS ODD IS...two things.
All the rods are children of the shell...so I thought that made them somewhat immobile compared to the shell (I.e. if they moved, the shell would move with them...which would be fine).
I have a ConfiguableJoint holding the rods to the center of the atoms shell ( 0,0,0). The x/y/z-motion is set to fixed. I thought this should keep the rods fairly immutably attached to the 0,0,0 center of the shell...but I guess not.
POINTS OF INTEREST:
The rods only push on each other, by a script attached to one rod adding force to an adjacent rod. they do not AddForce to the atom shell or anything else.
CODE:
void RepulseLike() {
if (control.disableRepulsionForce) { return; } // No force when dragging
//////////////////// DETERMINE IF FORCE APPLIED //////////////////////////////
// Scroll through each Collider that this.BondStick bumps
foreach (Collider found in Physics.OverlapSphere(transform.position, (1f))) {
// Don't repel self
if (found == this.collider) { continue; }
// Check for charged particle
if (found.gameObject.tag.IndexOf("Charge") < 0) { continue; }// No match "charge", not a charged particle
/////////////// APPLY FORCE ///////////////
// F = k(q1*q2/r^2)
// where
// k = Culombs constant which in this instance is represented by repulseChargeFactor
// r = distance
// q1 and q2 are the signed magnitudes of the charges, in this case -1 for electrons and +1 for protons
// Swap from local to global variable for other methods
other = found;
/////////////////////////////////
// Calculate pushPoints for SingleBonds
forceDirection = (other.transform.position - transform.position) * magnetism; //magnetism = 1
// F = k(q1*q2/distance^2), q1*q2 ia always one in this scenario. k is arbitrary in this scenario
force = control.repulseChargeFactor * (1 / (Mathf.Pow(distance, 2)));
found.rigidbody.AddForce(forceDirection.normalized * force);// * Time.fixedDeltaTime);
}//Foreach Collider
}//RepulseLike Method
You may want to use spheres to represent electrons, so apply forces onto them and re-orient(rotate) rods according to this sphere.
I think I found my own answer...unless someone has suggestions for a better way to handle this.
I simply reduced the mass of the electron rods, and increased the mass of the sphere. I'm not sure if this is the "best practices" solution or a kluge...so input still welcomed :-)

Vector direction for gravity in a circular orbit

I am currently working on a project in C# where i play around with planetary gravitation, which i know is a hardcore topic to graps to it's fullest but i like challenges. I've been reading up on Newtons laws and Keplers Laws, but one thing i cannot figure out is how to get the correct gravitational direction.
In my example i only have 2 bodies. A Satellite and a Planet. This is to make is simplify it, so i can grasp it - but my plan is to have multiple objects that dynamically effect each other, and hopefully end up with a somewhat realistic multi-body system.
When you have an orbit, then the satellite has a gravitational force, and that is ofcourse in the direction of the planet, but that direction isn't a constant. To explain my problem better i'll try using an example:
let's say we have a satellite moving at a speed of 50 m/s and accelerates towards the planet at a speed of 10 m/s/s, in a radius of 100 m. (all theoretical numbers) If we then say that the framerate is at 1, then after one second the object will be 50 units forward and 10 units down.
As the satellite moves multiple units in a frame and about 50% of the radius, the gravitational direcion have shifted alot, during this frame, but the applied force have only been "downwards". this creates a big margin of error, especially if the object is moving a big percentage of the radius.
In our example we'd probably needed our graviational direction to be based upon the average between our current position and the position at the end of this frame.
How would one go about calculating this?
I have a basis understanding of trigonometry, but mainly with focus on triangles. Assume i am stupid, because compared to any of you, i probably am.
(I made a previous question but ended up deleting it as it created some hostility and was basicly not that well phrased, and was ALL to general - it wasn't really a specific question. i hope this is better. if not, then please inform me, i am here to learn :) )
Just for reference, this is the function i have right now for movement:
foreach (ExtTerBody OtherObject in UniverseController.CurrentUniverse.ExterTerBodies.Where(x => x != this))
{
double massOther = OtherObject.Mass;
double R = Vector2Math.Distance(Position, OtherObject.Position);
double V = (massOther) / Math.Pow(R,2) * UniverseController.DeltaTime;
Vector2 NonNormTwo = (OtherObject.Position - Position).Normalized() * V;
Vector2 NonNormDir = Velocity + NonNormTwo;
Velocity = NonNormDir;
Position += Velocity * Time.DeltaTime;
}
If i have phrased myself badly, please ask me to rephrase parts - English isn't my native language, and specific subjects can be hard to phrase, when you don't know the correct technical terms. :)
I have a hunch that this is covered in keplers second law, but if it is, then i'm not sure how to use it, as i don't understand his laws to the fullest.
Thank you for your time - it means alot!
(also if anyone see multi mistakes in my function, then please point them out!)
I am currently working on a project in C# where i play around with planetary gravitation
This is a fun way to learn simulation techniques, programming and physics at the same time.
One thing I cannot figure out is how to get the correct gravitational direction.
I assume that you are not trying to simulate relativistic gravitation. The Earth isn't in orbit around the Sun, the Earth is in orbit around where the sun was eight minutes ago. Correcting for the fact that gravitation is not instantaneous can be difficult. (UPDATE: According to commentary this is incorrect. What do I know; I stopped taking physics after second year Newtonian dynamics and have only the vaguest understanding of tensor calculus.)
You'll do best at this early stage to assume that the gravitational force is instantaneous and that planets are points with all their mass at the center. The gravitational force vector is a straight line from one point to another.
Let's say we have a satellite moving at a speed of 50 m/s ... If we then say that the framerate is one frame per second then after one second the object will be 50 units right and 10 units down.
Let's make that more clear. Force is equal to mass times acceleration. You work out the force between the bodies. You know their masses, so you now know the acceleration of each body. Each body has a position and a velocity. The acceleration changes the velocity. The velocity changes the position. So if the particle starts off having a velocity of 50 m/s to the left and 0 m/s down, and then you apply a force that accelerates it by 10 m/s/s down, then we can work out the change to the velocity, and then the change to the position. As you note, at the end of that second the position and the velocity will have both changed by a huge amount compared to their existing magnitudes.
As the satellite moves multiple units in a frame and about 50% of the radius, the gravitational direcion have shifted alot, during this frame, but the applied force have only been "downwards". this creates a big margin of error, especially if the object is moving a big percentage of the radius.
Correct. The problem is that the frame rate is enormously too low to correctly model the interaction you're describing. You need to be running the simulation so that you're looking at tenths, hundredths or thousanths of seconds if the objects are changing direction that rapidly. The size of the time step is usually called the "delta t" of the simulation, and yours is way too large.
For planetary bodies, what you're doing now is like trying to model the earth by simulating its position every few months and assuming it moves in a straight line in the meanwhile. You need to actually simulate its position every few minutes, not every few months.
In our example we'd probably needed our graviational direction to be based upon the average between our current position and the position at the end of this frame.
You could do that but it would be easier to simply decrease the "delta t" for the computation. Then the difference between the directions at the beginning and the end of the frame is much smaller.
Once you've got that sorted out then there are more techniques you can use. For example, you could detect when the position changes too much between frames and go back and redo the computations with a smaller time step. If the positions change hardly at all then increase the time step.
Once you've got that sorted, there are lots of more advanced techniques you can use in physics simulations, but I would start by getting basic time stepping really solid first. The more advanced techniques are essentially variations on your idea of "do a smarter interpolation of the change over the time step" -- you are on the right track here, but you should walk before you run.
I'll start with a technique that is almost as simple as the Euler-Cromer integration you've been using but is markedly more accurate. This is the leapfrog technique. The idea is very simple: position and velocity are kept at half time steps from one another.
The initial state has position and velocity at time t0. To get that half step offset, you'll need a special case for the very first step, where velocity is advanced half a time step using the acceleration at the start of the interval and then position is advanced by a full step. After this first time special case, the code works just like your Euler-Cromer integrator.
In pseudo code, the algorithm looks like
void calculate_accel (orbiting_body_collection, central_body) {
foreach (orbiting_body : orbiting_body_collection) {
delta_pos = central_body.pos - orbiting_body.pos;
orbiting_body.acc =
(central_body.mu / pow(delta_pos.magnitude(),3)) * delta_pos;
}
}
void leapfrog_step (orbiting_body_collection, central_body, delta_t) {
static bool initialized = false;
calculate_accel (orbiting_body_collection, central_body);
if (! initialized) {
initialized = true;
foreach orbiting_body {
orbiting_body.vel += orbiting_body.acc*delta_t/2.0;
orbiting_body.pos += orbiting_body.vel*delta_t;
}
}
else {
foreach orbiting_body {
orbiting_body.vel += orbiting_body.acc*delta_t;
orbiting_body.pos += orbiting_body.vel*delta_t;
}
}
}
Note that I've added acceleration as a field of each orbiting body. This was a temporary step to keep the algorithm similar to yours. Note also that I moved the calculation of acceleration to it's own separate function. That is not a temporary step. It is the first essential step to advancing to even more advanced integration techniques.
The next essential step is to undo that temporary addition of the acceleration. The accelerations properly belong to the integrator, not the body. On the other hand, the calculation of accelerations belongs to the problem space, not the integrator. You might want to add relativistic corrections, or solar radiation pressure, or planet to planet gravitational interactions. The integrator should be unaware of what goes into those accelerations are calculated. The function calculate_accels is a black box called by the integrator.
Different integrators have very different concepts of when accelerations need to be calculated. Some store a history of recent accelerations, some need an additional workspace to compute an average acceleration of some sort. Some do the same with velocities (keep a history, have some velocity workspace). Some more advanced integration techniques use a number of techniques internally, switching from one to another to provide the best balance between accuracy and CPU usage. If you want to simulate the solar system, you need an extremely accurate integrator. (And you need to move far, far away from floats. Even doubles aren't good enough for a high precision solar system integration. With floats, there's not much point going past RK4, and maybe not even leapfrog.)
Properly separating what belongs to whom (the integrator versus the problem space) makes it possible to refine the problem domain (add relativity, etc.) and makes it possible to easily switch integration techniques so you can evaluate one technique versus another.
So i found a solution, it might not be the smartest, but it works, and it's pretty came to mind after reading both Eric's answer and also reading the comment made by marcus, you could say that it's a combination of the two:
This is the new code:
foreach (ExtTerBody OtherObject in UniverseController.CurrentUniverse.ExterTerBodies.Where(x => x != this))
{
double massOther = OtherObject.Mass;
double R = Vector2Math.Distance(Position, OtherObject.Position);
double V = (massOther) / Math.Pow(R,2) * Time.DeltaTime;
float VRmod = (float)Math.Round(V/(R*0.001), 0, MidpointRounding.AwayFromZero);
if(V > R*0.01f)
{
for (int x = 0; x < VRmod; x++)
{
EulerMovement(OtherObject, Time.DeltaTime / VRmod);
}
}
else
EulerMovement(OtherObject, Time.DeltaTime);
}
public void EulerMovement(ExtTerBody OtherObject, float deltaTime)
{
double massOther = OtherObject.Mass;
double R = Vector2Math.Distance(Position, OtherObject.Position);
double V = (massOther) / Math.Pow(R, 2) * deltaTime;
Vector2 NonNormTwo = (OtherObject.Position - Position).Normalized() * V;
Vector2 NonNormDir = Velocity + NonNormTwo;
Velocity = NonNormDir;
//Debug.WriteLine("Velocity=" + Velocity);
Position += Velocity * deltaTime;
}
To explain it:
I came to the conclusion that if the problem was that the satellite had too much velocity in one frame, then why not seperate it into multiple frames? So this is what "it" does now.
When the velocity of the satellite is more than 1% of the current radius, it seperates the calculation into multiple bites, making it more precise.. This will ofcourse lower the framerate when working with high velocities, but it's okay with a project like this.
Different solutions are still very welcome. I might tweak the trigger-amounts, but the most important thing is that it works, then i can worry about making it more smooth!
Thank's everybody that took a look, and everyone who helped be find the conclusion myself! :) It's awesome that people can help like this!

Difference in speed while accessing an array

Is any difference (in speed of my program - execution time) between??
1 st option:
private void particleReInit(int loop)
{
this.particle[loop].active = true;
this.particle[loop].life = 1.0f;
this.particle[loop].fade = 0.3f * (float)(this.random.Next(100)) / 1000.0f + 0.003f;
this.particle[loop].r = colors[this.col][0]; // Select Red Rainbow Color
this.particle[loop].g = colors[this.col][1]; // Select Red Rainbow Color
this.particle[loop].b = colors[this.col][2]; // Select Red Rainbow Color
this.particle[loop].x = 0.0f;
this.particle[loop].y = 0.0f;
this.particle[loop].xi = 10.0f * (this.random.Next(120) - 60.0f);
this.particle[loop].yi = (-50.0f) * (this.random.Next(60)) - (30.0f);
this.particle[loop].xg = 0.0f;
this.particle[loop].yg = 0.8f;
this.particle[loop].size = 0.2f;
this.particle[loop].center = new PointF(particleTextures[0].Width / 2, particleTextures[0].Height / 2);
}
2 nd option:
Particle p = particle[loop];
p.active = true;
p.life = 1.0f;
...
Where Particle particle[] = new Particle[NumberOfParticles]; is just an array of Particles which have some properties like life, position.
I'm doing it in Visual Studio 2010 Like WFA (Windows Form Aplication) and need to enhance performance (we're not able to use OpenGL, so for more particles my program tends to be slow).
I would certainly expect there to be a difference in speed - it's doing more work, after all. Another thread may have changed the contents of the array between statements, which may (or may not) be visible within this thread. If these are properties rather than fields, the property setter could even conceivably change the values in the array within the same thread, which would have to be visible.
Whether the difference in speed is significant or not is a different matter, and one that we can't judge.
More importantly, I'd say that the second form is clearer than the existing code.
In fact, if this is actually meant to be reinitializing the whole element, I'd actually create a new Particle and then assign that to the element:
particle[loop] = new Particle {
active = true,
life = 1f,
// etc
};
... or create a separate method/constructor which created a particle in an appropriate state.
While there is likely to be a very small difference in speed, any difference in speed here is likely going to be negligible. I would use the version that is the easiest to read and maintain.
Personally, I prefer your 2nd option, as I find it much easier to read.
I'm doing it in Visual Studio 2010 Like WFA (Windows Form Aplication) and need to enhance performance (we're not able to use OpenGL .. so for more particles my program tends to be slow).
If your goal is performance, I highly doubt this routine is the core of your problem. You should run this under a profiler. Until you actually measure your performance, and find the real problem, you're just guessing and likely going to spend time optimizing the wrong thing.
It is far more likely that the rendering of the "particles" using GDI+ is likely more of a bottleneck, and changing this routine between your two options will have no impact on the perceived speed.
As an alternative - make Particle a struct, initialize it sequentially in loop and I bet it will be much faster as any of these 2 options.

Categories

Resources