如果半径不相等,如果它是椭圆,如何在绘制的圆半径上移动对象?

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

如果半径相等且为圆形,则物体可以围绕它旋转。 但是如果半径例如 xRadius 是 1 并且 yRadius 是 5 并且它是椭圆形然后对象旋转远离半径。现在我只使用 xRadius,因为我认为 xRadius 和 yRadius 是相同的。

但现在 dc.xRadius 和 dc.yRadius 不是相同的值。如截图所示。

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;
            }
        }
    }
}

这是绘制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
}

如果您想直接在您发布的代码绘制的线上放置一些东西,您可以在 points[] 数组中的 Vector3 位置之间移动它。

如果您只想让代码在椭圆中移动一个对象,您可以这样做:

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);
    }
}

使用此脚本将对象放入父游戏对象中,您可以移动和旋转该父对象以更改轨道的中心和轴。顺时针旋转速度为负值