Skip to content

Instantly share code, notes, and snippets.

@rngtm
Last active November 26, 2018 14:40
Show Gist options
  • Save rngtm/0b6369ff2e7f8592729b2bd1cecc71a3 to your computer and use it in GitHub Desktop.
Save rngtm/0b6369ff2e7f8592729b2bd1cecc71a3 to your computer and use it in GitHub Desktop.
大量の球体をワンメッシュで作成し、ランダムな位置に並べるスクリプト。
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(GenerateManySphere))]
public class GenerateManySphereInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var gs = target as GenerateManySphere;
EditorGUILayout.LabelField("VertexCount", (gs.SphereCount * gs.CountXZ * gs.CountY).ToString());
}
}
#endif
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class GenerateManySphere : MonoBehaviour
{
[SerializeField] bool generateMeshOnUpdate = false;
[SerializeField] int sphereCount = 50; // 球体の個数
[SerializeField] int yCount = 12; // Y軸を直径とする円の角度の分割数
[SerializeField] int xzCount = 12; // XZ平面上での円の角度の分割数
[SerializeField] float positionRandom = 8f;
[SerializeField] int randomSeed = 100;
[SerializeField] float sphereSize = 1f;
private Mesh mesh;
public int SphereCount => sphereCount;
public int CountY => yCount;
public int CountXZ => xzCount;
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
Create();
}
void Update()
{
if (generateMeshOnUpdate)
{
Create();
}
}
void Create()
{
if (yCount < 3) { yCount = 3; }
if (xzCount < 3) { xzCount = 3; }
Random.InitState(randomSeed);
int vertexCountXZ = xzCount + 1;
// 法線・頂点座標の作成
Vector3[] vertices = new Vector3[sphereCount * vertexCountXZ * yCount]; //頂点座標
Vector3[] normals = new Vector3[vertices.Length]; // 法線
Vector2[] uv = new Vector2[vertices.Length];
int vi = 0;
for (int si = 0; si < sphereCount; si++)
{
Vector3 position = (
new Vector3(Random.value, Random.value, Random.value) - Vector3.one / 2f
) * positionRandom;
for (int yi = 0; yi < yCount; yi++)
{
float radian1 = yi * Mathf.PI / (yCount - 1) - Mathf.PI / 2f;
float y = Mathf.Sin(radian1);
for (int xi = 0; xi < vertexCountXZ; xi++)
{
float radian2 = xi * 2f * Mathf.PI / xzCount;
float x = Mathf.Cos(radian1) * Mathf.Cos(radian2);
float z = Mathf.Cos(radian1) * Mathf.Sin(radian2);
uv[vi] = new Vector2((float)si / sphereCount, 0f);
normals[vi] = new Vector3(x, y, z);
vertices[vi++] = new Vector3(x, y, z) * sphereSize + position;
}
}
}
// 頂点インデックスの作成
int[] triangles = new int[sphereCount * xzCount * (yCount - 1) * 6];
int ti = 0;
int triangleOffset = 0;
for (int si = 0; si < sphereCount; si++)
{
for (int i = 0; i < yCount - 1; i++)
{
for (int j = 0; j < xzCount; j++)
{
triangles[ti++] = triangleOffset + vertexCountXZ; // 2
triangles[ti++] = triangleOffset + 1; // 1
triangles[ti++] = triangleOffset + 0; // 0
triangles[ti++] = triangleOffset + 1 + vertexCountXZ; // 3
triangles[ti++] = triangleOffset + 1; // 1
triangles[ti++] = triangleOffset + vertexCountXZ; // 2
triangleOffset += 1;
}
triangleOffset += 1;
}
}
// メッシュ作成
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
}
}
@rngtm
Copy link
Author

rngtm commented Nov 26, 2018

大量の球体をワンメッシュで生成します。 頂点数が65536を超えると表示がおかしくなるので注意
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment