I was wondering if this class I wrote would be an example of “over optimization”… I am using this to store the velocity of the rigidbody of my main character because I need to use it in a number of different scripts. The main purpose is to avoid recalculating the magnitude since I know it wont change before I reset this variable…I figured this was more convenient than storing the velocity and magnitude as separate fields.
Anyways have a look, maybe you can tell me if the overhead involved here isn’t worth the speed increases. I have heard in many places that you want to avoid fractional exponents (eg: Square-root) as it’s an expensive operation for the CPU.
public class Vector3Fast
{
private Vector3 v3 = Vector3.zero;
private float _magnitude = -1;
private Vector3 _normalized = Vector3.zero;
private float time;
public float magnitude
{
get
{
if (_magnitude == -1)
_magnitude = v3.magnitude;
return _magnitude;
}
}
public Vector3 normalized
{
get
{
if (_normalized == Vector3.zero)
_normalized = v3 / magnitude;
return _normalized;
}
}
//not necessary if you are doing velocity = rigidbody.velocity; which creates a new instance of this class anyways
public void Reset()
{
_magnitude = -1;
_normalized = Vector3.zero;
}
public Vector3Fast(Vector3 v3)
{
this.v3 = v3;
}
public Vector3Fast(float x,float y, float z)
{
v3 = new Vector3(x, y, z);
}
public static implicit operator Vector3(Vector3Fast v)
{
return v.v3;
}
public static implicit operator Vector3Fast(Vector3 v3)
{
return new Vector3Fast(v3);
}
}
Yes that’s true. Actually there’s an error. I forgot to remove the x,y,z variables all together. I just updated it. Anyways the purpose of the class is just to provide me with an easy way of accessing the magnitude / normalized versions of a Vector without having to store them in other fields.
And yes “over-optimization” is an oxymoron, but you get what I mean
I don’t think over-optimization is an oxymoron. Optimization comes at a cost: increased code complexity. Increased code complexity has all sorts of drawbacks, including possible new performance issues (in your case, for example, you overlooked the fact that Vector3 is a struct, which in many cases is much friendlier to the Garbage Collector than your class).
In my view, any optimization that is not a direct response to performance measurements is over-optimization. If you didn’t measure, odds are that your Vector3 class does have any significant effect on your frame rate. Yet you did add a class to your code base that needs maintenance, debugging, etc.
Of course, if you did profile before this change and found that Vector3.magnitude is a major bottleneck in your application, such a class could be a solution.
I would say that unless you use the same velocity value each frame in many scripts then this is probably not worth doing. The main problem with Vector3.magnitude is that it is deceptively simple and so it is easy to use it several times in a script as if it were just a normal variable (in a loop, say). If you refer to the velocity several times in a given frame update function, then save the value to a variable and reuse it. However, it is probably not worth sharing it between scripts unless you have maybe ten or more of them using the velocity each frame. Furthermore, if you really are using that many scripts then a more appropriate optimisation might be to combine some of them together and handle the frame updates in one function (and thereby get to reuse the stored velocity value anyway).
Thank you very much for your response. In a sense I was hoping you would say this. In my case I only have two distinct scripts that need the magnitude every frame, others need it sporadically but not every-frame.
When you say it’s not worth it unless you have a large number (>10) scripts calling it, is that because of the overhead of the engine finding this variable in another object? I have read that in other languages that there is a certain overhead in calling methods/accessing variables from other objects. So accessing character.velocity in a loop would be considerably slower than storing this in an in-scope variable before entering the loop?