preview Link : https://velog.io/@suhan0304/Unity-Planet-Generation-The-Sphere
gitHub Link : https://github.com/suhan0304/Planet-Generation
PlanetGeneration
생성한 행성의 모양과 색상 설정을 유지하기 위해 여러 속성을 관리할 스크립트를 작성해보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu()]
public class ShapeSettings : ScriptableObject
{
public float planetRadius = 1;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShapeGenerator
{
ShapeSettings settings;
public ShapeGenerator(ShapeSettings settings)
{
this.settings = settings;
}
public Vector3 CalculatePoinOnPlanet(Vector3 pointOnUnitSphere)
{
return pointOnUnitSphere * settings.planetRadius;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu()]
public class ColorSettings : ScriptableObject
{
public Color planetColor;
}
이제 Planet해서 설정 스크립터블 오브젝트를 불러와서 생성을 처음 생성할 때 해당 설정을 사용한다.
public ShapeSettings shapeSettings;
public ColorSettings colorSettings;
[HideInInspector]
public bool shapeSettingFoldout;
[HideInInspector]
public bool colorSettingFoldout;
ShapeGenerator shapeGenerator;
private void OnValidate()
{
GeneratePlanet();
}
public void GeneratePlanet()
{
Initialize();
GenerateMesh();
GenerateColors();
}
public void OnShapeSettingsUpdated()
{
Initialize();
GenerateMesh();
}
public void OnColorSettingsUpdated()
{
Initialize();
GenerateColors();
}
void GenerateMesh()
{
foreach (TerrainFace face in terrainFaces)
{
face.ConstructMesh();
}
}
void GenerateColors()
{
foreach (MeshFilter m in meshFilters)
{
m.GetComponent<MeshRenderer>().sharedMaterial.color = colorSettings.planetColor;
}
}
이후에 Planet의 shapeGnerator를 사용해
Vector2 percent = new Vector2(x, y) / (resolution - 1);
Vector3 pointOnUnitCube = localUp + (percent.x - .5f) * 2 * axisA + (percent.y - .5f) * 2 * axisB;
Vector3 pointOnUnitSphere = pointOnUnitCube.normalized;
vertices[i] = shapeGenerator.CalculatePoinOnPlanet(pointOnUnitSphere);
스크립터블 오브젝트로 ColorSettings, ShapeSettings를 생성해서 인스펙스 창으로 드래그 드랍해서 Planet의 변수들을 초기화 해준다.
행성을 자체적으로 조절할 수 있도록 Planet Editor 스크립트를 추가로 작성한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Planet : MonoBehaviour {
[Range(2,256)]
public int resolution = 10;
public bool autoUpdate = true;
public ShapeSettings shapeSettings;
public ColorSettings colorSettings;
[HideInInspector]
public bool shapeSettingFoldout;
[HideInInspector]
public bool colorSettingFoldout;
ShapeGenerator shapeGenerator;
[SerializeField, HideInInspector]
MeshFilter[] meshFilters;
TerrainFace[] terrainFaces;
private void OnValidate()
{
GeneratePlanet();
}
void Initialize()
{
shapeGenerator = new ShapeGenerator(shapeSettings);
if (meshFilters == null || meshFilters.Length == 0)
{
meshFilters = new MeshFilter[6];
}
terrainFaces = new TerrainFace[6];
Vector3[] directions = { Vector3.up, Vector3.down, Vector3.left, Vector3.right, Vector3.forward, Vector3.back };
for (int i = 0; i < 6; i++)
{
if (meshFilters[i] == null)
{
GameObject meshObj = new GameObject("mesh");
meshObj.transform.parent = transform;
meshObj.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));
meshFilters[i] = meshObj.AddComponent<MeshFilter>();
meshFilters[i].sharedMesh = new Mesh();
}
terrainFaces[i] = new TerrainFace(shapeGenerator, meshFilters[i].sharedMesh, resolution, directions[i]);
}
}
public void GeneratePlanet()
{
Initialize();
GenerateMesh();
GenerateColors();
}
public void OnShapeSettingsUpdated()
{
if (autoUpdate)
{
Initialize();
GenerateMesh();
}
}
public void OnColorSettingsUpdated()
{
if (autoUpdate)
{
Initialize();
GenerateColors();
}
}
void GenerateMesh()
{
foreach (TerrainFace face in terrainFaces)
{
face.ConstructMesh();
}
}
void GenerateColors()
{
foreach (MeshFilter m in meshFilters)
{
m.GetComponent<MeshRenderer>().sharedMaterial.color = colorSettings.planetColor;
}
}
}
이제 인스펙터에 값을 적용하면 자동으로 Planet의 update 함수를 불러오면서 실시간으로 Unity Editor에 적용되는 것을 확인할 수 있다.
이제 행성의 색상과 크기를 인스펙터로 설정하면서 실시간으로 씬 창으로 행성을 확인할 수 있다.