What ways can I optimize a vector magnitude check?

Started by
10 comments, last by Geri 5 years, 10 months ago

So I have hundreds of moving objects that need to check there speed. One of the reasons they need to check there speed is so they don't accelerate into oblivion, as more and more force is added to each object.

At first I was just using the Unity vector3.magnitude. However this is actually very slow; when used hundreds of times.

Next I tried the dot-product check:  vector3.dot(this.transform.foward, ShipBody.velocity) The performance boost was fantastic. However this only measures speed in the forward direction. Resulting in bouncing objects accelerating way past the allowed limit.

 

I am hoping someone else knows a good way for me to check the speed with accuracy, that is fast on the CPU. Or just any magnitude calculations that I can test when I get home later.

 

What if I used  vector3.dot(ShipBody.velocity.normalized, ShipBody.velocity)?

How slow is it to normalize a vector, compared to asking it's magnitude?

Advertisement

sqrt(dot(velocity, velocity)) is speed, so dot(velocity,velocity) is speed_squared, which is useful in many situations.

Normalizing the velocity vector is velocity/speed, or velocity/sqrt(dot(velocity, velocity)).

So in that last example you're doing dot( velocity/sqrt(dot(velocity, velocity)), velocity ).

I'm not sure if this is relevant to what you are doing but quite often I store a unit vector and the magnitude as a separate number in situations that I may need to check the magnitude often.

29 minutes ago, Hodgman said:

So in that last example you're doing dot( velocity/sqrt(dot(velocity, velocity)), velocity ).

Ah, so that looks much slower than just asking the magnitude.

 

31 minutes ago, Hodgman said:

dot(velocity,velocity) is speed_squared

So if I used: vector3.dot(ShipBody.velocity, ShipBody.velocity) I will get my speed squared, is it correct, seems strange to use the velocity twice?

I could live with squared; it's a minor adjustment, I just need to squared my limits.

 

34 minutes ago, Gnollrunner said:

I store a unit vector and the magnitude as a separate number in situations that I may need to check the magnitude often.

Unity can provide them as needed. However because I have so man objects that change there velocity all the time I can't keep it stored and just use a linear growth or something.

Quote

So if I used: vector3.dot(ShipBody.velocity, ShipBody.velocity) I will get my speed squared, is it correct, seems strange to use the velocity twice?

Yes. The dot product is defined as


    public static float Dot (Vector3 lhs, Vector3 rhs)
    {
        return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
    }

And the magnitude as
 


    public float magnitude
    {
        get
        {
            float result = x * x + y * y + z * z;
            return (float)Math.Sqrt(result);
        }
    }

So, as you can see, taking the dot product of the same vector yields the same result as the squared magnitude.
Btw. Unity already provides a property for it's vector types called sqrMagnitude.

Is there no friction in the environment? Usually friction can take care of this problem for you.

Is the force being applied every tick? If the force applied is rare (like a meteor collision) you could maybe just do the check at this event rather than every tick.

Also with Unity with what little I've read, be especially aware that because of the garbage collected environment etc, how you are specifically doing this in code (are you using function calls, hidden costs of some internal functions) may drastically affect the performance. I'm assuming this is all profiled, and you are sure on what is the bottleneck. For instance things that seem cheap (like setting a transform position) can be massively expensive.

A few hundred sqr length calculations shouldn't be a massive hit, in theory, especially if you are using a fixed tick rate rather than doing every frame. There's various other things I might try in c++ but whether they will have any impact in unity I don't know.

In Unity you can just use Vector3.sqrMagnitude - no need for the manual dot-ting.

You probably also want to consider Vector3.clampMagnitude to keep your velocities from getting too high, as opposed to manually doing the comparison and modification yourself.

Finally, since you're working with hundreds of objects and performing very similar operations on them, you should look into the new job system and entity component system that modern versions of Unity have. They're designed to make this specific type of thing a lot quicker.

Have you tried "Carmack's" fast inverse square root? Personally, I haven't but I'd like to hear if you find it faster: 

 

18 minutes ago, turanszkij said:

Have you tried "Carmack's" fast inverse square root? Personally, I haven't but I'd like to hear if you find it faster: 

The 'fast inverse square root' is not so useful these days afaik, as most CPUs have SIMD instruction for inverse square root that are faster and more accurate I believe.

In this case though, if you want to just limit a bunch of velocities, there may be no need for a square root unless the value is over the threshold, unless you want to make it branchless (again profiling is key, and may depend on the data set).

11 hours ago, LifeIsGood said:

Yes. The dot product is defined as

Thank you very much. I can solve math easy on paper so I can use it easily but I am not aware of how it impacts the computer, or what version of the formulas is used on computer that is optimal.

Allso as a none programer I have no idea what is CPU friendly.

 

10 hours ago, lawnjelly said:

Is there no friction in the environment? Usually friction can take care of this problem for you.

It's a space game so I use no friction. However, enabling friction to get around this could be worth it. Will try it soon.

10 hours ago, lawnjelly said:

Is the force being applied every tick?

Yes, both my ships and projectiles have acceleration, so I need to adjust the amount of force every frame. Some projectiles also have other behaviors that need forced adjusted each frame.

10 hours ago, lawnjelly said:

I'm assuming this is all profiled, and you are sure on what is the bottleneck.

Yes, it is all profiled. After my little polygon mistake from last time I switched to a better workflow, now profiling as I go.

One of my aims is to get a lot of moving objects with complex interactions, to makeup for the fact that the game doesn't have a lot of content. So stress testing and profiling is a constant part of the workflow.

 

My problem is that I am running huge amounts of projectiles at a time. So even a small optimization in one gives back a lot of performance. The game is going to have "pinball" feel to it, that will have lots of content flying around and such, so I am doing basic optimizations; nothing drastic.

 

9 hours ago, Kylotan said:

In Unity you can just use Vector3.sqrMagnitude - no need for the manual dot-ting.

You probably also want to consider Vector3.clampMagnitude to keep your velocities from getting too high, as opposed to manually doing the comparison and modification yourself.

So that is where it is! Thanks, I have been looking in the math library this whole time.Vector3.clampMagnitude is new to me, definitely worth a try.

 

9 hours ago, turanszkij said:

Have you tried "Carmack's" fast inverse square root? Personally, I haven't but I'd like to hear if you find it faster: 

Thanks for the link, will add it to the list.

8 hours ago, lawnjelly said:

In this case though, if you want to just limit a bunch of velocities, there may be no need for a square root unless the value is over the threshold, unless you want to make it branchless (again profiling is key, and may depend on the data set).

Yes, looks like I have a busy weekend before me.

 

Thanks for all of the help. I don't know how much of this I will use to directly solve my problem, however I know that all the information here should prove useful as I advance with the game.

This is a huge new jem of information for me. Thanks. :)

This topic is closed to new replies.

Advertisement