- Home /
Fake Shadow Plane: Euler Rotation Optimization
I have a game that has targets that move on a flat surface. I have attached a shadow plane underneath these targets that follows the target via script.
If the target is knocked over, I wanted the shadow to stay on the ground, but continue to match the rotation on the Y axis. (I know it sounds weird, but it looks OK in this situation)
So I needed it to be able to match the rotation of the target that its shadowing on the Y, but not on the X or Z.(When the target is knocked over).
Currently I have a functioning script for the shadow that works like this. (I have updated this code as I left out some code while trying to simplify to the essence of the question. It only added to the confusion. The difference being that the shadow plane is offset towards the fixed camera in the scene.)
public Transform target; Vector3 zeroYPos = new Vector3(0,.06f,0); offset = new Vector3(.2f,0,-.2f); cameraPos = new Vector3(1,transform.position.y, 0);
void Update(){ zeroYPos.x = target.position.x; zeroYPos.z = target.position.z; offset = Vector3.MoveTowards(zeroYPos,cameraPos, .2f); transform.position = zeroYPos - (zeroYPos - offset); transform.rotation = Quaternion.Euler(0, target.transform.rotation.eulerAngles.y, 0);
}
I have heard Euler rotations are very slow so I was hoping to find an alternative way of doing this that might be faster. Any suggestions?
Thanks
On a total side note: I think position = zeroYPos-(zeroYPos-offset)
is identical to position = offset
-- the zeroYPos's cancel out and the sign flips. Or am I crazy?
You're saying that 7-(7-3) = 3? You must be crazy :) Ofc you are right. zeroYPos has no effect at all in this code.
There is also no need to call target.transform.rotataion etc when target already seems to be a transform (you got position from it a few lines above but the declaration isn't there for us to see).
Where did you hear that Euler rotations are 'very slow'?
I'm trying to dig it up. It was in an optimization post somewhere. If they are not. That's great, that confirms that I am not screwing things up too much.
Answer by Statement · Jan 11, 2011 at 06:37 PM
I have heard Euler rotations are very slow so I was hoping to find an alternative way of doing this that might be faster. Any suggestions?
Yeah, suggestions... Profile your code. If you don't have speed issues then it is not much worth checking for faster solutions. Once you realize your code is chewing up considerable time you might want to do something about it.
Here are a couple concrete mini optimizations you can do meanwhile:
// Remove redundant math... transform.position = Vector3.MoveTowards(zeroYPos, cameraPos, 0.2f);
// Remove redundant transform access... transform.rotation = Quaternion.Euler(0, target.rotation.eulerAngles.y, 0);
I made a quick profiling test and noticed a near 10% improvement of the last line of code just by ignoring the access to transform. It should be worth noting that my simple performance tests showed that Quaternion.Euler is about half as fast as copying another quaternion by value. If you are involved with quaternion math, you can't do much better since the whole operation takes about two assigns of time. Of course it could be different on iOS, I don't have access to that. Actually a great deal of the time were spent moving colliders around and not so much with actual quaternion code.
I am surprised your profiling says otherwise. Could you post some figures about time spent in update method? How many objects have this script enabled?
Thanks. I have profiled my code and that is why I am asking this question. If I disable this code or run it as a coroutine, I can improve the performance especially on the low level iOs devices. I was mainly trying to figure out if there is a more elegant way to accomplish this that may not be as expensive.
I don't get how running a co-routine makes any difference. Can you post an example of how it would?
void Start(){ updateFreq = .06f; //Already declared runCoroutines = true; //Already declared startCoroutine(updateShadow());
}
IEnumerator updateShadow(){
while(runCoroutines){
zeroYPos.x = target.position.x;
zeroYPos.z = target.position.z;
offset = Vector3.$$anonymous$$oveTowards(zeroYPos,cameraPos, .2f);
transform.position = zeroYPos - (zeroYPos - offset);
transform.rotation = Quaternion.Euler(0, target.transform.rotation.eulerAngles.y, 0);
yield return new WaitForSeconds(updateFreq);
}
}
@Statement, I noticed you have an interest in the benefits of coroutines. I don't know if you have seen this, but here is a giant thread on why to use them for performance. http://forum.unity3d.com/threads/28973-Coroutines-are-badass?highlight=coroutines+badass
And another, you have to filter through all the other stuff though in both. http://forum.unity3d.com/threads/67856-Coroutines-vs-Update?highlight=coroutines
Answer by BigToe · Jan 11, 2011 at 08:10 PM
This is regards to Statement's questions regarding the Coroutine. Not really an answer, but I didn't know where else to post code...
void Start(){
updateFreq = .06f; //Already declared
runCoroutines = true; //Already declared
startCoroutine(updateShadow());
}
IEnumerator updateShadow(){
while(runCoroutines)
{ zeroYPos.x = target.position.x;
zeroYPos.z = target.position.z; offset = Vector3.MoveTowards(zeroYPos,cameraPos, .2f);
transform.position = zeroYPos - (zeroYPos - offset); transform.rotation = Quaternion.Euler(0, target.transform.rotation.eulerAngles.y, 0);
yield return new WaitForSeconds(updateFreq);
}
}