I need to create 2D planes in a 3D scene, in which 1 or more circles/dots each rotate around a distinct wider circular tarjectory. I need to be able to set each dot’s colour, rotational speed & direction independently, and to be able to get its (x,y) coordinates in the 2D plane whenever I want at runtime.
I’m good with C#, but not familiar with scripting for unity nor 3D & game development in general.
So far, I have used a UI Canvas for the 2D plane and populated it with the circles as scripted by @Senshihere.
First of all, is this a sound way to proceed? If yes/no please can you tell me why?
If I’m on the right track, can someone explain or point me to a (hopefully basic) documentation where I can get started with making those dots rotate in the 2D plane?
FWIW I have kind of worked it out; I wrote a script that doest what i need:
using System;
using UnityEngine;
/// <summary>
/// This Unity script rotates a UI component in a 2D (x,y) plan according to the
/// parametric equation of the circle. The component will rotate from its
/// initial position around a given rotation centre at a given rotation speed.
///
/// Make sure that the parent Canvas' Rect Transform Anchors Min, Max and Pivot
/// are all set to 0.5 or the script doesn't work properly.
///
/// Source code can be clarified: some confusuions over period vs frequency
/// & over degrees vs radians.
///
/// More detail <see href="http://answers.unity3d.com/questions/596671/circular-rotation-via-the-mathematical-circle-equa.html">here</see>
/// </summary>
public class Rotator : MonoBehaviour {
# region ATTRIBUTES
// UI component's instant 2D coordinates :
public float X { get; private set; }
public float Y { get; private set; }
// orbit center 2D coordinates:
public float orbitCentreX;
public float orbitCentreY;
// positional angle, in degrees:
private float theta;
// time to complete a full revolution, in seconds:
[Range((float)1, 35)]
public float rotationTime;
private float period;
// circle radius:
private float radius;
// Rotation direction:
public bool isClockwise;
#endregion ATTRIBUTES
#region METHODS
#region Start() bloc
void Start () {
this.X = this.transform.localPosition.x;
this.Y = this.transform.localPosition.y;
this.period = getPeriod();
this.radius = getRadius();
this.theta = getTheta();
// DEBUG:
//print(this + "-----> this.period=" + this.period + "\n");
//print(this + "-----> this.radius=" + this.radius + "\n");
//print(this + "-----> this.theta=" + this.theta + "\n");
}
/*
* Returns the the time of a rotation in seconds.
*/
private float getPeriod()
{
// T=2*PI*f and f=1/rotationTime
// so one rotation is completed in 'rotationTime' seconds:
return (2 * Mathf.PI) / rotationTime;
}
/*
* Returns the radius of the trajectory (Pythagoras' formula).
*/
private float getRadius()
{
float a = orbitCentreX - X;
float b = orbitCentreY - Y;
return Mathf.Sqrt(a*a + b*b);
}
/*
* Returns the UI component's instant positional angle.
*/
private float getTheta()
{
return Mathf.Atan2(
Y - orbitCentreY,
X - orbitCentreX);
}
#endregion Start() bloc
#region Update() bloc
void Update () {
updatePosition();
this.period = getPeriod();
updateTheta();
}
/*
* Updates this script's internal (x,y) coordinates and moves the GameObject
* in the 2D plane accordingly:
*/
private void updatePosition()
{
X = orbitCentreX + (radius * Mathf.Cos(theta));
Y = orbitCentreY + (radius * Mathf.Sin(theta));
transform.localPosition = new Vector3(X, Y, 0);
}
/*
* Returns the next rotational angle in degrees.
*/
private void updateTheta()
{
theta = isClockwise ?
theta - (period * Time.deltaTime) % 360 :
theta + (period * Time.deltaTime) % 360;
}
#endregion Update() bloc
#endregion METHODS
}
Any comments or improvement suggestion more than welcome