Unity3D 正六邊形,環狀擴散,緊密分布,的程序
需求:中心有個正六邊形,輸入圍繞中心擴散的環數,自動創建和擺放。
大概就是這樣的吧,我覺得這個非常輕鬆的就可以搞定了。啊~~~~~啊~~~ 五環~~,你比四環多一環,啊~~~~啊~~~五環~~,你比六環少一環~~~可是,到底每環要放多少個六邊形?經過我縝密的觀察發現一個規律。
如果假設第一個環編號為1,那麼每個換六邊形的數量就是 環數*6。啊~~~~~啊~~~ 五環~~,一環就是紫~禁~城~~~~。
可是擺放的具體位置是哪裡?既然是圓形,那就需要知道 角度 和 半徑 就可以依據圓形坐標公式算出來了。
二維圓上的點坐標公式:
X = Mathf.Sin(角度*Mathf.PI/180) * 半徑
Y = Mathf.Cos(角度*Mathf.PI/180) * 半徑
有人可能問,上面寫的公式原理是啥?哈~哈~哈~~~~
我也是---
啊~~~~~啊~~~ 五環~~,你比四環多一環,啊~~~~啊~~~五環~~~~~~參見:已知圓心,半徑,角度,求圓上的點坐標 - - 博客頻道 - CSDN.NET
-----半徑是啥?
緊密擺放的話,半徑就是六邊形的寬度。而每一環的半徑就是環數*第一個半徑。
好了這個可以大概構建一個循環體了。=========下面搭建循環體============
Int RoundMax = 10;//最大環數變數
float Radius = 1f;//六邊形最短寬度
for(int round = 1;round<=RoundMax;round++)//每一層環的循環體
{
for(環上每個六邊形循環體)
Vector2 = new Vector2(Mathf.Sin(角度*Mathf.PI/180) * Radius * round, Mathf.Cos(角度*Mathf.PI/180) * Radius * round);
}
}
===============
那麼角度又是多少?
360 ÷ 每一環的總數 = 間隔的角度
間隔的角度 × 當前序號 = 當前角度
=========下面添加每一環的計算程序============
Int RoundMax = 10;//最大環數變數
float Radius = 1f;//六邊形最短寬度
for(int round = 1;round<=RoundMax;round++)//每一層環的循環體
{
for(int id = 0; id<=round*6; id++)//當前環的總個數 = round*6
{
Vector2 Pos= new Vector2(
Mathf.Sin(360/(round*6)*id*Mathf.PI/180) * Radius * round,
Mathf.Cos(360/(round*6)*id*Mathf.PI/180) * Radius * round
);
}
}
=======下面轉為三維向量========
Int RoundMax = 10;//最大環數變數
float Radius = 1f;//六邊形最短寬度
for(int round = 1;round<=RoundMax;round++)//每一層環的循環體
{
for(int id = 0; id<=round*6; id++)//當前環的總個數 = round*6
{
Vector3 Pos= new Vector3(
Mathf.Sin(360/(round*6)*id*Mathf.PI/180) * Radius * round,
0,
Mathf.Cos(360/(round*6)*id*Mathf.PI/180) * Radius * round
);
}
}
=====距離勝利還有一步 下面引入模型和創建========
GameObject Zero_OBJ;//六邊形物體
Int RoundMax = 10;//最大環數變數
float Radius = 1f;//六邊形最短寬度
for(int round = 1;round<=RoundMax;round++)//每一層環的循環體
{
for(int id = 0; id<=round*6; id++)//當前環的總個數 = round*6
{
Vector3 Pos= new Vector3(
Mathf.Sin(360/(round*6)*id*Mathf.PI/180) * Radius * round + ,
0,
Mathf.Cos(360/(round*6)*id*Mathf.PI/180) * Radius * round
);
Instantiate(Zero_OBJ,
Zero_OBJ.transform.position.+ Pos ,//依據物體坐標偏移
Quaternion.identity);
}
}
=======哈哈哈 我是在佩服我的智慧========
天空飄來五個字 那都不是事
運行結果
我去~~~真圓~~~~~接下的十幾分鐘...
=================然後開始奮發圖強的思考=============
其實還是有幾個擺放正確的六邊形也就是說除了這0 , 60,120 , 180 , 240 , 300 角度的六邊形,其餘六邊形其實不是正圓分布,而是直線分布。如果是直線分布,就需要依據兩點的坐標計算出排列的矢量方向,然後依據半徑擺放就可以了。
=====接下吧正確位置寫入 Pos_6[]========
GameObject Zero_OBJ;//六邊形物體
Int RoundMax = 10;//最大環數變數
float Radius = 1f;//六邊形最短寬度
for(int round = 1;round<=RoundMax;round++)//每一層環的循環體
{
Vector3 [] Pos_6 = new Vector3[6];//記錄正確6個位置的數組
for(int id = 0; id<= 6; id++)//當前環的總個數 = round*6
{
Pos_6[i] = new Vector3(
Mathf.Sin(360/(round*6)*id*Mathf.PI/180) * Radius * round + ,
0,
Mathf.Cos(360/(round*6)*id*Mathf.PI/180) * Radius * round
);
Instantiate(Zero_OBJ,
Zero_OBJ.transform.position.+ Pos_6[i] ,//依據物體坐標偏移
Quaternion.identity);
}
}
中間的六邊形個數規律是:
每個六邊形偏移距離是:
=======接下來插入之間的六邊形========GameObject Zero_OBJ;//六邊形物體
Int RoundMax = 10;//最大環數變數
float Radius = 1f;//六邊形最短寬度
for(int round = 1;round<=RoundMax;round++)//每一層環的循環體
{
Vector3 [] Pos_6 = new Vector3[6];//記錄正確6個位置的數組
for(int id = 0; id<= 6; id++)
{
Pos_6[i]= new Vector3(
Mathf.Sin(360/(round*6)*id*Mathf.PI/180) * Radius * round + ,
0,
Mathf.Cos(360/(round*6)*id*Mathf.PI/180) * Radius * round
);
Instantiate(Zero_OBJ,
Zero_OBJ.transform.position+ Pos_6[i] ,//依據物體坐標偏移
Quaternion.identity);
}
if(round >1)//第2圈開始執行插入
{
for(int id = 0; id<= 6; id++)//逐個區間插入
{
int NextID =( id+1)%6;//獲取下一個位置ID,在0~5中循環取值
Vector3 Orientation = Vector3.Normalize(Pos_6[NextID]-Pos_6[id])//單位朝向(下一個點-當前點)
for(int addID = 1;addID <round;addID ++)//循環插入
{
//----------插入點 = 單位方向*當前偏移距離+起點偏移
Vector3 Insert_Pos =
Orientation
*(Radius * addID )
+( Pos_6[addID ] + Zero_OBJ.transform.position);
//-------------------------------------------------------------
Instantiate(Zero_OBJ,Insert_Pos ,Quaternion.identity);
}
}
}
}
========運行結果===========
如果有更簡單的方法,求賜教。========我整理後的程序=========
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlacingHexagon_CRomputer : MonoBehaviour {
tpublic GameObject Zero_OBJ;//六邊形物體
tpublic int RoundMax = 10;//最大環數變數
tpublic float Radius = 1f;//六邊形最短寬度
tprivate Vector3 [] Pos_6 = new Vector3 [6];//記錄6個位置的數組
t// Use this for initialization
tvoid Start () {
ttInstantiate(Zero_OBJ, transform.position ,tQuaternion.identity);//創建中心物體
ttfor(int round = 1;round<=RoundMax;round++){//每一層環的循環體
tttfor(int id = 0; id < 6; id++){//放置每一環的頂點物體
ttttPos_6 [id] = new Vector3(Mathf.Sin(60*id * Mathf.PI / 180) * Radius * round , 0f , Mathf.Cos(60*id * Mathf.PI /180) * Radius * round) + transform.position ;//記錄6個正確位置
ttttInstantiate(Zero_OBJ, Pos_6[id] , Quaternion.identity);//生成物體
ttt}
tttif(round >1)//第2圈開始執行插入
ttt{
ttttfor(int id = 0; id < 6; id++)//逐個區間插入物體
tttt{
tttttint NextID =( id+1)%6;//獲取下一個位置ID,在0~5中循環取值
tttttVector3 Orientation = Vector3.Normalize( Pos_6[NextID]-Pos_6[id] );//單位朝向(下一個點-當前點)
tttttfor(int addID = 1; addID < round ; addID++) //循環插入
ttttt{
ttttttVector3 Insert_Pos = Orientation *(Radius * addID)+Pos_6[id];//插入點 = 單位方向*當前偏移距離 + 起點偏移
ttttttInstantiate(Zero_OBJ,Insert_Pos ,Quaternion.identity); //生成中間物體
ttttt}
tttt}
ttt}
tt}
t}
t// Update is called once per frame
tvoid Update () {
t}
}
========@鄧浩給出的遞歸思路=========
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlacingHexagon_DengHao : MonoBehaviour {
tpublic GameObject Zero_OBJ;//六邊形物體
tpublic int RoundMax = 10;//最大環數變數
tpublic float Radius = 1f;//六邊形最短寬度
tprivate List<Vector3> Hexagon_List =new List<Vector3>();//已創建位置列表
tvoid Placing(int n,Vector3 Pos)//擺放函數(遞歸調用)(剩餘環數.當前位置)
t{
ttif (Search (Pos)) {//如果當前位置無物體
tttInstantiate(Zero_OBJ,Pos,Quaternion.identity);//創建物體
tttHexagon_List.Add (Pos);//記錄位置
tttif (n > 0) {//如果環大於0繼續遞歸調用
ttttfor(int i=0;i<6;i++){//向周圍探測
tttttPlacing(n-1,new Vector3(Mathf.Sin(60 * i * Mathf.PI / 180) , 0f , Mathf.Cos(60 * i * Mathf.PI / 180)) * Radius + Pos);//探測(環數-1,周圍新位置)
tttt}
ttt}
tt}
t}
tbool Search(Vector3 Pos)//檢索函數(無物體返回真,有物體返回假)
t{
tttfor (int i = 0; i < Hexagon_List.Count; i++) {//逐個檢測位置列表
ttttif (Vector3.Distance (Pos, Hexagon_List [i]) < Radius * 0.2f) {//如果距離很小說明有物體
tttttreturn false;//返回假
tttt}
ttt}
tttreturn true;//遍歷完說明位置上無物體返回真
t}
t// Use this for initialization
tvoid Start () {
ttPlacing (RoundMax, transform.position);//第一次調用遞歸(圈數,當前位置)
t}
t// Update is called once per frame
tvoid Update () {
t}
}
理論是沒有問題,可能Unity3D的運行機制的問題。========Lv9給出的左右梯形循環創建=========
public class PlacingHexagon_Lv9 : MonoBehaviour {
tpublic GameObject Zero_OBJ;//六邊形物體
public int RoundMax = 10;//最大環數變數
public float Radius = 1f;//六邊形最短寬度
// Use this for initialization
tvoid Start () {
tt//循環列創建
ttfor (int dx = 0; dx <= RoundMax; dx++) {
ttt//向右創建一個高RoundMax的梯形。
ttt//循環列上每個物體(「最下方行」到 「最上方行-列」 循環)每列少一個。
tttfor (int dy = -RoundMax; dy <= RoundMax - dx; dy++) {
tttt//擺放位置=橫向偏移(外切圓半徑與內切圓半徑比為1.732)的一半,0,縱向向上偏移半個
ttttVector3 Pos = new Vector3 (dx*Mathf.Sqrt(3)*0.5f, 0, dy + dx * 0.5f)*Radius;
ttttInstantiate (Zero_OBJ, transform.position + Pos,tQuaternion.identity);
tttt//如果不在中心列上,鏡像創建左側
ttttif(dx!=0){
tttttInstantiate (Zero_OBJ, transform.position + new Vector3(-Pos.x,Pos.y,Pos.z),tQuaternion.identity);
tttt}
ttt}
tt}
t}
t// Update is called once per frame
tvoid Update () {
t}
}
推薦閱讀:
※從零開始學基於ARKit的Unity3d遊戲開發系列11
※Unity 內存優化 和 內存池使用實踐
※Unity3D熱更新LuaFramework入門實戰(2)——資源熱更新
※【補遺】基於體積的大氣散射Shader
TAG:Unity游戏引擎 |