public static void SetObjects(List <Transition>[] allTransitions, string[] allIds) { VegetationSystemPro system = GameObject.FindObjectOfType <VegetationSystemPro>(); PersistentVegetationStorage storage = system.PersistentVegetationStorage; for (int i = 0; i < allTransitions.Length; i++) { if (allTransitions[i] == null) { continue; } foreach (Transition obj in allTransitions[i]) { storage.AddVegetationItemInstance( allIds[i], obj.pos, obj.scale, obj.rotation, applyMeshRotation: true, vegetationSourceID: VS_MM_id, distanceFalloff: 1, clearCellCache: true); } } //for (int i=0; i<system.VegetationCellList.Count; i++) // system.VegetationCellList[i].ClearCache(); system.RefreshBillboards(); #if UNITY_EDITOR UnityEditor.EditorUtility.SetDirty(storage.PersistentVegetationStoragePackage); UnityEditor.EditorUtility.SetDirty(system); #endif }
public static void FlushObjects(Rect terrainRect, bool clearCache = true) { VegetationSystemPro system = GameObject.FindObjectOfType <VegetationSystemPro>(); if (system == null) { return; } PersistentVegetationStorage storage = system.PersistentVegetationStorage; PersistentVegetationStoragePackage storagePackage = system.PersistentVegetationStorage.PersistentVegetationStoragePackage; if (storagePackage == null) { return; } List <VegetationCell> overlapCellList = new List <VegetationCell>(); system.VegetationCellQuadTree.Query(terrainRect, overlapCellList); for (int i = 0; i < overlapCellList.Count; i++) { int cellIndex = overlapCellList[i].Index; //storagePackage.PersistentVegetationCellList[cellIndex].ClearCell(); var infoList = storagePackage.PersistentVegetationCellList[cellIndex].PersistentVegetationInfoList; for (int j = 0; j < infoList.Count; j++) { var itemList = infoList[j].VegetationItemList; for (int k = itemList.Count - 1; k >= 0; k--) { Vector3 pos = itemList[k].Position + system.VegetationSystemPosition; Vector2 pos2 = pos.V2(); if (terrainRect.Contains(pos2)) { itemList.RemoveAt(k); //storage.RemoveVegetationItemInstance(infoList[j].VegetationItemID, pos, 1, clearCellCache:false); } } } //VegetationItemIndexes indexes = VegetationSystemPro.GetVegetationItemIndexes(vegetationItemID); //system.ClearCache(overlapCellList[i],indexes.VegetationPackageIndex,indexes.VegetationItemIndex); } //if (clearCache) //{ // for (int i=0; i<system.VegetationCellList.Count; i++) // system.VegetationCellList[i].ClearCache(); //} system.RefreshBillboards(); }
public static void SetObjects(List <ObjectPool.Transition>[] allTransitions, string[] allIds) { if (system == null) { system = GameObject.FindObjectOfType <VegetationSystemPro>(); } if (system == null) { throw new System.Exception("MapMagic could not find Vegetation System in scene./n Add Window -> AwesomeTechnologies -> Vegetation System to scene"); } PersistentVegetationStorage storage = system.PersistentVegetationStorage; PersistentVegetationStoragePackage storagePackage = system.PersistentVegetationStorage.PersistentVegetationStoragePackage; if (storagePackage == null) { throw new System.Exception("Vegetation System has no storage package assigned to be used with MapMagic./nAssign a Persistent Vegetation Storage Package to Persistent Vegetation Storage component and initialize it."); } for (int i = 0; i < allTransitions.Length; i++) { if (allTransitions[i] == null) { continue; } var itemInfo = system.GetVegetationItemInfo(allIds[i]); if (itemInfo == null) { throw new System.Exception("Item applied by MapMagic is not present in Vegetation System storage"); } foreach (ObjectPool.Transition obj in allTransitions[i]) { storage.AddVegetationItemInstance( allIds[i], obj.pos, obj.scale, obj.rotation, applyMeshRotation: true, vegetationSourceID: VS_MM_id, distanceFalloff: 1, clearCellCache: true); } } //for (int i=0; i<system.VegetationCellList.Count; i++) // system.VegetationCellList[i].ClearCache(); //system.ClearCache(); system.RefreshBillboards(); #if UNITY_EDITOR UnityEditor.EditorUtility.SetDirty(storagePackage); UnityEditor.EditorUtility.SetDirty(system); #endif }
//Prepare public void CheckAddComponent(Chunk chunk) { #if VEGETATION_STUDIO Profiler.BeginSample("VS Prepare"); //adding the main vegetation object VegetationStudioManager.AddVegetationStudioManagerToScene(); //checking if all packs for all of the generators are the same if (packageShared == null) { packageShared = package; } else { package = packageShared; } //finding/creating vegetation system component VegetationSystem vetSys = chunk.terrain.gameObject.GetComponentInChildren <VegetationSystem>(); if (vetSys == null) { vetSys = VegetationStudioManager.AddVegetationSystemToTerrain(chunk.terrain, package, createPersistentVegetationStoragePackage: true); } if (vetSys.VegetationPackageList.Count == 0) { vetSys.VegetationPackageList.Add(package); } if (vetSys.VegetationPackageList.Count == 1 && vetSys.VegetationPackageList[0] == null) { vetSys.VegetationPackageList[0] = package; } if (!vetSys.VegetationPackageList.Contains(package)) { vetSys.VegetationPackageList.Add(package); } if (!vetSys.InitDone) { vetSys.SetupVegetationSystem(); vetSys.RefreshVegetationPackage(); } cellSize = vetSys.CellSize; //saving per-chunk storage (to access it from thread) PersistentVegetationStorage storage = vetSys.gameObject.GetComponent <PersistentVegetationStorage>(); if (!vetStorComponents.ContainsKey(chunk.rect)) { vetStorComponents.Add(chunk.rect, null); } vetStorComponents[chunk.rect] = storage; Profiler.EndSample(); #endif }
public VegetationSystem CopyVegetationSystem(GameObject srcGameObj, Terrain terrain) { GameObject vegetationSystemObject = GameObject.Instantiate(srcGameObj); vegetationSystemObject.transform.SetParent(terrain.transform); VegetationSystem vegetationSystem = vegetationSystemObject.GetComponent <VegetationSystem>(); if (vegetationSystem == null) { vegetationSystem = vegetationSystemObject.AddComponent <VegetationSystem>(); } if (package != null) { vegetationSystem.AddVegetationPackage(package, true); } if (vegetationSystemObject.GetComponent <TerrainSystem>() == null) { vegetationSystemObject.AddComponent <TerrainSystem>(); } BillboardSystem billboardSystem = vegetationSystemObject.GetComponent <BillboardSystem>(); if (billboardSystem == null) { billboardSystem = vegetationSystemObject.AddComponent <BillboardSystem>(); } billboardSystem.VegetationSystem = vegetationSystem; PersistentVegetationStorage srcStorage = vegetationSystemObject.GetComponent <PersistentVegetationStorage>(); if (srcStorage != null) { GameObject.DestroyImmediate(srcStorage); } PersistentVegetationStorage persistentVegetationStorage = vegetationSystemObject.AddComponent <PersistentVegetationStorage>(); persistentVegetationStorage.VegetationSystem = vegetationSystem; vegetationSystem.AutoselectTerrain = false; vegetationSystem.currentTerrain = terrain; //vegetationSystem.AutomaticWakeup = true; PersistentVegetationStoragePackage persistentVegetationStoragePackage = ScriptableObject.CreateInstance <PersistentVegetationStoragePackage>(); persistentVegetationStorage.PersistentVegetationStoragePackage = persistentVegetationStoragePackage; persistentVegetationStorage.AutoInitPersistentVegetationStoragePackage = true; vegetationSystem.SetSleepMode(false); return(vegetationSystem); }
void DoAddPersistentStorage(VegetationSystem _vegetationSystem) { _vegetationSystem.AutomaticWakeup = true; // NB seems redundant to recurse into parent object - but this is needed to get the terrain name GameObject parentTerrainGo = _vegetationSystem.gameObject.transform.parent.gameObject; PersistentVegetationStorage _persistentVegetationStorage = parentTerrainGo.GetComponentInChildren <PersistentVegetationStorage>(); PersistentVegetationStoragePackage newPersistentVegetationStoragePackage = ScriptableObject.CreateInstance <PersistentVegetationStoragePackage>(); AssetDatabase.CreateAsset(newPersistentVegetationStoragePackage, _assetsPath + "/" + parentTerrainGo.name + _DEFAULT_SUFFIX + ".asset"); _persistentVegetationStorage.PersistentVegetationStoragePackage = newPersistentVegetationStoragePackage; // initialize _persistentVegetationStorage.InitializePersistentStorage(); if (_debugToLog) { Debug.Log("Added storage asset for " + parentTerrainGo.name); } if (_autoBake) { if (_debugToLog) { Debug.Log("Auto Baking " + parentTerrainGo.name); } //if (_vegetationSystem.GetSleepMode()) //{ _vegetationSystem.SetSleepMode(false); // wake up VegetationSystem, needed for prefab //} // now bake List <string> vegetationItemIdList = VegetationPackageEditorTools.CreateVegetationInfoIdList(_persistentVegetationStorage.VegetationSystem.CurrentVegetationPackage); for (int i = 0; i <= vegetationItemIdList.Count - 1; i++) { _persistentVegetationStorage.BakeVegetationItem(vegetationItemIdList[i]); } _persistentVegetationStorage.VegetationSystem.DelayedClearVegetationCellCache(); EditorUtility.SetDirty(_persistentVegetationStorage.PersistentVegetationStoragePackage); EditorUtility.SetDirty(_persistentVegetationStorage.VegetationSystem.CurrentVegetationPackage); if (_debugToLog) { Debug.Log("Finished Baking for " + parentTerrainGo.name); } } }
public static void SetObjects(VegetationSystemPro system, List <Transition>[] allTransitions, string[] allIds) { PersistentVegetationStorage storage = system.PersistentVegetationStorage; //if (system.VegetationCellQuadTree == null) //could happen on scene loading or playmode change // system.RefreshVegetationSystem(); if (!system.InitDone) { system.enabled = true; } byte VS_MM_id = 15; //15 for MapMagic, 18 for Voxeland for (int i = 0; i < allTransitions.Length; i++) { if (allTransitions[i] == null) { continue; } foreach (Transition obj in allTransitions[i]) { storage.AddVegetationItemInstance( allIds[i], obj.pos, obj.scale, obj.rotation, applyMeshRotation: true, vegetationSourceID: VS_MM_id, distanceFalloff: 1, clearCellCache: true); } } //for (int i=0; i<system.VegetationCellList.Count; i++) // system.VegetationCellList[i].ClearCache(); system.RefreshBillboards(); #if UNITY_EDITOR if (storage.PersistentVegetationStoragePackage != null) { UnityEditor.EditorUtility.SetDirty(storage.PersistentVegetationStoragePackage); } UnityEditor.EditorUtility.SetDirty(system); #endif }
/// <summary> /// /// </summary> /// <param name="vegetationItemID"></param> public static void RemoveVegetationItemInstances(string vegetationItemID) { if (!Instance) { FindInstance(); } if (Instance) { for (int i = 0; i <= Instance.VegetationSystemList.Count - 1; i++) { PersistentVegetationStorage persistentVegetationStorage = Instance.VegetationSystemList[i].PersistentVegetationStorage; if (persistentVegetationStorage) { persistentVegetationStorage.RemoveVegetationItemInstances(vegetationItemID); } } } }
/// <summary> /// This will add a new instance of a vegetationItem to the PersistentVegetationStorage. The VegetationItemID is the one you get from the AddVegetationItem function or from an existing item in the VegetationPackage. You provide it with worldspace position and a vegetationSourceID. See PersistentVegetationStorageTools.cs for info about the vegetationSourceID. /// </summary> /// <param name="vegetationItemID"></param> /// <param name="worldPosition"></param> /// <param name="scale"></param> /// <param name="rotation"></param> /// <param name="applyMeshRotation"></param> /// <param name="vegetationSourceID"></param> /// <param name="distanceFalloff"></param> /// <param name="clearCellCache"></param> public static void AddVegetationItemInstance(string vegetationItemID, Vector3 worldPosition, Vector3 scale, Quaternion rotation, bool applyMeshRotation, byte vegetationSourceID, float distanceFalloff, bool clearCellCache = true) { if (!Instance) { FindInstance(); } if (Instance) { for (int i = 0; i <= Instance.VegetationSystemList.Count - 1; i++) { PersistentVegetationStorage persistentVegetationStorage = Instance.VegetationSystemList[i].PersistentVegetationStorage; if (persistentVegetationStorage) { persistentVegetationStorage.AddVegetationItemInstance(vegetationItemID, worldPosition, scale, rotation, applyMeshRotation, vegetationSourceID, distanceFalloff, clearCellCache); } } } }
void AssignTerrainToVS(Terrain terrain, VegetationSystem vs, VegetationPackage vegetationPackage, PersistentVegetationStoragePackage storagePackage) { vs.AutoselectTerrain = false; vs.CurrentVegetationPackage = vegetationPackage; PersistentVegetationStorage storage = vs.GetComponent <PersistentVegetationStorage>(); if (storage != null) { storage.SetPersistentVegetationStoragePackage(storagePackage); } if (vs.InitDone) { vs.HotswapTerrain(terrain, new UnityTerrainData(terrain)); } else { vs.SetTerrain(terrain); } }
/// <summary> /// /// </summary> /// <param name="vegetationItemID"></param> /// <param name="worldPosition"></param> /// <param name="minimumDistance"></param> /// <param name="clearCellCache"></param> public static void RemoveVegetationItemInstance(string vegetationItemID, Vector3 worldPosition, float minimumDistance, bool clearCellCache = true) { if (!Instance) { FindInstance(); } if (Instance) { for (int i = 0; i <= Instance.VegetationSystemList.Count - 1; i++) { PersistentVegetationStorage persistentVegetationStorage = Instance.VegetationSystemList[i].PersistentVegetationStorage; if (persistentVegetationStorage) { persistentVegetationStorage.RemoveVegetationItemInstance(vegetationItemID, worldPosition, minimumDistance, clearCellCache); } } } }
public static void SetupTerrain(Terrain terrain, ref VegetationPackage package, out VegetationSystem system, out PersistentVegetationStorage storage) { var vetSystems = GetVegetationSystemsForTerrain(terrain); VegetationSystem vetSys = null; for (var i = 0; i < vetSystems.Count; ++i) { var candidate = vetSystems[i]; if (candidate.CurrentVegetationPackage == package) { vetSys = candidate; break; } } if (vetSys == null) { vetSys = VegetationStudioManager.AddVegetationSystemToTerrain(terrain, package, createPersistentVegetationStoragePackage: true); } if (package != null) { if (vetSys.VegetationPackageList.Count == 0) { vetSys.VegetationPackageList.Add(package); } if (vetSys.VegetationPackageList.Count == 1 && vetSys.VegetationPackageList[0] == null) { vetSys.VegetationPackageList[0] = package; } if (!vetSys.VegetationPackageList.Contains(package)) { vetSys.VegetationPackageList.Add(package); } } if (!vetSys.InitDone) { vetSys.SetupVegetationSystem(); vetSys.RefreshVegetationPackage(); } vetSys.SetSleepMode(false); package = vetSys.CurrentVegetationPackage; system = vetSys; storage = vetSys.GetComponent <PersistentVegetationStorage>(); }
public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null) { #if VEGETATION_STUDIO if (stop != null && stop(0)) { return; } //preparing and clearing storage if (vetStorComponents == null || vetStorComponents.Count == 0) { return; //vs not used (process runs anyway) } PersistentVegetationStorage storage = vetStorComponents[rect]; int cellXCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize); int cellZCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize); Noise noise = new Noise(12345, permutationCount: 128); //to pick objects based on biome //clearing all of the items foreach (VegetationStudioOutput gen in gens.GeneratorsOfType <VegetationStudioOutput>(onlyEnabled:true, checkBiomes:true)) { for (int b = 0; b < gen.layers.Length; b++) { string id = gen.package.VegetationInfoList[b].VegetationItemID; storage.RemoveVegetationItemInstances(id, VS_MM_id); } break; //iterating in one generator only - they use the same layers } if (stop != null && stop(0)) { return; } //object outputs foreach (VegetationStudioOutput gen in gens.GeneratorsOfType <VegetationStudioOutput>(onlyEnabled:true, checkBiomes:true)) { //gen biome mask Matrix biomeMask = null; if (gen.biome != null) { object biomeMaskObj = gen.biome.mask.GetObject(results); if (biomeMaskObj == null) { continue; //adding nothing if biome has no mask } biomeMask = (Matrix)biomeMaskObj; if (biomeMask == null) { continue; } if (biomeMask.IsEmpty()) { continue; //optimizing empty biomes } } //iterating in layers for (int b = 0; b < gen.layers.Length; b++) { if (stop != null && stop(0)) { return; //checking stop before reading output } Layer layer = gen.layers[b]; string id = gen.package.VegetationInfoList[b].VegetationItemID; //objects layer if (layer.type == Layer.Type.Object) { //loading objects from input SpatialHash hash = (SpatialHash)gen.layers[b].objInput.GetObject(results); if (hash == null) { continue; } //filling instances (no need to check/add key in multidict) foreach (SpatialObject obj in hash.AllObjs()) { //skipping on biome not used float biomeFactor = 0; if (gen.biome == null) { biomeFactor = 1; } else if (biomeMask != null) { biomeFactor = biomeMask.GetInterpolated(obj.pos.x, obj.pos.y); } if (biomeFactor < 0.00001f) { continue; } float rnd; switch (biomeBlendType) { case ObjectOutput.BiomeBlendType.Sharp: rnd = 0.5f; break; case ObjectOutput.BiomeBlendType.AdditiveRandom: case ObjectOutput.BiomeBlendType.NormalizedRandom: rnd = noise.Random((int)obj.pos.x, (int)obj.pos.y); if (biomeFactor > 0.5f) { rnd = 1 - rnd; //test } break; case ObjectOutput.BiomeBlendType.Scale: rnd = 0.0f; break; default: rnd = 0.5f; break; } if (biomeFactor < rnd) { continue; } //flooring float terrainHeight = 0; if (layer.relativeHeight && results.heights != null) //if checbox enabled and heights exist (at least one height generator is in the graph) { terrainHeight = results.heights.GetInterpolated(obj.pos.x, obj.pos.y); } if (terrainHeight > 1) { terrainHeight = 1; } //terrain-space object position Vector3 position = new Vector3( (obj.pos.x - hash.offset.x) / hash.size * terrainSize.dimensions, (obj.height + terrainHeight) * terrainSize.height, (obj.pos.y - hash.offset.y) / hash.size * terrainSize.dimensions); //cell number int cx = (int)(position.x / cellSize); int cz = (int)(position.z / cellSize); PersistentVegetationCell cell = storage.PersistentVegetationStoragePackage.PersistentVegetationCellList[cz + cx * cellXCount]; //rotation + taking terrain normal Quaternion rotation; float objRotation = layer.rotate ? obj.rotation % 360 : 0; if (layer.takeTerrainNormal) { Vector3 terrainNormal = ObjectOutput.GetTerrainNormal(obj.pos.x, obj.pos.y, results.heights, terrainSize.height, terrainSize.pixelSize); Vector3 sideVector = new Vector3(Mathf.Sin((obj.rotation + 90) * Mathf.Deg2Rad), 0, Mathf.Cos((obj.rotation + 90) * Mathf.Deg2Rad)); Vector3 frontVector = Vector3.Cross(sideVector, terrainNormal); rotation = Quaternion.LookRotation(frontVector, terrainNormal); } else { rotation = objRotation.EulerToQuat(); } //scale + biome scale mode Vector3 scale = layer.scale ? new Vector3(layer.scaleY ? 1 : obj.size, obj.size, layer.scaleY ? 1 : obj.size) : Vector3.one; if (biomeBlendType == ObjectOutput.BiomeBlendType.Scale && gen.biome != null) { float biomeVal = 1; if (biomeMask != null) { biomeVal = biomeMask[obj.pos]; } if (biomeVal < 0.001f) { continue; //skip zero-scaled objects } scale *= biomeVal; } //storage.AddVegetationItemInstance(id, position, scale, rotation, layer.applyMeshRotation, VS_MM_id, true); cell.AddVegetationItemInstance(id, position, scale, rotation, VS_MM_id); } if (stop != null && stop(0)) { return; } } //map outputs if (layer.type == Layer.Type.Map) { //reading output directly //Output output = gen.layers[b].output; //if (stop!=null && stop(0)) return; //checking stop before reading output //if (!results.results.ContainsKey(output)) continue; //Matrix matrix = (Matrix)results.results[output]; //loading from input if (stop != null && stop(0)) { return; } Matrix matrix = (Matrix)gen.layers[b].mapInput.GetObject(results); if (matrix == null) { continue; } Matrix heights = results.heights; //get heights before the chunk is removed //setting bush by bush using the sample dist float sampleDist = 1f / layer.density; //filling float terrainPosX = 1f * rect.offset.x / terrainSize.resolution * terrainSize.dimensions; float terrainPosZ = 1f * rect.offset.z / terrainSize.resolution * terrainSize.dimensions; for (int cx = 0; cx <= cellXCount - 1; cx++) { for (int cz = 0; cz <= cellZCount - 1; cz++) { Vector3 cellCorner = new Vector3(terrainPosX + (cellSize * cx), 0, terrainPosZ + (cellSize * cz)); PersistentVegetationCell cell = storage.PersistentVegetationStoragePackage.PersistentVegetationCellList[cz + cx * cellXCount]; for (float x = 0; x < cellSize; x += sampleDist) { for (float z = 0; z < cellSize; z += sampleDist) { //world position float wx = cellSize * cx + x; float wz = cellSize * cz + z; //randomizing position wx += noise.Random((int)(wx * 10), (int)(wz * 10), 2) * sampleDist - sampleDist / 2; wz += noise.Random((int)(wx * 10), (int)(wz * 10), 3) * sampleDist - sampleDist / 2; //map position float mx = wx / terrainSize.dimensions * rect.size.x + rect.offset.x; // relative (0-1) position * terrain res float mz = wz / terrainSize.dimensions * rect.size.z + rect.offset.z; float val = matrix.GetInterpolated(mx, mz); float biomeFactor = 0; if (gen.biome == null) { biomeFactor = 1; } else if (biomeMask != null) { biomeFactor = biomeMask.GetInterpolated(mx, mz); } //placing object float rnd = (noise.Random((int)(wx * 10), (int)(wz * 10))); if (rnd < val * biomeFactor) { float terrainHeight = heights.GetInterpolated(mx, mz) * terrainSize.height; //rotation + taking terrain normal Quaternion rotation; float rotRnd = noise.Random((int)(wx * 10), (int)(wz * 10), 1); float objRotation = layer.rotate ? rotRnd * 360 : 0; if (layer.takeTerrainNormal) { Vector3 terrainNormal = ObjectOutput.GetTerrainNormal(mx, mz, heights, terrainSize.height, terrainSize.pixelSize); Vector3 sideVector = new Vector3(Mathf.Sin((objRotation + 90) * Mathf.Deg2Rad), 0, Mathf.Cos((objRotation + 90) * Mathf.Deg2Rad)); Vector3 frontVector = Vector3.Cross(sideVector, terrainNormal); rotation = Quaternion.LookRotation(frontVector, terrainNormal); } else { rotation = objRotation.EulerToQuat(); } //scale float rndScale = noise.Random((int)(wx * 10), (int)(wz * 10), 1); rndScale = layer.scaleMinMax.x + (layer.scaleMinMax.y - layer.scaleMinMax.x) * rndScale; Vector3 scale = new Vector3(rndScale, rndScale, rndScale); //storage.AddVegetationItemInstance(id, new Vector3(wx,terrainHeight,wz), scale, rotation, layer.applyMeshRotation, VS_MM_id, true); cell.AddVegetationItemInstance(id, new Vector3(wx, terrainHeight, wz), scale, rotation, VS_MM_id); } } } if (stop != null && stop(0)) { return; } } } } } } //refreshing billboards //calling it from thread ruins all the billboards //BillboardSystem billboardSys = billboardComponents[rect]; //if (billboardSys != null) // billboardSys.RefreshBillboards(); #endif //pushing anything to apply if (stop != null && stop(0)) { return; } results.apply.CheckAdd(typeof(VegetationStudioOutput), null, replace: true); }
public static void FlushObjects(Rect terrainRect, bool clearCache = true) { if (system == null) { system = GameObject.FindObjectOfType <VegetationSystemPro>(); } if (system == null) { return; } //throw new System.Exception("MapMagic could not find Vegetation System in scene./n Add Window -> AwesomeTechnologies -> Vegetation System to scene"); PersistentVegetationStorage storage = system.PersistentVegetationStorage; PersistentVegetationStoragePackage storagePackage = system.PersistentVegetationStorage.PersistentVegetationStoragePackage; if (storagePackage == null) { return; } //throw new System.Exception("Vegetation System has no storage package assigned to be used with MapMagic./nAssign a Persistent Vegetation Storage Package to Persistent Vegetation Storage component and initialize it."); List <VegetationCell> overlapCellList = new List <VegetationCell>(); system.VegetationCellQuadTree.Query(terrainRect, overlapCellList); if (system.VegetationCellQuadTree.Count != storagePackage.PersistentVegetationCellList.Count) { throw new System.Exception("Vegetation System cells number has a different count rather than Persistent Storage./nPlease re-initialize Persistent Storage."); } for (int i = 0; i < overlapCellList.Count; i++) { int cellIndex = overlapCellList[i].Index; //storagePackage.PersistentVegetationCellList[cellIndex].ClearCell(); var infoList = storagePackage.PersistentVegetationCellList[cellIndex].PersistentVegetationInfoList; for (int j = 0; j < infoList.Count; j++) { var itemList = infoList[j].VegetationItemList; for (int k = itemList.Count - 1; k >= 0; k--) { Vector3 pos = itemList[k].Position + system.VegetationSystemPosition; Vector2 pos2 = pos.V2(); if (terrainRect.Contains(pos2)) { itemList.RemoveAt(k); //storage.RemoveVegetationItemInstance(infoList[j].VegetationItemID, pos, 1, clearCellCache:false); } } } //VegetationItemIndexes indexes = VegetationSystemPro.GetVegetationItemIndexes(vegetationItemID); //system.ClearCache(overlapCellList[i],indexes.VegetationPackageIndex,indexes.VegetationItemIndex); } //if (clearCache) //{ // for (int i=0; i<system.VegetationCellList.Count; i++) // system.VegetationCellList[i].ClearCache(); //} system.ClearCache(new Bounds(terrainRect.center.V3(), terrainRect.size.V3())); system.RefreshBillboards(); }