How to generate random objects inside drawn circle area?

Viewed 46

The first script draw circle that i can control it's radius size and make the circle tin or wider :

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
}

Drawn Circle

The second script is generating objects i'm using the range slider to change the amount of object to be generated :

Generating Objects

now i want to be able to use both scripts to be able to generate the objects inside the drawn circle area when i will change the rang slider of the amount of objects to generate the variable numberOfObjects it will generate the objects inside the drawn circle area and will position the objects on the terrain depending the terrain height.

1 Answers

From the answer proposed, you'd only need to randomize the radius, and repeat the method call for as many objects you'd like. Like so:

private void SpawnSphereOnEdgeRandomly3D(float maxRadius)
{
    float radius = Random.Range(-0f, maxRadius);
    Vector3 randomPos = Random.insideUnitSphere * radius;
    randomPos += transform.position;
    randomPos.y = 0f;
        
    Vector3 direction = randomPos - transform.position;
    direction.Normalize();
        
    float dotProduct = Vector3.Dot(transform.forward, direction);
    float dotProductAngle = Mathf.Acos(dotProduct / transform.forward.magnitude * direction.magnitude);
        
    randomPos.x = Mathf.Cos(dotProductAngle) * radius + transform.position.x;
    randomPos.z = Mathf.Sin(dotProductAngle * (Random.value > 0.5f ? 1f : -1f)) * radius + transform.position.z;
        
    GameObject go = Instantiate(_spherePrefab, randomPos, Quaternion.identity);
    go.transform.position = randomPos;
}
Related