I want to draw a pentagon in unity using a script which adds a Linerender component to my object.
The Object I will use is a panel which is children of a larger canvas and this is the code I’m using:
public class CharacterUIManager : MonoBehaviour
{
public GameObject panelTalent;
public float chartRadiusFraction = 0.5f; // Fraction of parent object's width to use as pentagon radius
public double chartCenterXFraction = 0.3d; // Fraction of parent object's width to use as X coordinate of pentagon center
public double chartCenterYFraction = 0.5d; // Fraction of parent object's height to use as Y coordinate of pentagon center
int VertexNum = 5;
private void Start()
{
// Get parent object's width and height
double parentWidth;
double parentHeight;
double chartRadius;
double chartCenterX;
double chartCenterY;
double vertexAngle;
double vertexX;
double vertexY;
RectTransform panelTalentRectTransform;
LineRenderer lineRenderer;
Vector3[] vertexPositions = new Vector3[VertexNum];
int cont;
panelTalentRectTransform = panelTalent.GetComponent<RectTransform>();
parentWidth = panelTalentRectTransform.rect.width;
parentHeight = panelTalentRectTransform.rect.height;
// Calculate pentagon radius based on parent object's width and desired fraction
chartRadius = Math.Min(parentWidth, parentHeight) * chartRadiusFraction;
// Calculate X and Y coordinates of pentagon center based on parent object's dimensions and desired fractions
chartCenterX = parentWidth * chartCenterXFraction + panelTalentRectTransform.rect.xMin;
chartCenterY = parentHeight * chartCenterYFraction + panelTalentRectTransform.rect.yMin;
// Calculate vertex positions of pentagon
for (cont = 0; cont < vertexPositions.Length; cont++)
{
vertexAngle = cont * Math.PI * 2.0d / (double) VertexNum;
vertexX= chartRadius * Math.Cos(vertexAngle) + chartCenterX;
vertexY = chartRadius * Math.Sin(vertexAngle) + chartCenterY;
vertexPositions[cont] = new Vector3((float)vertexX, (float)vertexY, 0.0f);
}
// Draw pentagon using LineRenderer
lineRenderer = panelTalent.AddComponent<LineRenderer>();
lineRenderer.positionCount = VertexNum;
lineRenderer.SetPositions(vertexPositions);
lineRenderer.loop = true;
}
}
My problem is that I do not see anything when the program executes. I do not have errors but nothing is draw. If I look to the coordinates of the vertexes in the editor while the program is running they seems a bit strange but I can’t find where I’m wrong
So its just a request to 2 π 5 points into a circle.
If you are the complete beginner go and search unity forums for circle algorithm I think there is even one available on the unity documentation. Though your code looks ok. The type of question you ask indicates you might not fully understand why the code is doing what the code does yet. So you have the answer to the code but you don’t have the ability to make it do what you need. to Draw a pentagon. You must fully understand what your code is doing so that can make the change to the number of points in the circle so that it’s 5 the number of sides of a pentagon
Your code looks fine at first glance. However I suspect the issue being here:
The LineRenderer works with either worldspace coordinates or local space coordinates. However your parentWidth / parentHeight come from the rect of a RectTransform. Those could be way larger than what you may have in mind. So your line renderer may even render fine, but probably way outside your view.
We don’t know anything about your scene setup. What kind of camera you’re using and where relative to the camera you want to draw that pentagon. Maybe you want to draw in UI space? In that case the line renderer may not be the best option here.
To give some context, I have a 2D scene, I have a Canvas at the top of the hierarchy, than a Panel called “screen” where the code is attached and a Panel called “Talents” where I want to draw the pentagon.
“screen” is just a fraction of the original canvas, and “Talents” is 70% of the width of “screen” with the same heigth
I use an ortographic camera, I did not touch any setting on that.
You are probably right, when I try to draw by hand the pentagon it seems that the width and height are wrong how can I change that? Also what do you mean draw in UI space? if there are other options I am happy to try, I’m learning
using UnityEngine;
public class NgonGizmo : MonoBehaviour {
[SerializeField] [Min(0f)] float _size = 1f; // radius distance from the center
[SerializeField] [Range(3, 12)] int _sides = 5;
[SerializeField] [Range(0f, 360f)] float _rotation = 0f; // in local 2D space
void OnDrawGizmos() {
Gizmos.color = Color.white;
var angle = 2f * MathF.PI / _sides; // the angle between two consecutive vertices
var offset = _rotation * Mathf.Deg2Rad; // conversion to radians
var lastP = Vector3.zero;
for(int i = 0; i <= _sides; i++) { // the first iteration is used as a warm-up
var p = (Vector3)(_size * computePoint(i, angle, offset)); // (x, y) -> (x, y, 0)
p = transform.position + transform.rotation * p; // applies world transformation
if(i > 0) Gizmos.DrawLine(lastP, p);
lastP = p; // we can produce edges once we have the first point
}
// basic trigonometry (this is a local function)
static Vector2 computePoint(int index, float sliceAngle, float rotation) {
var x = rotation + sliceAngle * index;
return new Vector2(MathF.Cos(x), MathF.Sin(x));
}
}
}
edit:
You can also freely move and rotate the object in 3D
Well, the cameras and the UI are two completely separate systems. The Canvas is a special type of renderer that “usually” doesn’t use any camera at all. It’s rendered after the scene is rendered since UI is usually on top of the usual scene. The actual world is organised in world space units which usually map to “meters”. The UI / Canvas can be setup in many different ways. The usual UI works with arbirary units as well as pixels and unit less scale factors as usual UI is just relative to the screen itself. It usually has no direct connection with the actual virtual world. The Canvas has several modes it can operate in and can be linked in various ways to a camera if needed. See this video for example.
So you want to make the pentagon out of more than 5 points?
If that’s the case you only need to use the circle algorithm to find a 5 point circle based on the bounds of your desired pentagon. Then use these points to divide your total number of points into 5 and place them in lines across to each pentagon point.
Then you can have say 10 points between the corner of a pentagon say.
Thanks all for the answers but I have the feeling this is going over my intended question.
I try to explain better: I have a menu, this menu is my main canvas and it fills all the scene.
The menu is divided in 4 areas, each of them is a panel with different child’s.
In one of these panel I want to draw a pentagon.
I solved to get the correct coordinates by using the function TransformPoint for the vertexes of the panel.
Now my problem is that the pentagon is visible only if I set a Z coordinate <0. If it is 0 or more nothing is visible. This is strange because my scene is a 2D scene. Is it possible this has something to do with the background of the panel?
@Mpx83
You have a trouble explaining yourself. Why is this a question about pentagons at all?
Can’t you distill your question into something that nails down exactly what you’re doing and trying to achieve? If shapes are irrelevant, maybe it would be helpful if you would focus on the relevant stuff only.
I’m saying this because I can’t wrap my head around this. We can only guess from such info. I.e. your line renderer gets culled or is occluded and whatnot. I don’t know how your actual scene is set up etc.
The question was about pentagon because when I first posted this I was pretty sure that the code I posted was enough to draw a pentagon. Now I discovered there were 2 problems, one about the scale is solved and then other that the line can be hidden by the background or something.
As I told before I thank everyone for the help. I do not want anyone to loose sleep on that.
My scene is as simple as that: standard 2D scene with standard camera and the canvas that covers all the scene
I suppose so. The point is that if I add manually the points in the line render when nothing is running I can draw the pentagon but I have to put a negative Z. When I run the script I can see that the points have the “correct coordinates” but I cannot see anything
What I’m understanding is that your line renderer behaves properly in the scene but doesn’t appear on the camera view.
Are you sure you need a canvas for this step? Can you try this just with the camera view?
If changing Z affects the display, this sounds like your rendered object is being culled by the camera. Have you properly set up the planar culling of the camera frustum (which should look like a cuboid for an orthographic camera)? I.e. the minimum and maximum culling distance.
The object being rendered must be inside frustum at all times.
Thanks for your time. I made some tests changing the camera settings There is some improvements like now if I run the scene in the editor I can see the pentagon. I made a simple version of my problem and i draw by hand the pentagon and there are still some problems:
The line seems dashed even if I put thickness 1.
Also now I can see the pentagon at Z=0 but the visibility is still Z dependent, don’t know why.
I made some screenshoots of the settings of the camera and of the canvas and the line render, could you be so kind to tell me what I am terribly missing?
This is what appears when I run the scene in the editor
You have two separate issues, the UI system and the Main Camera system are unrelated. The way this normally works is: 1) you set up the scene, with your Line Renderer in it, and once this is working, 2) you add the UI system with its own camera. The UI is normally rendered on top of what the regular camera sees, adds the Canvas and you should set up its own camera whose job is to see only this Canvas.
However, you’ve dragged your Main Camera here, this makes it so that this camera sees both the world and the UI canvas, and so your Line Renderer is mingling in the wrong space. Yet because you’ve set up your UI to be in screen space, these spaces are very different and should not be mixed. Effectively your Line Renderer is constantly getting clipped by the Canvas and because you’ve set your Main Camera to be Solid Color (which is how it should be), the Canvas has an opaque background.
Again, you need a different camera for the UI system, this is what trips your set up completely. Normally you place this camera as a child of Canvas in your current setup, and it should only see ‘UI’ elements. (Likewise, your Main Camera should not see any ‘UI’ elements).
I advise you to get rid of the UI system and work only with Line Renderer and Main Camera. However if your intention was to make Line Renderer be the part of the UI graphics, then you cannot work in Screen Space anymore, you must switch to a World Space regime, because Line Renderer is like a regular Mesh Renderer in the world space. Or alternatively, I see there is a ‘Use World Space’ checkbox on it, so maybe you can configure this somehow to make it work for your set up, I just don’t know without trying it for myself.
What you need to do is to observe your Scene very carefully, understand how cameras work, and how UI system works, differentiate between what is world and what is screen space, and move one step at a time.
Last question because I understand that “I do not understand at all” There is nothing in the scene except the canvas, that’s why I (wrongly) assumed I only need one camera. Still if I understand what you are saying it means it is impossible to draw with line render on a canvas on a 2D scene?