FoxTheDog Posted January 26, 2022 Posted January 26, 2022 I am using GeNa spawners and terrain decorators in a procedural environment. I have a few Gaia terrains that I modify with prefabs / biomes every time the player visits them. Over the course of 1) playtesting, and 2) actually playing the build, I've noticed that the flattened region where structures had been spawned in previous visits to the planet remain in subsequent visits. Is there a way to 'undo' the terrain deformation caused by a runtime executed decorator spawn on exiting play mode? Thanks for any advice you can provide.
Bryan Posted January 31, 2022 Posted January 31, 2022 On 1/26/2022 at 9:19 AM, FoxTheDog said: I am using GeNa spawners and terrain decorators in a procedural environment. I have a few Gaia terrains that I modify with prefabs / biomes every time the player visits them. Over the course of 1) playtesting, and 2) actually playing the build, I've noticed that the flattened region where structures had been spawned in previous visits to the planet remain in subsequent visits. Is there a way to 'undo' the terrain deformation caused by a runtime executed decorator spawn on exiting play mode? Thanks for any advice you can provide. We are looking into this.
Adam Posted February 1, 2022 Posted February 1, 2022 Unity terrain stores its data in what essentially acts like a scriptable object. What this means is that changes at design time and runtime are persisted. You would need to backup and restore the terraindata to revert this behaviour. GeNa has an in memory undo, you would need to call that when you exit play mode.
FoxTheDog Posted February 1, 2022 Author Posted February 1, 2022 Thanks for the reply. I've been digging into the API docs and found GeNaSpawner.UndoAll(). Although the function is public, I'm having a hard time calling it. My idea was to use the onApplicationQuit event to undo all the spawns that a single spawner made (those with terrain decorators). Something like this: [SerializeField] GeNa.Core.GeNaSpawner spawner void OnApplicationQuit() { spawner.UndoAll(); } I'm clearly not understanding the docs though, UndoAll doesn't appear to be a public method of the GenaSpawner class (but I am admittedly very new to all this!) 5 hours ago, Adam said: You would need to backup and restore the terraindata to revert this behaviour. GeNa has an in memory undo, you would need to call that when you exit play mode. I've looked into this, its nothing I've done before and a bit complex. Are you suggesting that GeNa's in memory undo would handle the backup and restore of the terrain data, or are those separate tasks? Im guessing saving and loading the terrain data isnt going to be very performant in a build.. but I did find this post (2013, recent comment 2019) about the subject, in case anyone else is interested. https://answers.unity.com/questions/390209/how-to-prevent-terrain-changes-from-being-permanen.html
FoxTheDog Posted February 3, 2022 Author Posted February 3, 2022 @Manny This is indeed a huge help. I either need to rethink how I'm using the procedural spawners or implement some sort of deep copy / reload of the terraindata. I'll look into the latter and if its reasonable and works, I'll update this thread to share the solution with the community. Thanks again, you guys are really helping me out!
FoxTheDog Posted February 4, 2022 Author Posted February 4, 2022 Well this was incredibly simple after all, the solution suggested by @Manny and @Adam works like a charm. I fixed up some deprecated code but used the script linked above mostly as is. For the sake of completeness, I wrote a tiny script that takes the Terrain component from Gaia and assigns the terrain data and collider components to the deep copy. I only have one tile per scene here, but you easily could iterate over the hierarchy and get the terrain component at runtime rather than assign it in the editor like I do here. ,Literally copy pasted from the thread above. using UnityEngine; // Uses TerrainDataCloner to create a deep copy of the terrain. // Subsequent edits to the terrain and its collider at runtime will be // made to the deep copy rather than the original. // Useful if you re-use a handful of terrains with procedurally spawned // prefabs that modify the mesh and/or details. // // TerrainDataCloner: https://gist.github.com/Eldoir/d5a438dfedee55552915b55097dda1d4 // Unity thread: https://tinyurl.com/ykbd2fze public class TerrainCloneRestore : MonoBehaviour { [SerializeField] Terrain terrain; private void Awake() { terrain.terrainData = TerrainDataCloner.Clone(terrain.terrainData); terrain.GetComponent<TerrainCollider>().terrainData = terrain.terrainData; } } Thanks again!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now