Net.Like.Xue.Tokyo/Assets/Plugins/MeshCombineStudio/Scripts/Mesh/ObjectSpawner.cs

131 lines
4.3 KiB
C#
Raw Normal View History

2024-11-03 16:42:23 +08:00
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MeshCombineStudio
{
[ExecuteInEditMode]
public class ObjectSpawner : MonoBehaviour
{
public GameObject[] objects;
public Vector3 spawnArea = new Vector3(512, 512, 512);
public float density = 0.5f;
public Vector2 scaleRange = new Vector2(0.5f, 2f);
public Vector3 rotationRange = new Vector3(5, 360, 5);
public Vector2 heightRange = new Vector2(0, 1);
public float scaleMulti = 1;
public float metersBetweenSpawning = 2;
public bool spawnInRuntime;
public bool spawn;
public bool deleteChildren;
Transform t;
private void Awake()
{
t = transform;
if (spawnInRuntime && Application.isPlaying)
{
Spawn();
}
}
private void Update()
{
if (spawn)
{
spawn = false;
Spawn();
}
if (deleteChildren)
{
deleteChildren = false;
DeleteChildren();
}
}
public void DeleteChildren()
{
Transform[] transforms = GetComponentsInChildren<Transform>();
for (int i = 0; i < transforms.Length; i++)
{
if (t != transforms[i] && transforms[i] != null) DestroyImmediate(transforms[i].gameObject);
}
#if UNITY_EDITOR
if (!Application.isPlaying) UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(gameObject.scene);
#endif
}
void SetObjectsActive(bool active)
{
for (int i = 0; i < objects.Length; i++)
{
objects[i].SetActive(active);
}
}
public void Spawn()
{
SetObjectsActive(true);
Bounds bounds = new Bounds();
bounds.center = transform.position;
bounds.size = spawnArea;
float xStart = bounds.min.x;
float xEnd = bounds.max.x;
float yStart = bounds.min.y;
float yEnd = bounds.max.y;
float zStart = bounds.min.z;
float zEnd = bounds.max.z;
int objectCount = objects.Length;
float halfRes = metersBetweenSpawning * 0.5f;
float heightOffset = transform.lossyScale.y * 0.5f;
int count = 0;
for (float z = zStart; z < zEnd; z += metersBetweenSpawning)
{
for (float x = xStart; x < xEnd; x += metersBetweenSpawning)
{
for (float y = yStart; y < yEnd; y += metersBetweenSpawning)
{
int index = Random.Range(0, objectCount);
float spawnValue = Random.value;
if (spawnValue < density)
{
Vector3 pos = new Vector3(x + Random.Range(-halfRes, halfRes), yStart + (Random.Range(0, bounds.size.y) * Random.Range(heightRange.x, heightRange.y)), z + Random.Range(-halfRes, halfRes));
if (pos.x < xStart || pos.x > xEnd || pos.y < yStart || pos.y > yEnd || pos.z < zStart || pos.z > zEnd) continue;
pos.y += heightOffset;
Vector3 eulerAngles = new Vector3(Random.Range(0, rotationRange.x), Random.Range(0, rotationRange.y), Random.Range(0, rotationRange.z));
GameObject go = (GameObject)Instantiate(objects[index], pos, Quaternion.Euler(eulerAngles));
float scale = Random.Range(scaleRange.x, scaleRange.y) * scaleMulti;
go.transform.localScale = new Vector3(scale, scale, scale);
go.transform.parent = t;
++count;
}
}
}
}
SetObjectsActive(false);
#if UNITY_EDITOR
if (!Application.isPlaying) UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(gameObject.scene);
#endif
Debug.Log("Spawned " + count);
}
private void OnDrawGizmosSelected()
{
Gizmos.DrawWireCube(transform.position + new Vector3(0, 0, 0), spawnArea);
}
}
}