using System.Collections;
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.AI;
namespace Unity.AI.Navigation.Samples
{
///
/// Fill 5x5 tiles around the local position procedurally by instantiating prefabs at random positions/orientations
///
[DefaultExecutionOrder(-200)]
public class RandomInstancing : MonoBehaviour
{
public GameObject m_Prefab;
public int m_PoolSize = 250;
public int m_InstancesPerTile = 10;
public bool m_RandomPosition = true;
public bool m_RandomOrientation = true;
public float m_Height;
public int m_BaseHash = 347652783;
public float m_Size = 100.0f;
[SerializeField]
Transform parent;
[SerializeField]
NavMeshAgent trackedAgent;
List m_Instances = new List();
int m_Used;
int m_LocX, m_LocZ;
void Awake()
{
for (int i = 0; i < m_PoolSize; ++i)
{
var go = Instantiate(m_Prefab, Vector3.zero, Quaternion.identity, parent) as GameObject;
go.SetActive(false);
m_Instances.Add(go.transform);
}
}
void OnEnable()
{
m_LocX = ~0;
m_LocZ = ~0;
UpdateInstances();
}
void OnDestroy()
{
for (int i = 0; i < m_Instances.Count; ++i)
{
if (m_Instances[i])
Destroy(m_Instances[i].gameObject);
}
m_Instances.Clear();
}
void Update()
{
if (trackedAgent.remainingDistance > 0.1f)
{
UpdateInstances();
}
}
void UpdateInstances()
{
var x = (int)Mathf.Floor(transform.position.x / m_Size);
var z = (int)Mathf.Floor(transform.position.z / m_Size);
if (x == m_LocX && z == m_LocZ)
return;
m_LocX = x;
m_LocZ = z;
m_Used = 0;
for (var i = x - 2; i <= x + 2; ++i)
{
for (var j = z - 2; j <= z + 2; ++j)
{
var count = UpdateTileInstances(i, j);
if (count != m_InstancesPerTile)
return;
}
}
// Deactivate the remaining active elements in the pool.
// Here we assume all active elements are contiguous and first in the list.
for (int i = m_Used; i < m_PoolSize && m_Instances[i].gameObject.activeSelf; ++i)
m_Instances[i].gameObject.SetActive(false);
}
int UpdateTileInstances(int i, int j)
{
var seed = Hash2(i, j) ^ m_BaseHash;
var count = System.Math.Min(m_InstancesPerTile, m_PoolSize - m_Used);
for (var end = m_Used + count; m_Used < end; ++m_Used)
{
float x = 0;
float y = 0;
if (m_RandomPosition)
{
x = Random(ref seed);
y = Random(ref seed);
}
var pos = new Vector3((i + x) * m_Size, m_Height, (j + y) * m_Size);
if (m_RandomOrientation)
{
float r = 360.0f * Random(ref seed);
m_Instances[m_Used].rotation = Quaternion.AngleAxis(r, Vector3.up);
}
m_Instances[m_Used].position = pos;
m_Instances[m_Used].gameObject.SetActive(true);
}
if (count < m_InstancesPerTile)
Debug.LogWarning("Pool exhausted", this);
return count;
}
static int Hash2(int i, int j)
{
return (i * 73856093) ^ (j * 19349663);
}
static float Random(ref int seed)
{
seed = (seed ^ 123459876);
var k = seed / 127773;
seed = 16807 * (seed - k * 127773) - 2836 * k;
if (seed < 0)
seed = seed + 2147483647;
float ran0 = seed * 1.0f / 2147483647.0f;
seed = (seed ^ 123459876);
return ran0;
}
}
}