How to change the created objects height when changing the height value of the circle?

in this method i create the circle using line renderer:
when i change the value of the variable height it’s changing the circle height.

void CreatePoints()
{
    float angleStep = 360f / segments;
    float angle = 0f;
    float y = height; // Fixed height for the circle plane

    // Adjust radii based on parent's scale
    Vector3 parentScale = transform.parent ? transform.parent.lossyScale : Vector3.one;
    float adjustedXRadius = xradius / parentScale.x;
    float adjustedYRadius = yradius / parentScale.z;

    for (int i = 0; i <= segments; i++) // <= to close the circle
    {
        float x = Mathf.Sin(Mathf.Deg2Rad * angle) * adjustedXRadius;
        float z = Mathf.Cos(Mathf.Deg2Rad * angle) * adjustedYRadius;

        line.SetPosition(i, new Vector3(x, y, z));
        angle += angleStep;
    }
}

in this method i create objects and put them position them on the circle:

public void CreateObjectsAroundPoint(int num, Vector3 point, float xRadius, float yRadius)
{
    // Clear existing objects
    ClearObjects(true);

    // Ensure at least one object is created
    if (num < 1) return;

    // Temporary list to track new objects
    List<GameObject> newObjects = new List<GameObject>();

    for (int i = 0; i < num; i++)
    {
        // Distance around the ellipse
        var radians = 2 * Mathf.PI / num * i;

        // Calculate the position on the ellipse
        var x = Mathf.Cos(radians) * xRadius;
        var z = Mathf.Sin(radians) * yRadius;

        var spawnPos = point + new Vector3(x, 0, z); // Set position on ellipse

        // Instantiate and position the object
        var obj = Instantiate(objectPrefab, spawnPos, Quaternion.identity);

        // Set tag and name
        obj.tag = "ObjectonCircle";
        obj.name = "Object on Circle";

        // Rotate the object to face the center
        obj.transform.LookAt(point);

        // Add the object to the list
        newObjects.Add(obj);
    }

    // Update the objects array with the newly created objects
    objects = newObjects.ToArray();
}

and in this method i adjust the objects positions:

private void AdjustPositions(int num, Vector3 point, float xRadius, float yRadius)
{
    if (objects == null || objects.Length == 0 || num <= 0) return;

    for (int i = 0; i < objects.Length; i++)
    {
        if (objects[i] == null) continue; // Skip if the object was destroyed

        // Distance around the ellipse
        var radians = 2 * Mathf.PI / num * i;

        // Calculate the new position on the ellipse
        var x = Mathf.Cos(radians) * xRadius;
        var z = Mathf.Sin(radians) * yRadius;

        var spawnPos = point + new Vector3(x, 0, z); // Set position on ellipse

        // Update object position
        objects[i].transform.position = spawnPos;

        // Rotate the object to face the center
        objects[i].transform.LookAt(point);
    }
}

now when i change the circle radius size on the xrdaius or yradius the created objects also change position and keep staying on the circle radius even if i change only the xradius or only the yradius and it become ellipse the objects keep staying on the circle. same if i change the value of the variable changeBothRadius.

the problem is when i change the circle height the objects stay down not moving.

i tried to change in both methods CreateObjectsAroundPoint and AdjustPositions the line:

var spawnPos = point + new Vector3(x, 0, z);

to

var spawnPos = point + new Vector3(x, height, z);

when i change the height value the circle moves up but the objects on the circle move too much higher offset above the circle.

how to fix it? i want when i change the circle height that the objects will stay on the circle and move with it.

here is the full script:

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using TMPro;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

[ExecuteAlways]
[RequireComponent(typeof(LineRenderer))]
public class DrawCircleAroundObject : MonoBehaviour
{
    [Header("Debug Information")]
    public TextMeshProUGUI debugText; // Reference to the TextMeshPro text field

    [Header("Draw Circle")]
    [Range(0, 50)]
    public int segments = 50;
    [Range(0, 5)]
    public float xradius = 5;
    [Range(0, 5)]
    public float yradius = 5;
    [Range(0, 5)]
    public float changeBothRadius = 1; // Synchronization control
    [Range(0.1f, 5f)]
    public float width = 0.1f;
    [Range(0, 50)]
    public float height = 0;
    public bool draw = true;
    [Header("Add Objects on Circle")]
    [Range(0, 50)]
    public int numOfObjects = 5;
    public GameObject objectPrefab;
    private int prevNumOfObjects;

    [Header("Move Objects")]
    public MoveObjects moveObjects;

    private float previousBothRadius = -1; // Tracks the last value of changeBothRadius
    private float previousXradius;
    private float previousYradius; 
    private LineRenderer line;
    private GameObject[] objects;

    private float initialXRadius = -1;
    private float initialYRadius = -1;
    private float initialBothRadius = -1;
    private Vector3 initialObjectPosition = Vector3.zero;
    private GameObject referenceObject; // Reference to track one object
    
    void Start()
    {
        prevNumOfObjects = numOfObjects;
        line = gameObject.GetComponent<LineRenderer>();
        ConfigureLineRenderer();
        CreatePoints();
    }

    private void OnValidate()
    {
        // Handle changes to changeBothRadius
        if (changeBothRadius != previousBothRadius)
        {
            SyncRadii(); // Sync radii when changeBothRadius changes
            previousBothRadius = changeBothRadius;
        }
        else if (xradius != previousXradius || yradius != previousYradius)
        {
            // Allow independent changes to xradius and yradius
            Debug.Log($"Updating radii: X = {xradius}, Y = {yradius}");
            previousXradius = xradius;
            previousYradius = yradius;
        }

        // Update LineRenderer and object positions
        if (line != null && draw)
        {
            ConfigureLineRenderer();
            CreatePoints();
            AdjustPositions(numOfObjects, transform.position, xradius, yradius); // Pass both radii
        }
    }

    private void Update()
    {
        if (line != null && draw)
        {
            line.enabled = true;
        }
        else if (line != null)
        {
            line.enabled = false;
        }

        if (prevNumOfObjects != numOfObjects)
        {
            CreateObjectsAroundPoint(numOfObjects, transform.position, xradius, yradius); // Pass both radii
            prevNumOfObjects = numOfObjects;
        }

        // Update Debug Text
        UpdateDebugText();
    }

    void ConfigureLineRenderer()
    {
        line.useWorldSpace = false;
        line.loop = true; // Ensures the circle is closed
        line.startWidth = width;
        line.endWidth = width;
        line.positionCount = segments + 1; // +1 to close the circle
    }

    void SyncRadii()
    {
        xradius = changeBothRadius;
        yradius = changeBothRadius;

        previousXradius = xradius;
        previousYradius = yradius;
    }

    void CreatePoints()
    {
        float angleStep = 360f / segments;
        float angle = 0f;
        float y = height; // Fixed height for the circle plane

        // Adjust radii based on parent's scale
        Vector3 parentScale = transform.parent ? transform.parent.lossyScale : Vector3.one;
        float adjustedXRadius = xradius / parentScale.x;
        float adjustedYRadius = yradius / parentScale.z;

        for (int i = 0; i <= segments; i++) // <= to close the circle
        {
            float x = Mathf.Sin(Mathf.Deg2Rad * angle) * adjustedXRadius;
            float z = Mathf.Cos(Mathf.Deg2Rad * angle) * adjustedYRadius;

            line.SetPosition(i, new Vector3(x, y, z));
            angle += angleStep;
        }
    }

    public void CreateObjectsAroundPoint(int num, Vector3 point, float xRadius, float yRadius)
    {
        // Clear existing objects
        ClearObjects(true);

        // Ensure at least one object is created
        if (num < 1) return;

        // Temporary list to track new objects
        List<GameObject> newObjects = new List<GameObject>();

        for (int i = 0; i < num; i++)
        {
            // Distance around the ellipse
            var radians = 2 * Mathf.PI / num * i;

            // Calculate the position on the ellipse
            var x = Mathf.Cos(radians) * xRadius;
            var z = Mathf.Sin(radians) * yRadius;

            var spawnPos = point + new Vector3(x, 0, z); // Set position on ellipse

            // Instantiate and position the object
            var obj = Instantiate(objectPrefab, spawnPos, Quaternion.identity);

            // Set tag and name
            obj.tag = "ObjectonCircle";
            obj.name = "Object on Circle";

            // Rotate the object to face the center
            obj.transform.LookAt(point);

            // Add the object to the list
            newObjects.Add(obj);
        }

        // Update the objects array with the newly created objects
        objects = newObjects.ToArray();
    }

    private void AdjustPositions(int num, Vector3 point, float xRadius, float yRadius)
    {
        if (objects == null || objects.Length == 0 || num <= 0) return;

        for (int i = 0; i < objects.Length; i++)
        {
            if (objects[i] == null) continue; // Skip if the object was destroyed

            // Distance around the ellipse
            var radians = 2 * Mathf.PI / num * i;

            // Calculate the new position on the ellipse
            var x = Mathf.Cos(radians) * xRadius;
            var z = Mathf.Sin(radians) * yRadius;

            var spawnPos = point + new Vector3(x, 0, z); // Set position on ellipse

            // Update object position
            objects[i].transform.position = spawnPos;

            // Rotate the object to face the center
            objects[i].transform.LookAt(point);
        }
    }

    public void ClearObjects(bool createNew)
    {
        GameObject[] objectsOnCircle = GameObject.FindGameObjectsWithTag("ObjectonCircle");
        foreach (var obj in objectsOnCircle)
        {
            if (Application.isPlaying)
            {
                Destroy(obj);
            }
            else
            {
                DestroyImmediate(obj);
            }
        }

        // Clear the objects array
        objects = new GameObject[0];

        if (!createNew)
        {
            numOfObjects = 0;
        }
    }

    private void UpdateDebugText()
    {
        if (debugText == null) return;

        // Initialize radius values if not done yet
        if (initialXRadius < 0) initialXRadius = xradius;
        if (initialYRadius < 0) initialYRadius = yradius;
        if (initialBothRadius < 0) initialBothRadius = changeBothRadius;

        // Get current and initial positions of the reference object
        Vector3 currentPosition = referenceObject != null ? referenceObject.transform.position : Vector3.zero;

        // Format debug text with consistent colors and correct formatting
        debugText.text = string.Format(
            "<color=red><b>Debug Info:</b></color>\n\n" + // Header in red
            "<color=white>Current Radii:</color> <color=green>X = {0:F2}, Y = {1:F2}, Both = {2:F2}</color>\n" +
            "<color=blue>Initial Radii:</color> <color=green>X = {3:F2}, Y = {4:F2}, Both = {5:F2}</color>\n" +
            "<color=yellow>Object Position:</color> <color=green>{6}</color>\n" +
            "<color=orange>Initial Position:</color> <color=green>{7}</color>",
            xradius, yradius, changeBothRadius,
            initialXRadius, initialYRadius, initialBothRadius,
            currentPosition.ToString("F2"), initialObjectPosition.ToString("F2")
        );

        // Adjust text size for better readability
        debugText.fontSize = 18; // Smaller text size for better fit
    }
}

In general you seem to be facing a ‘scope’ issue. Perhaps there are a few bits you may want to consider.

If you wish for a bunch of objects to move (you say hight-wise, i.e. in y direction) with some object, perhaps it might prove useful to have the latter object as the parent object of said bunch. Having said so, it seems your instantiated objects are created outside of your object with a circle. With ‘parentless’ objects you may be facing an offset because they are not moving in the scope you think the objects are moving. That is to say you perhaps want them moving in ‘local’ measurements, but actually instructing them to move globally. So they move not enough or too much.

At any rate, you may want to instantiate your orbiting objects in Hierarchy under the guiding gameObject. There are several instantiation methods you can call, others might prove more convenient to the one you have now, e.g. the one allowing you to instantiate an object under a parent directly var obj = Instantiate(objectPrefab, gameObject.GetComponent<Transform>()), or modify your code like so var obj = Instantiate(objectPrefab, spawnPos, Quaternion.identity, gameObject.GetComponent<Transform>());. If you stay with what you have, try moving those created game objects under your main object. You can do so after the line 24 with obj.SetParent(gameObject, true); and then set their local position.

Yes, in addition you may benefit from using the transform.localPosition = new Vector3(x, y, z); approach, as an object’s position would then be relative to its parent transform, thus in line 19 objects[i].transform.localPosition = spawnPosition;

If you decide not to have those instantiated objects as children of the gameObject to which your script is attached, you just need make sure the amounts of movements are accurately calculated. Again, now you seem to have a local-world mismatch. It may be more work, but it can be done, too.