So i forget the idea of creating terrain at runtime, and try to redesign the code to use a pool a terrain object pre-created in editor. X terrain, with X own terrain datas.
Now the problem is elsewhere,
at first execution, the world script modify all the terrains object / grass, tree, heighmap ⌠-
back to the editor: warning & console error everywhere âTerrain detail doesnt existâ âinvalid prototypeâ âterrain layer missingâ âŚrefuse to rebuild (but play mode works)
I tried the following approch to âclean terrainâ on application exit
void OnApplicationQuit()
{
// reassign a fake persistent terrain layer
TerrainLayer refLayer = Resources.Load<TerrainLayer>("....f");
List<TerrainLayer> listeTerrainLayers = new List<TerrainLayer>();
listeTerrainLayers.Add(refLayer);
float[,,] map = new float[128, 128, 1];
for( int i = 0 ; i < 128 ; ++i)
{
for( int j = 0 ; j < 128 ; ++j)
{
map[i,j,0] = 1;
}
}
terrain.terrainData.terrainLayers = listeTerrainLayers.ToArray();
terrain.terrainData.SetAlphamaps(0, 0, map);
// remove all trees
List<TreePrototype> tlTrress = new List<TreePrototype>();
terrain.terrainData.treePrototypes = tlTrress.ToArray();
// remove all details
List<DetailPrototype> tlDetails = new List<DetailPrototype>();
terrain.terrainData.detailPrototypes = tlDetails.ToArray();
terrain.Flush();
}
But it doesnt âresetâ correctly the terrain. On editor, the terrain has changed as wished, and seems reseted, but there is still multiple âunder the hoodâ red terrain Errors, the terrain has reference to âpreviousâ objects somewhere.
I am not successfull to correctly refresh the object
blocked
canât dynamicly create the terrain and populate it via script - cause it doesnât work in build mode
with pre-created terrains instead, it works in build mode, but the terrains objects end being âcorrupted in some wayâ, and itâs misery in editor to reinit thingsâŚ
Hereâs my script to remove all tree instances and tree prototypes. You might be getting an error because you are removing the prototypes without removing the instances first. Hopefully this will help you also remove the detail instances and prototypes.
using UnityEngine;
// Clear existing tree instances
// https://discussions.unity.com/t/how-to-clear-treeinstance-list/147166
public class ClearTreeInstances : MonoBehaviour
{
[ContextMenu("Remove Trees")]
public void RemoveTrees()
{
Terrain terrain = Terrain.activeTerrain;
if (terrain == null)
{
return;
}
TerrainData terrainData = terrain.terrainData;
if (terrainData == null)
{
return;
}
TreeInstance[ ] instances = new TreeInstance[0];
terrainData.SetTreeInstances(instances, false);
TreePrototype[ ] treePrototypes = new TreePrototype[0];
terrainData.treePrototypes = treePrototypes;
terrainData.RefreshPrototypes();
terrain.Flush();
}
void OnDisable()
{
RemoveTrees();
}
void OnApplicationQuit()
{
RemoveTrees();
}
}
According to the docs you need to have at least one scene with a terrain in it as part of your build before you can create a terrain at runtime. Unity - Manual: Using Terrain at runtime
I dropped all dynamic gen terrain, with your function, i can now build & get backto editor and build again ! (adding a hidden terrain didnt solve the textures not apparing on createTerrain unfortunatly)
But i still have the weird crash, it seems to occur the second time when i recycle a terrain and set a new detail prototype array on a terrain.
only implemented in editor :
terrainData.detailPrototypes = herbeProto;
a bit weird, the first âinitâ is the exact same code portion and it doesnât make this error
I canât see herbeProto in your script, but it may be the same problem where youâre deleting the prototypes before clearing the terrain of the details that rely on the prototype.
Before terrainData.RefreshPrototypes(); try adding this:
// The DetailPrototype array must be overwritten
DetailPrototype[ ] detailPrototypes = new DetailPrototype[0];
terrainData.detailPrototypes = detailPrototypes;```
If that doesn't work then try this:
```int detailPrototypesCount = terrainData.detailPrototypes.Length;
for (int i = detailPrototypesCount - 1; i >= 0; i--)
{
terrainData.RemoveDetailPrototype(i);
}```
Is the terrain or anything else in your scene using the âEditor Onlyâ tag?
Are you using OnValidate() instead of Start(), Awake() or OnEnable()?
Is strpath in the Resources folder? If not it might not work outside of the editor.
t.terrainData.RemoveDetailPrototype(i);
// <-- red error in build mode : only implemented in editor
I have a terrain âpool / tileâ system, the message happens when i ârecycleâ an existing terrain (in game while walking i take the â-1â terrain and re compute it so it become the â+1â futur terrain)
this line
terrainData.detailPrototypes = herbeProto;
// <-- red error in build mode : 40x only implemented in editor if i have 40 details..
// all the proto are supposed to be valide
for (int i = 0 ; i < herbeProto.Length ; ++i) {
Debug.Log("herbe" + i + " validate ?" + herbeProto[i].Validate());
}
i Think that when i reassign a detailPrototypes, it calls underthehood âRemoveDetailPrototypeâ on each of the existing one, but it trigger the error. Maybe i am wrong.
I suppose its ânoâ, but can we âlookâ the terrainData class code somewhere to see exactly what is happening, and try to locate the source of the problem ?
i keep trying things, and thanks for your time btw
Is terrain.bakeLightProbesForTrees set to true? Thatâs the only property in either Terrain or TerrainData that mentions being editor only.
In TerrainData thereâs also this function, but I assume you arenât calling it.
public void SetTerrainLayersRegisterUndo(TerrainLayer[ ] terrainLayers, string undoName)
Edit: If you have using UnityEditor; in your script, itâs better to wrap it in an ifdef like this:
#if UNITY_EDITOR
using UnityEditor;
#endif
You may have to copy each detailPrototype in a loop instead of just copying the array with terrainData.detailPrototypes = herbeProto. If you donât, the new array will just have references to the contents of the old array, so when the old array is deleted or cleared then it will also affect the new one.
terrainData.detailPrototypes = new DetailPrototype[herbeProtoCount];
for (int i = 0 ; i < herbeProtoCount ; ++i) {
terrainData.detailPrototypes _= new DetailPrototype(herbeProto*);*_
_*}```*_
There are definitely problems since Unity 2021.2 with procedurally generated Detail objects.
In Editor, it all works fine (Iâm using Built-In Render Pipeline myself, but having very similar problems)âŚ
âŚbut once you make a Build, the Detail objects do not appear.
Unity changed some stuff about how Detail objects worked between 2021.1.28 and 2021.2, and something in those changes stopped procedurally generated Detail objects from working anymore.
Iâve been banging my head against the problem for about 4 days now, and I canât find a solution in the documentation, or on the forums. And all I can find is some issues that Unity have said âWonât Fix⌠the terrain team has other prioritiesâ, which leaves us who are making proc gen games without a working engine.
Too bad about those 5 years of work Iâve put into the project.
If youâre instantiating your terrain as a prefab, make sure thereâs at least one terrain actually placed in a scene included in your build to make sure the terrain code isnât been stripped from the build.
If none of these work, you could just find the diff between the version of Unity that worked and the one that didnât to see what changed in the terrain code: 2021.1.28 2021.2.1 Diff
Although Iâd do a diff between local copies with a tool like WinMerge instead of using GitHub directly.