I’m trying to draw out circular orbits for a solar system. I found some code and tinkered with it (most of the tinkering was converting it to Javascript), but I’m getting a weird result where (what I think is) the last part of the orbit goes back to origin. I understand the math superficially, but would appreciate some help figuring this out.
Code:
public var radius : float = 1.0;
private var theta_scale : float = 0.1; //Set lower to add more points
private var size : float = (3.0 * Mathf.PI) / theta_scale; //Total number of points in circle.
function Start()
{
var lineRenderer : LineRenderer = gameObject.AddComponent("LineRenderer");
var c1 : Color = Color(0.5, 0.5, 0.5, 1);
lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
lineRenderer.SetColors(c1, c1);
lineRenderer.SetWidth(0.05, 0.05);
lineRenderer.SetVertexCount(size);
var i : int = 0;
for(var theta : float = 0; theta < (2.0 * Mathf.PI); theta += 0.1)
{
var x : float = radius * Mathf.Cos(theta);
var y : float = radius * Mathf.Sin(theta);
var pos : Vector3 = new Vector3(x, y, 0);
lineRenderer.SetPosition(i, pos);
i += 1;
}
}
You have “3.0 * Mathf.PI” instead of “2.0 * Mathf.PI”. Also is there any reason why you calculate the vertex count from a theta_scale and not the other way round?
Usually it makes much more sense like this:
public var radius : float = 1.0;
public var vertexCount = 20;
function Start()
{
var lineRenderer : LineRenderer = gameObject.AddComponent("LineRenderer");
var c1 : Color = Color(0.5, 0.5, 0.5, 1);
lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
lineRenderer.SetColors(c1, c1);
lineRenderer.SetWidth(0.05, 0.05);
lineRenderer.SetVertexCount(vertexCount+1);
for(var i = 0; i < vertexCount+1; i++)
{
var angle : float = i;
i = (i / vertexCount) * Mathf.PI * 2;
var pos : Vector3 = new Vector3(Mathf.Cos(angle), Mathf.Sin(angle), 0) * radius;
lineRenderer.SetPosition(i, pos);
}
}
I used vertexCount+1 because you need to duplicate the last point since the first and the last point should be the same.
I worked with a programmer friend of mine in meatspace and he suggests something very similar to this. I am happy to have two good answers. Thanks so much. Unity devs are great!
For posterity, my meatspace programmer friend suggests:
public var radius : float = 1.0;
private var numSegments:int = 128;
function Start()
{
var lineRenderer : LineRenderer = gameObject.AddComponent("LineRenderer");
var c1 : Color = Color(0.5, 0.5, 0.5, 1);
lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
lineRenderer.SetColors(c1, c1);
lineRenderer.SetWidth(0.05, 0.05);
lineRenderer.SetVertexCount(numSegments + 1);
var deltaTheta:float = (2.0 * Mathf.PI) / numSegments;
var theta:float = 0;
for (var i:int = 0; i < numSegments + 1; i++)
{
var x : float = radius * Mathf.Cos(theta);
var y : float = radius * Mathf.Sin(theta);
var pos : Vector3 = new Vector3(x, y, 0);
lineRenderer.SetPosition(i, pos);
theta += deltaTheta;
}
}
KarenM’s revision in c#, in my case I wasn’t able to see the circle till I set useWorldSpace to false. This is a late answer I know, but who knows it may help someone later.
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class CircleRenderer : MonoBehaviour {
[Range(0.1f, 100f)]
public float radius = 1.0f;
[Range(3, 256)]
public int numSegments = 128;
void Start ( ) {
DoRenderer();
}
public void DoRenderer ( ) {
LineRenderer lineRenderer = gameObject.GetComponent<LineRenderer>();
Color c1 = new Color(0.5f, 0.5f, 0.5f, 1);
lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
lineRenderer.SetColors(c1, c1);
lineRenderer.SetWidth(0.05f, 0.05f);
lineRenderer.SetVertexCount(numSegments + 1);
lineRenderer.useWorldSpace = false;
float deltaTheta = (float) (2.0 * Mathf.PI) / numSegments;
float theta = 0f;
for (int i = 0 ; i < numSegments + 1 ; i++) {
float x = radius * Mathf.Cos(theta);
float y = radius * Mathf.Sin(theta);
Vector3 pos = new Vector3(x, y, 0);
lineRenderer.SetPosition(i, pos);
theta += deltaTheta;
}
}
}