Skip to content

Instantly share code, notes, and snippets.

@rngtm
Last active November 26, 2018 14:40
Show Gist options
  • Select an option

  • Save rngtm/0b6369ff2e7f8592729b2bd1cecc71a3 to your computer and use it in GitHub Desktop.

Select an option

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

rngtm commented Nov 26, 2018

Copy link
Copy Markdown
Author

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

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