- Home /
Question by
waelelsawy · Sep 03, 2019 at 04:01 PM ·
c#lerptransform.positioncoroutines
How to spawn evenly spaced game objects and move them in a circular path?
Hi Everyone, I don't know why my code doesn't work as intended!, please help me. :)
Actual Behavior:
Expected Behavior:
Orbit class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Orbit : MonoBehaviour
{
public Circle circlePrefab;
public Vector2 centerPoint = Vector2.zero;
[Range(3, 360)] public int segments = 5;
public float xRadius = 2f;
public float yRadius = 2f;
public int numberOfCircles = 0;
public float speed = 0f;
private Vector2 initPosition = new Vector2(0, 2f);
private Vector2[] points;
private List<float> distances = new List<float>();
private float totalDistance = 0;
// Start is called before the first frame update
void Start()
{
points = new Vector2[segments];
for (var i = 0; i < segments; i++)
{
Vector2 point = GetPathPoint(i / (float) segments);
if (i > 0)
totalDistance += AddSegment(points[i - 1], point);
points[i] = point;
}
totalDistance += AddSegment(points[segments - 1], points[0]);
StartCoroutine(SpawnCircles());
}
private Vector2 GetPathPoint(float t)
{
var angle = t * 360f * Mathf.Deg2Rad;
var x = Mathf.Sin(angle) * xRadius;
var y = Mathf.Cos(angle) * yRadius;
return new Vector2(centerPoint.x + x, centerPoint.y + y);
}
private float AddSegment(Vector2 from, Vector2 to)
{
float distance = (from - to).sqrMagnitude;
distances.Add(distance);
return distance;
}
private IEnumerator SpawnCircles()
{
yield return new WaitForSeconds(1);
var time = new WaitForSeconds(totalDistance / speed / numberOfCircles);
for (var i = 0; i < numberOfCircles; i++)
{
Circle circle = Instantiate(circlePrefab, initPosition, transform.rotation);
circle.transform.parent = transform;
circle.name = "circle " + i;
circle.points = points;
circle.distances = distances;
circle.speed = speed;
yield return time;
}
}
}
Circle class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Circle : MonoBehaviour
{
public Vector2[] points;
public float speed = 1f;
public List<float> distances = new List<float>();
private float distance = 0;
private int currentIndex = 0;
private float time = 0;
private Vector2 currentPoint;
private Vector2 nextPoint;
// Start is called before the first frame update
void Start()
{
currentPoint = points[currentIndex];
nextPoint = points[currentIndex + 1];
}
// Update is called once per frame
void Update()
{
if (transform.position == (Vector3) nextPoint)
{
currentIndex++;
currentIndex %= distances.Count;
time = 0;
currentPoint = points[currentIndex];
nextPoint = points[(currentIndex + 1) % points.Length];
}
time += Time.deltaTime;
distance = time * speed / distances[currentIndex];
transform.position = Vector2.Lerp(currentPoint, nextPoint, distance);
}
}
Can you have a look @Leia and @ImpOfThePerverse ?
screen-shot-2019-09-04-at-30948-pm.png
(59.0 kB)
screen-shot-2019-09-04-at-30730-pm.png
(59.1 kB)
Comment
Answer by RunninglVlan · Sep 05, 2019 at 12:55 PM
Based on the code from Code Monkey's video (which I just happened to watch yesterday =D) here's my solution:
using UnityEngine;
public class Orbit : MonoBehaviour {
[SerializeField] Transform satellite;
[SerializeField] int count = 10;
[SerializeField] float distanceFromCenter = 2;
[SerializeField] int rotationSpeed = 5;
void Start() => PlaceSatellitesAround();
private void PlaceSatellitesAround() {
for (int i = 0; i < count; i++) {
var angle = i * (360f / count);
var direction = Quaternion.Euler(0, 0, angle) * Vector3.up;
var position = transform.position + direction * distanceFromCenter;
Instantiate(satellite, position, Quaternion.identity, transform);
}
}
void Update() => Rotate();
private void Rotate() {
transform.Rotate(Vector3.forward, rotationSpeed * Time.deltaTime);
}
}
I hope you'll be able to adapt it to your needs. Feel free to ask questions if you have any.