Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Dynamic Terrain Manipulation, TreePrototypes, Prefabs, etc.

Discussion in 'Scripting' started by Aubrey-Falconer, Dec 5, 2009.

  1. Aubrey-Falconer

    Aubrey-Falconer

    Joined:
    Feb 13, 2008
    Posts:
    438
    In order to dynamically add trees to terrain objects via scripting, I create a TreePrototype object for each tree my script builds. In order to create a TreePrototype object, I have to create a Prefab object to populate with the tree before passing it to the TreePrototype.

    Unfortunately, I can't figure out any possible way to create a prefab object via scripting.

    I am currently creating 10 empty prefabs in the editor, assigning them to an array, and then later populating them with trees in my script, assigning them to TreePrototypes, and placing them on terrains - but this is an incredibly dumb solution.

    How do I initialize a Prefab object via scripting?
    Note that Prefabs are somehow different from GameObjects - passing a GameObject to a TreePrototype does not work.

    Thanks,

    -Aubrey
     
  2. KaelisAsur

    KaelisAsur

    Joined:
    Apr 9, 2009
    Posts:
    361
  3. Aubrey-Falconer

    Aubrey-Falconer

    Joined:
    Feb 13, 2008
    Posts:
    438
    Exactly :)

    I have played with the EditorUtility prefab system - but only functioning as an EditorScript is a dealbreaker.

    If it really is impossible to create terrain details at runtime from scratch due to their (rather strange) dependance on prefabs, this is a huge oversight on Unity's part!

    I suppose I should submit a bug report...
     
  4. KaelisAsur

    KaelisAsur

    Joined:
    Apr 9, 2009
    Posts:
    361
    Theres no bug, so no use submitting bug reports...

    As far as i know, the terrain system was done by a third party and later integrated into Unity, and judging by the lack of documentation, i guess they dont want us messing with it. I too hate how inflexible and closed in general the terrain system is, but it makes sense.
     
  5. Aubrey-Falconer

    Aubrey-Falconer

    Joined:
    Feb 13, 2008
    Posts:
    438
    I understand with your position, but I have put a ton of effort into "prying open" the terrain system - and I can now do practically anything with a terrain through scripting except for creating trees and details from absolute scratch :)

    I'll abstain from bug reporting for now and stick with my terribly ugly preprefab hack, but I sure hope Unity sees fit to breath some new life into documented terrain scripting in the future...
     
  6. Furfire

    Furfire

    Joined:
    Feb 27, 2011
    Posts:
    23
    Its possible to change the terrain hight at a certain point during runtime?
     
  7. Antitheory

    Antitheory

    Joined:
    Nov 14, 2010
    Posts:
    549
    Yes, and there was no need to ask the question in this outdated thread. There are other threads that detail all kinds of runtime Terrain manipulation.

    The method you want is

    terrain.terrainData.SetHeight(int heightmapX, int heightmapY, float normalizedHeight)
     
  8. KyleStaves

    KyleStaves

    Joined:
    Nov 4, 2009
    Posts:
    821
    The tree prefabs and tree instances are two different things entirely.

    For each type of tree you want, you need a tree prefab - one per type. Usually you can (and should) set this up in the editor not at runtime. If you need to generate the terrain 100% from scratch you still can though, just by replacing this array with a new array of prefab references:

    http://unity3d.com/support/documentation/ScriptReference/TerrainData-treePrototypes.html

    After you adjust that array, make sure you run yourTerrain.terrainData.RefreshPrototypes();

    Now your terrain has the prototype(s) you want to spawn, time to actually to about adding the tree instances (the individual trees).

    Code (csharp):
    1.  
    2. public void SpawnTree(Vector3 position){
    3.         if (MapTerrain.terrainData.treePrototypes.Length > 0){
    4.             TreeInstance newInstance = new TreeInstance();
    5.             newInstance.position = WorldToTerrainPoint(position);
    6.             newInstance.heightScale = 0.3f;
    7.             newInstance.widthScale = 0.3f;
    8.             newInstance.prototypeIndex = 0;
    9.             newInstance.lightmapColor = Color.white;
    10.             newInstance.color = Color.white;
    11.             MapTerrain.AddTreeInstance(newInstance);
    12.             MapTerrain.Flush();
    13.         }
    14.     }
    15.  
    Code (csharp):
    1.  
    2. TreeInstance newInstance = new TreeInstance();
    3. newInstance.position = new Vector3(wherever you want it);
    4. newInstance.heightScale = 1; newInstance.widthScale = 1;
    5. newInstance.prototypeIndex = whatever index you want (if you only have 1 prototype, just set this to zero)
    6. newInstance.lightmapColor = Color.white; If you don't set the lightMap color your trees will appear as black silhouettes
    7. newInstance.lightmapColor = Color.white;
    8.  
    9. YourTerrain.AddTreeInstance(newInstance);
    10. MapTerrain.Flush();
    11.  
    If you are generating a lot of trees, I suggest making your own TreeInstance[] - populating that - and replacing the YourTerrain.terrainData.treeInstances variable with your own array instead of pushing each individual tree (for performance reasons).

    NOTE:
    The location of your trees is based on a float from 0 to 1, it is NOT a world position. (so 0,0 = bottom right corner of the terrain, 1,1 = top left, or vice versa - don't remember off the top of my head).

    For the heights yea, SetHeight() is the ticket there. I *STRONGLY* recommend using SetHeights though and setting the entire hightmap in a single call, as the performance impact of calling SetHeight for every pixel in the heightmap is huge.

    EDIT:
    /facepalm - sorry, didn't realize this thread was a necro.

    @Furfire - yea, you want SetHeight/SetHeights (the same advice applies, do it all in a single call if you can - much faster). You *may* need to call YourTerrain.Flush() after you do this to see the changes, not sure if the heightmap requires a flush or not off the top of my head.
     
  9. Furfire

    Furfire

    Joined:
    Feb 27, 2011
    Posts:
    23
    Apologies, I ran into this thread on Google and didn't realize how old it was XD