using System.Collections.Generic; using System.Xml; using AwesomeTechnologies.Utility; using AwesomeTechnologies.Vegetation; using AwesomeTechnologies.VegetationSystem; using Unity.Collections; using UnityEngine; using UnityEngine.AI; public class ColliderPool : VegetationItemPool { private readonly List _colliderPoolList = new List(); private readonly VegetationItemInfoPro _vegetationItemInfoPro; private readonly VegetationItemModelInfo _vegetationItemModelInfo; private readonly VegetationSystemPro _vegetationSystemPro; private int _colliderCounter; private readonly Transform _colliderParent; private readonly GameObject _sourceColliderObject; private bool _showColliders; private LayerMask _colliderLayer; private string _colliderTag; public ColliderPool(VegetationItemInfoPro vegetationItemInfoPro, VegetationItemModelInfo vegetationItemModelInfo, VegetationSystemPro vegetationSystemPro, Transform colliderParent, bool showColliders) { _vegetationItemInfoPro = vegetationItemInfoPro; _vegetationItemModelInfo = vegetationItemModelInfo; _vegetationSystemPro = vegetationSystemPro; _colliderParent = colliderParent; _showColliders = showColliders; _colliderLayer = vegetationSystemPro.VegetationSettings.GetLayer(vegetationItemInfoPro.VegetationType); _colliderTag = vegetationItemInfoPro.ColliderTag; if (_colliderTag == "") { _colliderTag = "Untagged"; } if (_vegetationItemInfoPro.ColliderType == ColliderType.FromPrefab) { GameObject tmpColliderObject = Object.Instantiate(vegetationItemInfoPro.VegetationPrefab); if (_vegetationItemInfoPro.ColliderTag != "") { tmpColliderObject.tag = vegetationItemInfoPro.ColliderTag; } tmpColliderObject.hideFlags = HideFlags.DontSave; tmpColliderObject.name = "ColliderSource_" + _vegetationItemInfoPro.VegetationItemID; tmpColliderObject.transform.SetParent(_colliderParent); _sourceColliderObject = CreateColliderObject(tmpColliderObject); DestroyObject(tmpColliderObject); } } void AddVegetationItemInstanceInfo(GameObject colliderObject) { var vegetationItemInstanceInfo = colliderObject.AddComponent(); vegetationItemInstanceInfo.VegetationType = _vegetationItemInfoPro.VegetationType; vegetationItemInstanceInfo.VegetationItemID = _vegetationItemInfoPro.VegetationItemID; RuntimeObjectInfo runtimeObjectInfo = colliderObject.AddComponent(); runtimeObjectInfo.VegetationItemInfo = _vegetationItemInfoPro; } void UpdateVegetationItemInstanceInfo(GameObject colliderObject, ItemSelectorInstanceInfo info) { VegetationItemInstanceInfo vegetationItemInstanceInfo = colliderObject.GetComponent(); if (vegetationItemInstanceInfo) { vegetationItemInstanceInfo.Position = info.Position; vegetationItemInstanceInfo.VegetationItemInstanceID = Mathf.RoundToInt(vegetationItemInstanceInfo.Position.x *100f).ToString() + "_" + Mathf.RoundToInt(vegetationItemInstanceInfo.Position.y * 100f).ToString() + "_" + Mathf.RoundToInt(vegetationItemInstanceInfo.Position.z * 100f).ToString(); vegetationItemInstanceInfo.Rotation = info.Rotation; vegetationItemInstanceInfo.Scale = info.Scale; } } public void SetColliderVisibility(bool value) { _showColliders = value; for (int i = 0; i <= _colliderPoolList.Count - 1; i++) { GameObject go = _colliderPoolList[i]; if (value) { go.hideFlags = HideFlags.DontSave; } else { go.hideFlags = HideFlags.HideAndDontSave; } } } public override GameObject GetObject(ItemSelectorInstanceInfo info) { if (_colliderPoolList.Count <= 0) return CreateColliderObject(info); GameObject colliderObject = _colliderPoolList[_colliderPoolList.Count - 1]; _colliderPoolList.RemoveAtSwapBack(_colliderPoolList.Count -1); colliderObject.SetActive(true); PositionColliderObject(colliderObject, info); return colliderObject; } private HideFlags GetVisibilityHideFlags() { return _showColliders ? HideFlags.DontSave : HideFlags.HideAndDontSave; } void PositionColliderObject(GameObject colliderObject, ItemSelectorInstanceInfo info) { colliderObject.transform.position = info.Position + _vegetationSystemPro.FloatingOriginOffset; colliderObject.transform.localScale = info.Scale; colliderObject.transform.rotation = info.Rotation; UpdateVegetationItemInstanceInfo(colliderObject, info); } public GameObject CreateColliderObject(ItemSelectorInstanceInfo info) { _colliderCounter++; GameObject newColliderObject; if (_vegetationItemInfoPro.ColliderType == ColliderType.FromPrefab) { newColliderObject = Object.Instantiate(_sourceColliderObject); newColliderObject.name = "Collider_" + _colliderCounter.ToString(); newColliderObject.hideFlags = GetVisibilityHideFlags(); newColliderObject.transform.SetParent(_colliderParent); } else { newColliderObject = CreatePrimitiveCollider(info); } if (_vegetationItemInfoPro.ColliderTag != "") { newColliderObject.tag = _vegetationItemInfoPro.ColliderTag; } AddNavMesObstacle(newColliderObject); newColliderObject.SetActive(true); AddVegetationItemInstanceInfo(newColliderObject); PositionColliderObject(newColliderObject,info); newColliderObject.layer = _vegetationSystemPro.VegetationSettings.GetLayer(_vegetationItemInfoPro.VegetationType); return newColliderObject; } private GameObject CreatePrimitiveCollider(ItemSelectorInstanceInfo info) { switch (_vegetationItemInfoPro.ColliderType) { case ColliderType.Capsule: GameObject newCapsuleColliderObject = new GameObject("CapsuleCollider_" + _colliderCounter); newCapsuleColliderObject.layer = _colliderLayer; newCapsuleColliderObject.tag = _colliderTag; newCapsuleColliderObject.transform.SetParent(_colliderParent); newCapsuleColliderObject.hideFlags = GetVisibilityHideFlags(); CapsuleCollider capsuleCollider = newCapsuleColliderObject.AddComponent(); capsuleCollider.height = _vegetationItemInfoPro.ColliderHeight; capsuleCollider.radius = _vegetationItemInfoPro.ColliderRadius; capsuleCollider.isTrigger =_vegetationItemInfoPro.ColliderTrigger; Vector3 capsuleColliderOffset = new Vector3(info.Scale.x * _vegetationItemInfoPro.ColliderOffset.x, info.Scale.y * _vegetationItemInfoPro.ColliderOffset.y, info.Scale.z * _vegetationItemInfoPro.ColliderOffset.z); capsuleColliderOffset +=info.Rotation * capsuleColliderOffset; capsuleCollider.center = capsuleColliderOffset; return newCapsuleColliderObject; case ColliderType.Sphere: GameObject newSphereColliderObject = new GameObject("SphereCollider_" + _colliderCounter); newSphereColliderObject.layer = _colliderLayer; newSphereColliderObject.tag = _colliderTag; newSphereColliderObject.transform.SetParent(_colliderParent); newSphereColliderObject.hideFlags =GetVisibilityHideFlags(); SphereCollider sphereCollider = newSphereColliderObject.AddComponent(); sphereCollider.radius = _vegetationItemInfoPro.ColliderRadius; sphereCollider.isTrigger =_vegetationItemInfoPro.ColliderTrigger; Vector3 sphereColliderOffset = new Vector3(info.Scale.x * _vegetationItemInfoPro.ColliderOffset.x, info.Scale.y * _vegetationItemInfoPro.ColliderOffset.y, info.Scale.z * _vegetationItemInfoPro.ColliderOffset.z); sphereColliderOffset +=info.Rotation * sphereColliderOffset; sphereCollider.center = sphereColliderOffset; return newSphereColliderObject; case ColliderType.Box : GameObject newColliderObject = new GameObject("BoxCollider_" + _colliderCounter); newColliderObject.layer = _colliderLayer; newColliderObject.tag = _colliderTag; newColliderObject.transform.SetParent(_colliderParent); newColliderObject.hideFlags =GetVisibilityHideFlags(); BoxCollider boxCollider = newColliderObject.AddComponent(); Vector3 boxColliderSize = new Vector3(info.Scale.x * _vegetationItemInfoPro.ColliderSize.x, info.Scale.y * _vegetationItemInfoPro.ColliderSize.y, info.Scale.z * _vegetationItemInfoPro.ColliderSize.z); boxCollider.size = boxColliderSize; boxCollider.isTrigger =_vegetationItemInfoPro.ColliderTrigger; Vector3 boxColliderOffset = new Vector3(info.Scale.x * _vegetationItemInfoPro.ColliderOffset.x, info.Scale.y * _vegetationItemInfoPro.ColliderOffset.y, info.Scale.z * _vegetationItemInfoPro.ColliderOffset.z); boxColliderOffset +=info.Rotation * boxColliderOffset; boxCollider.center = boxColliderOffset; return newColliderObject; case ColliderType.CustomMesh : GameObject newCustomMeshColliderObject = new GameObject("MeshCollider_" + _colliderCounter); newCustomMeshColliderObject.layer = _colliderLayer; newCustomMeshColliderObject.tag = _colliderTag; newCustomMeshColliderObject.transform.SetParent(_colliderParent); newCustomMeshColliderObject.hideFlags = GetVisibilityHideFlags(); MeshCollider customMeshCollider = newCustomMeshColliderObject.AddComponent(); customMeshCollider.isTrigger =_vegetationItemInfoPro.ColliderTrigger; customMeshCollider.sharedMesh = _vegetationItemInfoPro.ColliderMesh; customMeshCollider.convex = _vegetationItemInfoPro.ColliderConvex; return newCustomMeshColliderObject; case ColliderType.Mesh : GameObject newMeshColliderObject = new GameObject("MeshCollider_" + _colliderCounter); newMeshColliderObject.layer = _colliderLayer; newMeshColliderObject.tag = _colliderTag; newMeshColliderObject.transform.SetParent(_colliderParent); newMeshColliderObject.hideFlags = GetVisibilityHideFlags(); MeshCollider meshCollider = newMeshColliderObject.AddComponent(); meshCollider.isTrigger =_vegetationItemInfoPro.ColliderTrigger; meshCollider.sharedMesh = _vegetationItemModelInfo.VegetationMeshLod0; meshCollider.convex = _vegetationItemInfoPro.ColliderConvex; return newMeshColliderObject; } return new GameObject("Empty collider object"); } void AddNavMesObstacle(GameObject go) { NavMeshObstacle navMeshObstacle; switch (_vegetationItemInfoPro.NavMeshObstacleType) { case NavMeshObstacleType.Box: navMeshObstacle = go.AddComponent(); navMeshObstacle.shape = NavMeshObstacleShape.Box; navMeshObstacle.center = _vegetationItemInfoPro.NavMeshObstacleCenter; navMeshObstacle.size = _vegetationItemInfoPro.NavMeshObstacleSize; navMeshObstacle.carving = _vegetationItemInfoPro.NavMeshObstacleCarve; break; case NavMeshObstacleType.Capsule: navMeshObstacle = go.AddComponent(); navMeshObstacle.shape = NavMeshObstacleShape.Capsule; navMeshObstacle.center = _vegetationItemInfoPro.NavMeshObstacleCenter; navMeshObstacle.radius = _vegetationItemInfoPro.NavMeshObstacleRadius; navMeshObstacle.height = _vegetationItemInfoPro.NavMeshObstacleHeight; navMeshObstacle.carving = _vegetationItemInfoPro.NavMeshObstacleCarve; break; } } public override void ReturnObject(GameObject colliderObject) { if (colliderObject) { colliderObject.SetActive(false); _colliderPoolList.Add(colliderObject); } } private GameObject CreateColliderObject(GameObject sourceObject) { sourceObject.transform.position = Vector3.zero; sourceObject.transform.localScale = Vector3.one; sourceObject.transform.rotation = Quaternion.identity; GameObject colliderObject = new GameObject("SourceColliderObject") {hideFlags = HideFlags.DontSave}; colliderObject.transform.SetParent(_colliderParent); colliderObject.transform.position = Vector3.zero; colliderObject.transform.localScale = Vector3.one; colliderObject.transform.rotation = Quaternion.identity; colliderObject.layer = _colliderLayer; colliderObject.tag = _colliderTag; colliderObject.SetActive(false); MeshCollider[] meshColliders = sourceObject.GetComponentsInChildren(); SphereCollider[] sphereColliders = sourceObject.GetComponentsInChildren(); BoxCollider[] boxColliders = sourceObject.GetComponentsInChildren(); CapsuleCollider[] capsuleColliders = sourceObject.GetComponentsInChildren(); for (int i = 0; i <= capsuleColliders.Length - 1; i++) { GameObject capsuleObject = new GameObject("CapsuleCollider") {hideFlags = HideFlags.DontSave}; capsuleObject.transform.SetParent(colliderObject.transform); capsuleObject.transform.position = capsuleColliders[i].transform.position; capsuleObject.transform.localScale = capsuleColliders[i].transform.localScale; capsuleObject.transform.rotation = capsuleColliders[i].transform.rotation; capsuleObject.layer = _colliderLayer; capsuleObject.tag = _colliderTag; CapsuleCollider newCollider = capsuleObject.AddComponent(); newCollider.radius = capsuleColliders[i].radius; newCollider.height = capsuleColliders[i].height; newCollider.center = capsuleColliders[i].center; newCollider.direction = capsuleColliders[i].direction; newCollider.sharedMaterial = capsuleColliders[i].sharedMaterial; newCollider.isTrigger = capsuleColliders[i].isTrigger; } for (int i = 0; i <= boxColliders.Length - 1; i++) { GameObject boxobject = new GameObject("BoxCollider") {hideFlags = HideFlags.DontSave}; boxobject.transform.SetParent(colliderObject.transform); boxobject.transform.position = boxColliders[i].transform.position; boxobject.transform.localScale = boxColliders[i].transform.localScale; boxobject.transform.rotation = boxColliders[i].transform.rotation; boxobject.layer = _colliderLayer; boxobject.tag = _colliderTag; BoxCollider newCollider = boxobject.AddComponent(); newCollider.center = boxColliders[i].center; newCollider.size = boxColliders[i].size; newCollider.sharedMaterial = boxColliders[i].sharedMaterial; newCollider.isTrigger = boxColliders[i].isTrigger; } for (int i = 0; i <= sphereColliders.Length - 1; i++) { GameObject sphereObject = new GameObject("SphereCollider") {hideFlags = HideFlags.DontSave}; sphereObject.transform.SetParent(colliderObject.transform); sphereObject.transform.position = sphereColliders[i].transform.position; sphereObject.transform.localScale = sphereColliders[i].transform.localScale; sphereObject.transform.rotation = sphereColliders[i].transform.rotation; sphereObject.layer = _colliderLayer; sphereObject.tag = _colliderTag; SphereCollider newCollider = sphereObject.AddComponent(); newCollider.center = sphereColliders[i].center; newCollider.radius = sphereColliders[i].radius; newCollider.sharedMaterial = sphereColliders[i].sharedMaterial; newCollider.isTrigger = sphereColliders[i].isTrigger; } for (int i = 0; i <= meshColliders.Length - 1; i++) { GameObject meshObject = new GameObject("MeshCollider") {hideFlags = HideFlags.DontSave}; meshObject.transform.SetParent(colliderObject.transform); meshObject.transform.position = meshColliders[i].transform.position; meshObject.transform.localScale = meshColliders[i].transform.localScale; meshObject.transform.rotation = meshColliders[i].transform.rotation; meshObject.layer = _colliderLayer; meshObject.tag = _colliderTag; MeshCollider newCollider = meshObject.AddComponent(); newCollider.cookingOptions = meshColliders[i].cookingOptions; newCollider.convex = meshColliders[i].convex; newCollider.sharedMesh = meshColliders[i].sharedMesh; newCollider.sharedMaterial = meshColliders[i].sharedMaterial; newCollider.isTrigger = meshColliders[i].isTrigger; } return colliderObject; } // private bool IsReservedComponent(Component component) // { // if (component is Collider) return true; // if (component is Transform) return true; // if (component is Rigidbody) return true; // return false; // } // private static void DestroyComponent(Object component) // { // if (Application.isPlaying) // { // Object.Destroy(component); // } // else // { // Object.DestroyImmediate(component); // } // } private static void DestroyObject(GameObject go) { if (Application.isPlaying) { Object.DestroyImmediate(go); } else { Object.DestroyImmediate(go); } } public void Dispose() { for (int i = 0; i <= _colliderPoolList.Count - 1; i++) { DestroyObject(_colliderPoolList[i]); } _colliderPoolList.Clear(); if (_vegetationItemInfoPro.ColliderType == ColliderType.FromPrefab) { DestroyObject(_sourceColliderObject); } } }