Unity3D 程式遊樂園 – 隨機生成物件在球體表面的程式

生成物件在球體表面

目的:

這裡分享在球體表面生成物件的開發思路,透過C Sharp Script ,亂數生成X,Y的座標值,並帶入球型方程式得出一組座標值,並可將亂數值控制在半球體或水平線高度以上。可自訂隨機生成數次。本代碼以滑鼠觸發,每按一下可生成(Instantiate)數個物件。

程式主要兩大部分,第一部分為亂數生成座標,並最後在隨機控制Z軸座標,生成在球面的左側或右側。第二部分為生成數個物件的程式碼。

成果:

Spawn_object_on_surface_of_sphere

將物件亂數生成在球體表面。

原始程式碼:

首先,將此原代碼複製貼上另存至你的Script中。

這邊暫稱Spawn Orange,可以自己改變名字。

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

public class SpawnOrange : MonoBehaviour
 {
     public float tempX, tempY, tempZ;
     private float tempZ2;
     public float BallToSpawnRadius;
     public GameObject ToBeSpawnObject;
     public int SpawnTimes;
     private float tempSQRTRadius;
     public float clampedSpwanHeight;
     [SerializeField] Transform refPos;
     private int i=1;

// Start is called before the first frame update
void Start()
{

    //check if the original reference object is null, give 0,0,0 as ref.
    if (refPos == null)
    {
        Vector3 RandPos = new Vector3(0f, 0f, 0f);
    }

}

// Update is called once per frame
void Update()
{

    if (Input.GetMouseButtonDown(0))
    {
        i = 1;
        while (i < SpawnTimes)
        {
            PreCalculateSphere();
            i++;
        }
    }


}

public void PreCalculateSphere()
{
    //Randomize Oritentation on sphere
    // 球面的方程式為(x−x0)2+(y−y0)2+(z−z0)2=r2


    tempSQRTRadius = Mathf.Pow(BallToSpawnRadius, 2);
    tempX = Random.Range(-BallToSpawnRadius, BallToSpawnRadius);
    tempY = Random.Range((0+ clampedSpwanHeight), BallToSpawnRadius);
    tempZ2 = tempSQRTRadius - (Mathf.Pow((tempX - refPos.position.x), 2) + Mathf.Pow((tempY - refPos.position.y), 2));





    if (tempZ2 > 0 )
    {

        tempZ = Mathf.Sqrt(tempZ2);
        //Debug.Log("TempX=" + tempX.ToString() + " " + "TempY=" + tempY.ToString() + " " + "TempZ=" + tempZ.ToString());
        SpawningOrange();
    }
    else {
        PreCalculateSphere();
    }

}

public void SpawningOrange()
{
    // Random Z direction 
        float Zdirection = Random.Range(0,10);
        if (Zdirection < 5)
            {
            tempZ = -tempZ;
            };
        Vector3 RandPos = new Vector3(tempX, tempY, tempZ);

        Instantiate(ToBeSpawnObject, RandPos, Quaternion.identity);


}
}

開發思路重點提要:

A. 第一個步驟就是要先找到數學方程式,可以到Google搜尋 球型方程式。

若設球面S的球心O(x0,y0,z0),半徑為r,

則球面的方程式為(x−x0) 2 +(y−y0) 2 +(z−z0) 2 =r 2

B. 再將此方程式轉為Unity3D 的C#程式碼。

這邊用到幾個數學函式 Mathf.*** API:

Mathf.Pow

Pow 就是平方,乘兩次的意思。

Mathf.Sqrt

Sqrt 就是開根號,英文叫做Square Root。

Mathf.Abs

Abs 就是取絕對值,就是去掉負的直接轉正值。

上述的函數用法可以點擊文字連結,直接跳出原廠說明文件。

這段就是計算球體的方程式,先亂數生成兩個數值當作X與Y。

Z則是由球型方程式反推出來。此時會有兩個解,+Z或-Z,我們再利用亂數隨機給Z值正負值。

tempSQRTRadius = Mathf.Pow(BallToSpawnRadius, 2);
tempX = Random.Range(-BallToSpawnRadius, BallToSpawnRadius);
tempY = Random.Range((0+ clampedSpwanHeight), BallToSpawnRadius);
tempZ2 = tempSQRTRadius – (Mathf.Pow((tempX – refPos.position.x), 2) + Mathf.Pow((tempY – refPos.position.y), 2));

而Y值有加上一個 clampedSpwanHeight ,如此一來就能規範生成的高度。

clamp_height

使用方法:

套用此程式碼的方式非常簡單,先將Script拖曳到場景中的任一個物件。

並且指定好你要生成的物件ToBeSpawnObject,輸入要生成的次數SpawnTimes也就是數量,更重要的是球體的半徑BallToSpawnRadius。最後可以輸入要限制的高度,也就是從多高的地方開始長出ClampedSpawnHeight。而RefPos就是圓心的位置,若不指定則從0,0,0原點當作圓心開始生成。

如此一來按下撥放,在畫面內點一下滑鼠左鍵,就能依照設定的生成次數,自動隨機亂數生成物件數量。

生成數十顆已經可以看出趨近於半球型
密集的生成,已佈成半球體形狀。

可自行改變程式碼把半球體表面生成應用在需要的地方,例如自駕車的圓環障礙物等。

結論:

本文透過一個球型亂數表面生成物件案例,提供大家開發幾何形數學的開發思維,也包含了亂數產生數值,以及物件生成的方法 (Instantiate )。

同樣的思路可以用在任何數學相關的開發,例如正弦波位置、方塊物體等等。

都是先找方程式,再將座標或Transform產生出來,最後再做進一步的應用。希望對有需要的人有幫助。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *