Home > Enterprise >  How to move object on drawn circle radius if the radius is not equal if it's ellipse?
How to move object on drawn circle radius if the radius is not equal if it's ellipse?

Time:04-16

If the radius is equal and it's a circle shape then the object rotatearound it fine. but if the radius for example xRadius is 1 and yRadius is 5 and it's ellipse shape then the object rotating out away from the radius. Now i'm using only the xRadius because i consider both xRadius and yRadius are the same.

but now dc.xRadius and dc.yRadius are not the same values. like in the screenshot.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateAroundTarget : MonoBehaviour
{
    public Transform target;
    public float rotatingSpeed;
    public float movingSpeed;
    public Vector3 axis;
    public bool randomHeight;
    public float setRandomHeight = 1;
    public float radius;
    public DrawCircle dc;

    private float lastRadius;
    private bool move = false;
    private float t = 0.0f;
    public float upperLimit, lowerLimit, delay;
    private float prevHeight;
    private Vector3 radiusPosition;

    private void Start()
    {
        if (dc != null)
        {
            lastRadius = dc.xRadius;
            radius = dc.xRadius;
        }
        else
        {
            lastRadius = radius;
        }
        move = true;
    }

    private void Update()
    {
        if (target != null)
        {
            if (dc != null)
            {
                radiusPosition = new Vector3(target.position.x,
                    target.position.y, target.position.z   dc.xRadius);
                radius = dc.xRadius;
            }
            else
            {
                radiusPosition = new Vector3(target.position.x, target.position.y, target.position.z   radius);
            }
        }

        if (move == false)
        {
            if (target != null)
            {
                transform.RotateAround(target.position, axis, rotatingSpeed * Time.deltaTime);
            }

            if (randomHeight)
            {
                t  = Time.deltaTime;

                if (t > delay)
                {
                    prevHeight = setRandomHeight;
                    setRandomHeight = Random.Range(lowerLimit, upperLimit);
                    t = 0;
                }

                var tt = transform.position;
                tt.y = Mathf.Lerp(prevHeight, setRandomHeight, t);
                transform.position = tt;
            }
        }

        if (dc != null)
        {
            if (lastRadius != dc.xRadius)
            {
                move = true;

                lastRadius = dc.xRadius;
            }
        }
        else
        {
            if (lastRadius != radius)
            {
                move = true;

                lastRadius = radius;
            }
        }

        if (move)
        {
            if (transform.position != radiusPosition)
            {
                float step = movingSpeed * Time.deltaTime;
                transform.position = Vector3.MoveTowards(transform.position,
                    radiusPosition, step);
            }
            else
            {
                move = false;
            }
        }
    }
}

The ellipse is around the sphere and the cube should rotate around the sphere on the ellipse.

This is the script that draw the circle/ellipse :

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[ExecuteAlways]
[RequireComponent(typeof(UnityEngine.LineRenderer))]
public class DrawCircle : MonoBehaviour
{
    [Range(1, 50)] public int segments = 50;
    [Range(1, 500)] public float xRadius = 5;
    [Range(1, 500)] public float yRadius = 5;
    [Range(0.1f, 5)] public float width = 0.1f;
    [Range(0, 100)] public float height = 0;
    public bool controlBothXradiusYradius = false;
    public bool draw = true;

    [SerializeField] private LayerMask targetLayers;
    [SerializeField] private LineRenderer line;

    private void Start()
    {
        if (!line) line = GetComponent<LineRenderer>();

        if (draw)
            CreatePoints();
    }

    private void Update()
    {
        if (Physics.CheckSphere(transform.position, xRadius, targetLayers))
        {
            Debug.Log("player detected");
        }
        else
        {
            Debug.Log("player NOT detected");
        }
    }

    public void CreatePoints()
    {
        line.enabled = true;
        line.widthMultiplier = width;
        line.useWorldSpace = false;
        line.widthMultiplier = width;
        line.positionCount = segments   1;

        float x;
        float y;

        var angle = 20f;
        var points = new Vector3[segments   1];

        for (int i = 0; i < segments   1; i  )
        {
            x = Mathf.Sin(Mathf.Deg2Rad * angle) * xRadius;
            y = Mathf.Cos(Mathf.Deg2Rad * angle) * yRadius;

            points[i] = new Vector3(x, height, y);

            angle  = (380f / segments);
        }

        // it's way more efficient to do this in one go!
        line.SetPositions(points);
    }

#if UNITY_EDITOR
    private float prevXRadius, prevYRadius;
    private int prevSegments;
    private float prevWidth;
    private float prevHeight;

    private void OnValidate()
    {
        // Can't set up our line if the user hasn't connected it yet.
        if (!line) line = GetComponent<LineRenderer>();
        if (!line) return;

        if (!draw)
        {
            // instead simply disable the component
            line.enabled = false;
        }
        else
        {
            // Otherwise re-enable the component
            // This will simply re-use the previously created points
            line.enabled = true;

            if (xRadius != prevXRadius || yRadius != prevYRadius || segments != prevSegments || width != prevWidth || height != prevHeight)
            {
                CreatePoints();

                // Cache our most recently used values.
                prevXRadius = xRadius;
                prevYRadius = yRadius;
                prevSegments = segments;
                prevWidth = width;
                prevHeight = height;
            }

            if (controlBothXradiusYradius)
            {
                yRadius = xRadius;

                CreatePoints();
            }
        }
    }
#endif
}

CodePudding user response:

If you want to put something directly on the line drawn by the code you posted, you can move it between the Vector3 positions in the points[] array.

If you just want code to move an object in an ellipse, you could do something like this:

using UnityEngine;

public class Orbit : MonoBehaviour
{
    public float radiusX, radiusY;
    public float speed;
    public float currentAngleInRadians;

    void Update()
    {
        currentAngleInRadians  = speed * Time.deltaTime;
        transform.localPosition = new Vector3(
                Mathf.Cos(currentAngleInRadians) * radiusX,
                Mathf.Sin(currentAngleInRadians) * radiusY,
                0);
    }
}

Put the object using this script inside a parent GameObject and you can move and rotate that parent object to change the centre and the axis of the orbit. Make speed negative for clockwise rotation.

  • Related