You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
3.6 KiB
158 lines
3.6 KiB
// HACK:
|
|
// This will work out of the box, but it's intended to be an example of how to approach
|
|
// procedural decoration like this.
|
|
// A better approach would be to operate on the geometry itself.
|
|
|
|
namespace Mapbox.Unity.MeshGeneration.Modifiers
|
|
{
|
|
using Mapbox.Unity.MeshGeneration.Data;
|
|
using Mapbox.Unity.MeshGeneration.Components;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
|
|
[CreateAssetMenu(menuName = "Mapbox/Modifiers/Spawn Inside Modifier")]
|
|
public class SpawnInsideModifier : GameObjectModifier
|
|
{
|
|
[SerializeField]
|
|
int _spawnRateInSquareMeters;
|
|
|
|
[SerializeField]
|
|
int _maxSpawn = 1000;
|
|
|
|
[SerializeField]
|
|
GameObject[] _prefabs;
|
|
|
|
[SerializeField]
|
|
LayerMask _layerMask;
|
|
|
|
[SerializeField]
|
|
bool _scaleDownWithWorld;
|
|
|
|
[SerializeField]
|
|
bool _randomizeScale;
|
|
|
|
[SerializeField]
|
|
bool _randomizeRotation;
|
|
|
|
int _spawnedCount;
|
|
|
|
private Dictionary<GameObject, List<GameObject>> _objects;
|
|
private Queue<GameObject> _pool;
|
|
|
|
public override void Initialize()
|
|
{
|
|
if (_objects == null || _pool == null)
|
|
{
|
|
_objects = new Dictionary<GameObject, List<GameObject>>();
|
|
_pool = new Queue<GameObject>();
|
|
}
|
|
}
|
|
|
|
public override void Run(VectorEntity ve, UnityTile tile)
|
|
{
|
|
_spawnedCount = 0;
|
|
var bounds = ve.Mesh.bounds;
|
|
var center = ve.Transform.position + bounds.center;
|
|
center.y = 0;
|
|
|
|
var area = (int)(bounds.size.x * bounds.size.z);
|
|
int spawnCount = Mathf.Min(area / _spawnRateInSquareMeters, _maxSpawn);
|
|
while (_spawnedCount < spawnCount)
|
|
{
|
|
var x = UnityEngine.Random.Range(-bounds.extents.x, bounds.extents.x);
|
|
var z = UnityEngine.Random.Range(-bounds.extents.z, bounds.extents.z);
|
|
var ray = new Ray(center + new Vector3(x, 100, z), Vector3.down * 2000);
|
|
|
|
RaycastHit hit;
|
|
if (Physics.Raycast(ray, out hit, 150, _layerMask))
|
|
{
|
|
var index = UnityEngine.Random.Range(0, _prefabs.Length);
|
|
var transform = GetObject(index, ve.GameObject).transform;
|
|
transform.position = hit.point;
|
|
if (_randomizeRotation)
|
|
{
|
|
transform.localEulerAngles = new Vector3(0, UnityEngine.Random.Range(-180f, 180f), 0);
|
|
}
|
|
if (!_scaleDownWithWorld)
|
|
{
|
|
transform.localScale = Vector3.one / tile.TileScale;
|
|
}
|
|
|
|
if (_randomizeScale)
|
|
{
|
|
var scale = transform.localScale;
|
|
var y = UnityEngine.Random.Range(scale.y * .7f, scale.y * 1.3f);
|
|
scale.y = y;
|
|
transform.localScale = scale;
|
|
}
|
|
|
|
}
|
|
_spawnedCount++;
|
|
}
|
|
}
|
|
|
|
public override void OnPoolItem(VectorEntity vectorEntity)
|
|
{
|
|
if(_objects.ContainsKey(vectorEntity.GameObject))
|
|
{
|
|
foreach (var item in _objects[vectorEntity.GameObject])
|
|
{
|
|
item.SetActive(false);
|
|
_pool.Enqueue(item);
|
|
}
|
|
|
|
_objects[vectorEntity.GameObject].Clear();
|
|
_objects.Remove(vectorEntity.GameObject);
|
|
}
|
|
}
|
|
|
|
public override void Clear()
|
|
{
|
|
foreach (var go in _pool)
|
|
{
|
|
go.Destroy();
|
|
}
|
|
_pool.Clear();
|
|
foreach (var tileObject in _objects)
|
|
{
|
|
foreach (var go in tileObject.Value)
|
|
{
|
|
if (Application.isEditor && !Application.isPlaying)
|
|
{
|
|
DestroyImmediate(go);
|
|
}
|
|
else
|
|
{
|
|
Destroy(go);
|
|
}
|
|
}
|
|
}
|
|
_objects.Clear();
|
|
}
|
|
|
|
private GameObject GetObject(int index, GameObject go)
|
|
{
|
|
GameObject ob;
|
|
if (_pool.Count > 0)
|
|
{
|
|
ob = _pool.Dequeue();
|
|
ob.SetActive(true);
|
|
ob.transform.SetParent(go.transform);
|
|
}
|
|
else
|
|
{
|
|
ob = ((GameObject)Instantiate(_prefabs[index], go.transform, false));
|
|
}
|
|
if (_objects.ContainsKey(go))
|
|
{
|
|
_objects[go].Add(ob);
|
|
}
|
|
else
|
|
{
|
|
_objects.Add(go, new List<GameObject>() { ob });
|
|
}
|
|
return ob;
|
|
}
|
|
}
|
|
}
|
|
|