| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 | using System.Collections;using UnityEngine;using System.Collections.Generic;using UnityEngine.AI;namespace Unity.AI.Navigation.Samples{    /// <summary>    /// Fill 5x5 tiles around the local position procedurally by instantiating prefabs at random positions/orientations    /// </summary>    [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<Transform> m_Instances = new List<Transform>();        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;        }    }}
 |