1

I want to draw line from unityUI. (i dont want to use Line Renderer in unity).

So I figured out the coding below, but my problem is the line sizes are not constant.

public class MyUILineRenderer : Graphic
{
    public Vector2[] pointPos;
    public float[] angles;
    public MyUIGridRenderer gridRenderer;

    public Vector2Int gridSize = new Vector2Int(1, 1);
    public float lineThickness = 0.5f;
    public float width;
    public float height;
    public float unitWidth;
    public float unitHeight;

    public float angleHelp;
    public bool calAngle;

    public Color[] colors;

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        width = rectTransform.rect.width;
        height = rectTransform.rect.height;

        unitWidth = width / (float)gridSize.x;
        unitHeight = height / (float)gridSize.y;
        if (calAngle)
        {
            angles = new float[pointPos.Length];
        }

        if (pointPos.Length < 2)
        {
            return;
        }

        float angle = 0;

        for (int i = 0; i < pointPos.Length; i++)
        {
            Vector2 point = pointPos[i];

            if (i < pointPos.Length - 1)
            {
                if (calAngle)
                {
                    angle = angles[i] = -GetAngle(pointPos[i], pointPos[i + 1]) + angleHelp;
                }
                else
                {
                    angle = angles[i];
                }
            }
            DrawLine(vh, point, angle);
        }

        int count = pointPos.Length * 2 - 2;
        for (int i = 0; i < count; i += 2)
        {
            vh.AddTriangle(i + 0, i + 1, i + 3);
            vh.AddTriangle(i + 0, i + 2, i + 3);
        }
    }

    public float GetAngle(Vector2 currentPos, Vector2 targetPos) {
        return (float)(Mathf.Atan2(targetPos.y - currentPos.y, targetPos.x - currentPos.x) * (180 / Mathf.PI));
    }

    private void DrawLine(VertexHelper vh, Vector2 point, float angle)
    {
        UIVertex vertex = UIVertex.simpleVert;
        vertex.color = colors[0];

        vertex.position = Quaternion.Euler(0, 0, angle) * new Vector3(-lineThickness, 0);
        vertex.position += new Vector3(unitWidth * point.x, unitHeight * point.y);
        vh.AddVert(vertex);

        vertex.color = colors[1];
        vertex.position = Quaternion.Euler(0, 0, angle) * new Vector3(lineThickness, 0);
        vertex.position += new Vector3(unitWidth * point.x, unitHeight * point.y);
        vh.AddVert(vertex);
    }
}

and when i draw in unity like this

https://ibb.co/0MS63Ly

As you guys can see that line thickness is not constant.

How could i make line like picture below?

https://ibb.co/JdhRxqH

  • [This seems to be the same problem](https://gamedev.stackexchange.com/questions/93823/how-to-make-line-renderer-lines-stay-flat). BTW, is there a particular reason, you don't use the linerenderer? – Roland Deschain Jan 02 '21 at 13:42
  • BTW linerenderer is really not ideal for drawing lines like this; we usually use Linefy from the asset store (it's like $2). it's actually an awful lot of work to program good line drawing from scratch - well, you'd have to literally re-program all of Linefy to begin with! – Fattie Jan 02 '21 at 13:57
  • 2
    [Linefy](https://assetstore.unity.com/packages/tools/particles-effects/linefy-165393) is over **20** $ ;) Problem with the line renderer is that it is tricky to use it for Screenspace Overly UI as seems to be OP's intend (@RolandDeschain) – derHugo Jan 02 '21 at 14:16
  • wouldnt [this](https://gamedev.stackexchange.com/questions/96964/how-to-correctly-draw-a-line-in-unity) work? I tried to make it work, but does not render de lines in the game screen (up to what I achieved). It would be nice to know if this might work to get lines rendered in game, and if there are any issues when shown in the UIs. However this might take a while... – rustyBucketBay Jan 03 '21 at 00:31
  • @rustyBucketBay that is Gizmo base which mean cant see in game. I want to draw graph for player not for me T_T – Arbus Omana Jan 03 '21 at 07:29
  • @RolandDeschain i want to draw in UI with URP. line renderer is not good on UI with URP – Arbus Omana Jan 03 '21 at 07:30
  • @Arbus Obama the solition I posted is supposed to work in game, not only as a scene gizmo `// To show the lines in the game window whne it is running void OnPostRender() { DrawConnectingLines(); }` Its and old post and I could not make work in game as It involves a small shader etc. But that does not mean it doesnot work. That is why I was providing the info... – rustyBucketBay Jan 03 '21 at 08:34
  • I think you should be able to draw lines in game with [glLines](https://docs.unity3d.com/ScriptReference/GL.LINES.html) and also in yout UI with [glLoadOrtho](https://docs.unity3d.com/ScriptReference/GL.LINES.html) – rustyBucketBay Jan 03 '21 at 08:44

1 Answers1

1

In case it's useful, find this adapted script from the docs to draw lines.

using UnityEngine;

public class Example : MonoBehaviour
{
    // Draws a line from "startVertex" var to the curent mouse position.
    public Material mat;
    Vector3 startVertex;
    Vector3 mousePos;

    void Start()
    {
        startVertex = Vector3.zero;
    }

    void Update()
    {
        mousePos = Input.mousePosition;
        // Press space to update startVertex
        if (Input.GetKeyDown(KeyCode.Space))
        {
            startVertex = new Vector3(mousePos.x / Screen.width, mousePos.y / Screen.height, 0);
        }
    }

    void OnPostRender()
    {
        if (!mat)
        {
            Debug.LogError("Please Assign a material on the inspector");
            return;
        }
        GL.PushMatrix();
        mat.SetPass(0);
        GL.LoadOrtho();

        GL.Begin(GL.LINES);
        GL.Color(Color.red);
        //GL.Vertex(startVertex);
        //GL.Vertex(new Vector3(mousePos.x / Screen.width, mousePos.y / Screen.height, 0));
        
        GL.Vertex(new Vector3(0, 0, 0));
        GL.Vertex(new Vector3(0.3f, 0.3f, 0f));

        GL.Vertex(new Vector3(0.3f, 0.3f, 0f));
        GL.Vertex(new Vector3(0.3f, 0.5f, 0f));

        GL.Vertex(new Vector3(0.3f, 0.5f, 0f));
        GL.Vertex(new Vector3(0.7f, 0.5f, 0f));

        GL.End();

        GL.PopMatrix();
    }
}

Check how you need to insert every pair of points in screen coordinates. Be aware that Unity calls OnPostRender on MonoBehaviours that are attached to the same GameObject as an enabled Camera component, so there is where you would need to attach this script for it to work.

Find screenShot of the red lines:

enter image description here

In case you might need to draw points from the scene in the world space, you can obtain The Size of the Frustum at a Given Distance from the Camera to transform the points you need to the screen space.

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47
  • Is that can control line thickness?? – Arbus Omana Jan 04 '21 at 06:34
  • 1
    No, no chance to control the thickness this way. You would need to draw quads. [this](https://stackoverflow.com/questions/3484260/opengl-line-width) might be helpfull if you are going for that approach. However assets may ease your way. Find a couple of alternatives I stepped into while researchiing this topic, [2D Shaper](https://assetstore.unity.com/packages/tools/gui/2d-shaper-library-105973?_ga=2.84626905.1345179327.1609576276-170802885.1544202759) and [Vectrosity](https://starscenesoftware.com/vectrosity.html). Did not try them, but might be close to what you want – rustyBucketBay Jan 04 '21 at 08:31