- Home /
WorldToScreenPoint in Update/OnGUI: Bad Performance
Hey all,
I have a simple script which takes the position of the current game object and overlays a 2D texture in its Screen point position.
The issue I am having is it is chewing the main thread! I'm seeing a normal thread time of 12.1ms without the WorldToScreenPoint. With it, it can jump as high as 127ms, but idles around 78ms.
Any suggestion for an alternative?
My Code:
This can be in either Update () or OnGUI () - But OnGUI () results in much worse performance (as expected).
screenPos = Camera.main.WorldToScreenPoint(transform.position);
screenPos.y = Screen.height - screenPos.y;
screenRect = new Rect
(
screenPos.x - (prefabManager.planetGUIWindowTexture.width / 2) - (Camera.main.transform.position.y),
screenPos.y - (Camera.main.transform.position.y),
prefabManager.planetGUIWindowTexture.width,
prefabManager.planetGUIWindowTexture.height
);
Here is the code creating the texture:
void OnGUI () {
GUI.DrawTexture(screenRect, prefabManager.planetGUIWindowTexture);
}
Try updating only when the object is actually seen by the camera and the objects position has changed or the camera has moved.
I have tried that by using IsVisibleFrom but the performance hit is actually less than running that particular script. I tagged all the "planets", grabbed all the objects with that tag and ran them through this script.
Is there a better way of doing this?
BTW, my CPU is an i5 3770k, so I dont think CPU is really the issue (just in case that was next :P)
EDIT: I should note, that I cached the list, and then checked if the planet was a member before drawing the texture (not loaded a list for every planet this was attached to lol)
Did you try only updating if something moved? Unless all your objects or camera are moving every frame, you won't need to be recalculating your screenRect every frame.
I've updated my code in Update () to:
if (child.renderer.IsVisibleFrom(Camera.main)) {
screenPos = Camera.main.WorldToScreenPoint(transform.position);
screenPos.y = Screen.height - screenPos.y;
screenRect = new Rect
(
screenPos.x,
screenPos.y,
prefab$$anonymous$$anager.planetGUIWindowTexture.width,
prefab$$anonymous$$anager.planetGUIWindowTexture.height
);
}
And in OnGUI:
void OnGUI () {
if (child.renderer.IsVisibleFrom(Camera.main)) {
GUI.Label (screenRect, "TEst");
}
}
Still adding at least 10ms to the thread even when no planets are being rendered. Heres a screeny of profiler.
Those are not cheap functions that you have added for checking if on screen. Again, you will not want to be calling that each frame (especially not in both Update and OnGUI on every object).
Answer by Azmodii · Sep 12, 2013 at 03:45 PM
I managed to solve this.
isVisible = child.renderer.IsVisibleFrom(Camera.main);
if (isVisible) {
screenPos = Camera.main.WorldToScreenPoint(transform.position);
screenPos.y = Screen.height - screenPos.y;
screenRect = new Rect
(
screenPos.x,
screenPos.y,
prefabManager.planetGUIWindowTexture.width,
prefabManager.planetGUIWindowTexture.height
);
}
}
Storing the result of IsVisibleFrom in a cached variable solved the extra CPU time. Seems the functions were executing asynchronously and causing leaks.
Your answer
Follow this Question
Related Questions
Erroe when resizing GUITextures in C# file 1 Answer
Is there any easy way to keep buttons inside of box? (c#) 1 Answer
Create a Button Scrollview 0 Answers
C# GUI Destroy or Disable? 1 Answer