Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UILineRenderer - issues with specifying point locations at runtime #123

Closed
SimonDarksideJ opened this issue Apr 25, 2022 · 14 comments
Closed

Comments

@SimonDarksideJ
Copy link
Contributor

Issue created by Alastair Aitchison as Bitbucket Issue #​123 on 2017.03.08 16:11.
Hi, thanks for all the effort that's gone into these extensions - it's much appreciated!

I'm trying to use the UILineRenderer to generate (at runtime) connections between "nodes" in a graph, where nodes are panels and the graph is on a screenspace overlay canvas that stretches with screen size.

However, I'm having problems specifying the coordinates for the Points array of the linerenderer correctly - I've tried various combinations of using position, anchorPosition, anchoredPosition before and after using SetParent(true or false) to parent the GO containing the UILineRenderer to either the canvas itself or to other items, but it seems that the LineRenderer always has an undesired offset or incorrect scaling.

Please could you clarify whether the coordinates are meant to be provided in worldspace, screenspace, or some other coordinate system? And, even better, could you provide a simple code example that takes, say, two RectTransform parameters of different elements on a canvas and programmatically draws a line between them? Because this doesn't seem to work:

GetComponent<UnityEngine.UI.Extensions.UILineRenderer>().Points = new Vector2[] {
    start.GetComponent<RectTransform>().position, 
    end.GetComponent<RectTransform>().position
};

May thanks!

@SimonDarksideJ
Copy link
Contributor Author

On 2017.03.08 17:22, @SimonDarksideJ commented:
Thanks for the kind words, all helps to support the project and spread awareness.

As to coordinates it is a bit of a strange situation currently. The coordinates are relative coordinates to the bottom left position of the Rect Transform currently. Just the way the original author defined the control.

I have been meaning to revisit this as there have been a few requests to use positional coordinates in SS and WS, but need to find the time to investigate. All that is needed is to transform the WS or SS coordinates relative to the control.

So if you look at the demo videos, they all use 0,0 to 1,1 (bottom left to top right). higher or lower numbers project outside of the rect transform. (it gets a little more freaky if you also turn of the "relative" option (just zoom OUT).

So best to play with what you can and if you can offer any code / updates suggestions I'll add them in (or wait until I got more time to dig in to it)

Hope that helps.

@SimonDarksideJ
Copy link
Contributor Author

On 2017.03.08 18:41, Alastair Aitchison commented:
Ah great, thanks for the reply. That makes sense. I'll have a play around with subtracting the delta from the bottom-left of the RectTransform and seeing if that fixes it (I suspect I may also have to stretch the element containing the UILineRenderer to fill the canvas?).

I'll post back if I make any progress!

@SimonDarksideJ
Copy link
Contributor Author

On 2017.03.09 14:30, Alastair Aitchison commented:
Hmm, so this seems more complicated than I was expecting! I'm not sure but I suspect it's because I have a hierarchy of nested RectTransform components using a variety of different alignments, so calculating the "absolute" position of a given RectTransform relative to the parent canvas is tricky. I had thought that using InverseTransformPoint on the canvas might help, but it seems not....

But I've certainly found a lot of other people having similar problems - unfortunately not with any concrete solutions!

@SimonDarksideJ
Copy link
Contributor Author

On 2017.03.09 16:14, @SimonDarksideJ commented:
:D Welcome to my world @alastaira
Might be worth breaking your scenario down in to smaller parts. So if you update the control to accept SS coordinates. Then have a separate "master" script that trolls the hierarchy to grab their positions and update the control, or have each control simply report it's position back up to the master script.

If I get some time this week, I'll try and look in to it.

@SimonDarksideJ
Copy link
Contributor Author

On 2017.03.13 11:25, Alastair Aitchison commented:
Well, I seem to have got something that works for my scenario at least - not sure how robust it is, but thought I'd share it here anyway! The following allows you to assign an arbitrary number of UI elements to the "Transforms" array and will then correctly draw a UILineRenderer between them.

Assumptions are:

  • that this script is attached to the same gameobject as the UILineRenderer component
  • that the RectTransform of this object is positioned in the middle centre of the canvas, with pivot (0, 0)
using UnityEngine;
using System.Collections;
using UnityEngine.UI.Extensions;

[RequireComponent(typeof(UILineRenderer))]
[ExecuteInEditMode]
public class UILineConnector : MonoBehaviour {

	// The elements between which line segments should be drawn
	public RectTransform[] transforms;
	// The canvas on which the elements lie
	public RectTransform canvas;
	
	// Update is called once per frame
	void Update () {

		// Get the pivot points
		Vector2 thisPivot = GetComponent<RectTransform>().pivot;
		Vector2 canvasPivot = canvas.pivot;

		// Set up some arrays of coordinates in various reference systems
		Vector3[] worldSpaces = new Vector3[transforms.Length];
		Vector3[] canvasSpaces = new Vector3[transforms.Length];
		Vector2[] points = new Vector2[transforms.Length];

		// First, convert the pivot to worldspace
		for (int i = 0; i < transforms.Length; i++) {
			worldSpaces[i] = transforms[i].TransformPoint(thisPivot);
		}

		// Then, convert to canvas space
		for (int i = 0; i < transforms.Length; i++) {
			canvasSpaces[i] = canvas.InverseTransformPoint(worldSpaces[i]);
		}
			
		// Calculate delta from the canvas pivot point
		for (int i = 0; i < transforms.Length; i++) {
			points[i] = new Vector2(canvasSpaces[i].x - canvasPivot.x, canvasSpaces[i].y - canvasPivot.y);
		}

		// And assign the converted points to the line renderer
		GetComponent<UILineRenderer>().Points = points;
	}
}

And here's what it looks like:

UILineConnector.jpg

@SimonDarksideJ
Copy link
Contributor Author

On 2017.03.13 13:44, @SimonDarksideJ commented:
I like your approach to provide an extension script instead of altering the base behaviour of the component. Means it could also be used with the other primitive controls.
Will check it out in a bit.

@SimonDarksideJ
Copy link
Contributor Author

On 2017.06.22 00:54, @SimonDarksideJ commented:
Added Line Renderer Connector from #123 (resolves #123)

Added new Extension method for discovering a parent canvas for a non-graphic

Referenced by ec165a5

@SimonDarksideJ
Copy link
Contributor Author

On 2017.06.22 00:54 @SimonDarksideJ modified issue:
status changed newresolved

@SimonDarksideJ
Copy link
Contributor Author

On 2017.06.22 00:57, @SimonDarksideJ commented:
Added to source with a few teaks and full credit to you @alastaira

Only peculiarity, is that moving pivots on either the Canvas or Line Renderer affect the line drawn. Tried a few tweaks but couldn't resolve. A problem for another day and will just mention it in the documentation for the control.

Thanks again for the submission !

@SimonDarksideJ
Copy link
Contributor Author

On 2017.08.03 23:24, R Bryan Irwin commented:
This is exactly what I was looking for!

If you want to make it more performant, consider replacing the Update method with the event : void OnRectTransformDimensionsChange()
{}

Thanks for making this!

@SimonDarksideJ
Copy link
Contributor Author

On 2017.08.04 10:54, @SimonDarksideJ commented:
You are quite right @bosaku , update probably isn't the best event to update the lines. Not sure OnRectTransformDimensionsChange is the right event as the children transform changes may not kick off that event, but I'll investigate (happy to be wrong :D)

@SimonDarksideJ
Copy link
Contributor Author

On 2017.08.04 20:38, @SimonDarksideJ commented:
Ok, implemented a perf tweak @bosaku , RectTransformChange didn't help as it wouldn't update when the child transforms moved.
So changed the update logic to track the positions of the children and to only redraw the line when they move. Any other Rect Changes in the scene should cause the line to redrawn on it's own.

@SimonDarksideJ
Copy link
Contributor Author

On 2021.07.22 22:19, kobi malul commented:
This Component really Doesn;t work in 2020.3.
This and the Line connector are by far the most confusing thing i’ve used in unity.

@SimonDarksideJ
Copy link
Contributor Author

On 2021.07.22 23:49, @SimonDarksideJ commented:
Hi Kobi.

Can you log a new issue with the issues you are facing, the components and controls have been tested with 2020 and I’m not aware of any new issues.

If there is an issue in the documentation regarding its use, I’ve love to hear your frustrations so we can better improve the guides. Just use a new issue rather than updating old, closed ones.

SimonDarksideJ pushed a commit that referenced this issue Mar 12, 2023
Improved UI Highlightable Utility

Approved-by: Simon Jackson
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant