- Home /
How can I draw something in screen pixel coordinates in a OnDrawGizmos in MonoBehaviour?
I'd like to draw a rect in screen pixel coordinates in OnDrawGizmos
in a MonoBehaviour
public class Test : MonoBehaviour
{
void OnDrawGizmos()
{
Rect rect = new Rect(10, 10, 150, -100);
UnityEditor.Handles.DrawSolidRectangleWithOutline(rect, Color.black, Color.white);
}
}
Those values in rect
end up being world space coords oriented toward the screen relative to the Transform
of the GameObject
this script is attached to.
I'd like to just draw in pixels on the screen where 0, 0 is the top left of the screen. Do I need to get out the camera and compute those positions relative to the current GameObject's transform or is there an easier way?
Ideally I'd like to be able to use things like GUI.Label it's not working
Answer by greggman · May 14, 2016 at 06:12 PM
So this is NOT the solution I was looking for. The solution I wanted was some way to just tell Unity I want to draw in 2D and start using the GUI
, GUILayout
functions but when I tried to use them I got errors. Maybe someone has an example?
In lieu of that here's some code to compute the correct world coordinates for the desired screen coordinates
Vector3 ScreenToWorld(float x, float y) {
Camera camera = Camera.current;
Vector3 s = camera.WorldToScreenPoint(transform.position);
return camera.ScreenToWorldPoint(new Vector3(x, camera.pixelHeight - y, s.z));
}
Rect ScreenRect(int x, int y, int w, int h) {
Vector3 tl = ScreenToWorld(x, y);
Vector3 br = ScreenToWorld(x + w, y + h);
return new Rect(tl.x, tl.y, br.x - tl.x, br.y - tl.y);
}
So with that this seems to work
public class Test : MonoBehaviour
{
void OnDrawGizmos()
{
Rect rect = ScreenRect(10, 10, 150, 100);
UnityEditor.Handles.DrawSolidRectangleWithOutline(rect, Color.black, Color.white);
}
...
Answer by AuriMoogle · Feb 25 at 08:53 PM
Unity's gizmos can't draw in screen space but you can draw on the camera.NearClipPlane. This will give the impression of drawing on the screen. You just have to take the camera projection type and canvas scale into account. Further explanation and more content can be found at my blog: http://anja-haumann.de/unity-screen-space-gizmos/
using UnityEngine;
public static class ScreenGizmos
{
private const float offset = 0.001f;
/// <summary>
/// Draws a line in screen space between the
/// <paramref name="startPixelPos"/> and the
/// <paramref name="endPixelPos"/>.
/// </summary>
public static void DrawLine(
Canvas canvas,
Camera camera,
Vector3 startPixelPos,
Vector3 endPixelPos)
{
if (camera == null || canvas == null)
return;
Vector3 startWorld = PixelToCameraClipPlane(
camera,
canvas,
startPixelPos);
Vector3 endWorld = PixelToCameraClipPlane(
camera,
canvas,
endPixelPos);
Gizmos.DrawLine(startWorld, endWorld);
}
/// <summary>
/// Converts the <paramref name="screenPos"/> to world space
/// near the <paramref name="camera"/> near clip plane. The
/// z component of the <paramref name="screenPos"/>
/// will be overriden.
/// </summary>
private static Vector3 PixelToCameraClipPlane(
Camera camera,
Canvas canvas,
Vector3 screenPos)
{
// The canvas scale factor affects the
// screen position of all UI elements.
screenPos *= canvas.scaleFactor;
// The z-position defines the distance to the camera
// when using Camera.ScreenToWorldPoint.
screenPos.z = camera.nearClipPlane + offset;
return camera.ScreenToWorldPoint(screenPos);
}
}
Your answer
Follow this Question
Related Questions
popup gui label/image on object click 0 Answers
Unity 4.6B UI Scrollbar Usage 1 Answer
UI elements change position 0 Answers
Can I do a "rotatory" UI like this? 1 Answer