Say I have a few draggable image elements. I want to draw some lines between them, like a flow chart or a family tree type structure. Do you know of a good way to do this?
My thoughts are my options:
Draw a think black rotated image to act as a line
Draw an image and set the pixels of the image to draw a line say from top-left to bottom-right
Use GL.Line
Draw 100 tiny images of circles lines up in a line or curve
Draw many short rotated thin line images to make a curved line
Hey there, I had the same problem and I solved it by drawing a thick black rotated image :))
Works only between 2 objects, but can be easily extended
Here is the code, if anyone needs it:
You have to call the SetObjects function and give as parameters 2 gameObjects that have rect transform attached to them.
using UnityEngine;
using UnityEngine.UI;
public class LineBetweenObjects : MonoBehaviour
{
private RectTransform object1;
private RectTransform object2;
private Image image;
private RectTransform rectTransform;
// Start is called before the first frame update
void Start()
{
image = GetComponent<Image>();
rectTransform = GetComponent<RectTransform>();
}
public void SetObjects(GameObject one, GameObject two)
{
object1 = one.GetComponent<RectTransform>();
object2 = two.GetComponent<RectTransform>();
RectTransform aux;
if (object1.localPosition.x > object2.localPosition.x)
{
aux = object1;
object1 = object2;
object2 = aux;
}
}
// Update is called once per frame
void Update()
{
if (object1.gameObject.activeSelf && object2.gameObject.activeSelf)
{
rectTransform.localPosition = (object1.localPosition + object2.localPosition) / 2;
Vector3 dif = object2.localPosition - object1.localPosition;
rectTransform.sizeDelta = new Vector3(dif.magnitude, 5);
rectTransform.rotation = Quaternion.Euler(new Vector3(0, 0, 180 * Mathf.Atan(dif.y / dif.x) / Mathf.PI));
}
}
}
That works like a charm. Here’s my version, which dynamically creates the lines:
void MakeLine(float ax, float ay, float bx, float by, Color col) {
GameObject NewObj = new GameObject();
NewObj.name = "line from "+ax+" to "+bx;
Image NewImage = NewObj.AddComponent<Image>();
NewImage.sprite = lineImage;
NewImage.color = col;
RectTransform rect = NewObj.GetComponent<RectTransform>();
rect.SetParent(transform);
rect.localScale = Vector3.one;
Vector3 a = new Vector3(ax*graphScale.x, ay*graphScale.y, 0);
Vector3 b = new Vector3(bx*graphScale.x, by*graphScale.y, 0);
rect.localPosition = (a + b) / 2;
Vector3 dif = a - b;
rect.sizeDelta = new Vector3(dif.magnitude, lineWidth);
rect.rotation = Quaternion.Euler(new Vector3(0, 0, 180 * Mathf.Atan(dif.y / dif.x) / Mathf.PI));
}
Note that you need to make sure the anchor points are set correctly. My graph starts bottom left, so I add:
// set them to start bottom-left
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.zero;
as the last lines of that function.
The function above uses a few global variables to scale and set line width, etc. but it should be easy enough to figure it out. I pass in parameters as individual floats because that’s how I get my data, but you could easily adapt it to accept a Vector3.