Graphics.DrawTexture drawing in both 2d and 3d?!?

I'm trying to use Graphics.DrawTexture to draw some 2D HUD-style overlays on my scene. (I'm not using GUI.DrawTexture for this because that can only draw the entire texture -- I need to draw a lot of little pieces from a larger texture map.) I'm calling this from OnGUI().

It all works great, except for one thing: it appears that Graphics.DrawTexture is drawing twice. Once, as a 2D object in screen space, exactly as I would expect; and again, as a textured 3D plane that floats out in the environment. If I look in the right direction, there it is, hanging out at some funny angle and upside-down behind the 2D version I intended.

I've gone carefully over my code to see if there is some way I could be rendering the same texture in two different ways, but I don't think so. If I comment out the one Graphics.DrawTexture call, both version disappear. When I put it back in, and turn the camera in the right way to see it, there they both are.

I've searched the other questions here related to Graphics.DrawTexture, but can't find any other references to this problem. I'm using the latest version of Unity (3.2rf4) on a Mac. Any ideas what's going on here?

Graphics.DrawTexture is not a GUI function, Why do you call it from OnGUI? if you do non GUI stuff in OnGUI you have to make sure to do it the right way. OnGUI is called multiple times in one frame. You have to check the current GUIevent

//C# 
void OnGUI()
{
    if (Event.current.type == EventType.Repaint)
    {
        // Do your drawing stuff here
    }
}

//JS
function OnGUI()
{
    if (Event.current.type == EventType.Repaint)
    {
        // Do your drawing stuff here
    }
}

Or maybe move it to OnRenderObject

Take a look at this forum thread:

http://forum.unity3d.com/threads/43277-Graphics.DrawTexture-side-effect

OK, further experimentation, plus a real gem of a tip noticed in an example from this question, has led to the answer.

It appears that OnGUI is called multiple times (as the docs do mention), and the current transform is only set up for overlay drawing when the event type is EventType.Repaint. At other times (for example, when it's EventType.Layout), the transform is something else, and your attempt at GUI drawing will appear out in the world instead.

So for me, simply inserting this line before the drawing function:

if (Event.current.type != EventType.Repaint) return;

solved the problem completely. I would speculate that the various drawing methods in the GUI module (such as GUI.DrawTexture) each contain such a line already, which is why you only notice this issue if you use the lower-level Graphics drawing.

Sorry for answering my own question -- something about displaying my ignorance publicly seems to immediately add 10 points to my IQ. :) Hopefully having this in the archives will help the next person to run into the same issue!