Search Unity

Instantiate on Canvas

Discussion in 'General Discussion' started by CitrusScribbles, Mar 13, 2022.

  1. CitrusScribbles

    CitrusScribbles

    Joined:
    Mar 5, 2022
    Posts:
    2
    I'm currently doing a proof of concept similar to how MS paint works. I'm using Line Renderer to create basic drawing capabilities, but there's a problem. The Instantiate process always shows up outside of any canvas, meaning it's always covered by my background. I've tried making it a child of the initial and of a separate canvas in the code, but that didn't work. I've tried the 'creating a new camera and linking it to one canvas' trick, but that didn't work (though I might not have understood that completely). I've also tried masking layers, though I don't understand that 100%. It still shows up outside of any canvas, so it's always under my background. Any ideas for a good solution?

    Here's my code:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Draw : MonoBehaviour
    {
    public GameObject canvasObject;
    public Camera m_camera;
    public GameObject brush;

    LineRenderer currentLineRenderer;

    Vector2 lastPos;

    private void Update()
    {
    Drawing();
    }

    void Drawing()
    {
    if (Input.GetKeyDown(KeyCode.Mouse0))
    {
    CreateBrush();
    }
    else if (Input.GetKey(KeyCode.Mouse0))
    {
    PointToMousePos();
    }
    else
    {
    currentLineRenderer = null;
    }
    }

    void CreateBrush()
    {
    GameObject brushInstance = Instantiate(brush);
    // Next line is attempt as making the canvas the parent
    brushInstance.transform.SetParent(canvasObject.transform, false);
    currentLineRenderer = brushInstance.GetComponent <LineRenderer>();

    Vector2 mousePos = m_camera.ScreenToWorldPoint(Input.mousePosition);

    currentLineRenderer.SetPosition(0, mousePos);
    currentLineRenderer.SetPosition(1, mousePos);

    }

    void AddAPoint(Vector2 pointPos)
    {
    currentLineRenderer.positionCount++;
    int positionIndex = currentLineRenderer.positionCount - 1;
    currentLineRenderer.SetPosition(positionIndex, pointPos);
    }

    void PointToMousePos()
    {
    Vector2 mousePos = m_camera.ScreenToWorldPoint(Input.mousePosition);
    if (lastPos != mousePos)
    {
    AddAPoint(mousePos);
    lastPos = mousePos;
    }
    }

    }


    And here's my hierarchy:
    Before Instantiating
    upload_2022-3-13_16-16-25.png
    After Instantiating
    upload_2022-3-13_16-16-4.png

    For further elaboration:
    I followed this tutorial
     

    Attached Files:

  2. CitrusScribbles

    CitrusScribbles

    Joined:
    Mar 5, 2022
    Posts:
    2
    For anyone that finds this, don't use the Line Renderer method! There is literally NO SOLUTION for this! Line Renderers cannot be put on a canvas! I have no idea why, but sadly they can't. Instead, I'm now currently trying to figure out how to use a Spriteshape method, which I'm also struggling with due to my Raw Image just... poofing. Will update when I get it figured out!
     
  3. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    That's correct, the LineRenderer can't be used on a Canvas. As for why, it's because Canvas elements are rendered in a fundamentally different way to non-Canvas objects. The short version is that "normal" objects such as LineRenderers render their own content, where Images and UI Text and other similar elements instead just contain content which is rendered by the Canvas they are a part of.

    Unfortunately I do not believe that there is a line rendering solution for Canvas rendering provided by Unity. There are some 3rd party ones you could check out, though. (I can't recommend one. The only one I tried was... frightfully inefficient.)
     
  4. Murgilod

    Murgilod

    Joined:
    Nov 12, 2013
    Posts:
    10,152
    Because LineRenderer predates UGUI by a significant amount of time and you should just use Camera.ScreenToWorldPoint to set its position instead.