unity3d地形系统总结

发布时间:2019-09-12 08:00:21编辑:auto阅读(2455)


    前言:

    本文不是讲地形编辑器的使用,而是主要讲解(1)地形相关知识(2)使用代码创建地形(3)使用AnimationCurve创建曲面地形(4)使用photoshop绘制地形表面,即SplatAlphaMap(5)使用代码为地形添加树

                             地形

    本讲结构:

    一:地形的基础知识

    (1)地形编辑器的不足

    (2)地形结构

    (3)地形与SplatAlpha

    二:动态创建地形

    (1)动态创建简单平面地形

    (2)动态创建凹凸地形

    (3)利用AnimationCurve创建特殊曲线地形。

    (4)动态创建地形,并设置splatPrototypes,最后使用photoShop绘制2D图编辑地形贴图。

    (5)动态创建地形,使用photoShop绘制 多张splats

    三:地形与树

    (1)TreePrototypes

    (2)TreeInstances

    一:地形的基础知识

    (0)基本术语

    Splat:地形所使用的贴图,即Terrain Texture。术语叫Splat或者 Splat map。

    Splat Alhpa Map:地形贴图布局图,用图的rgba各个通道来表示贴图在地形上的使用,project界面里展开地形即可看见。术语叫Splat Alpha Map,或者Alpha Map.

    (1)地形编辑器的不足

    地形Terrain是3D游戏里必不可少的一部分。Unity提供的地形编辑器也十分好用,但是依然有少许不足和缺陷。

    Unity地形编辑器的不足:

    1)地形只能是成片的抬高或者降低。如果想定制某特定斜率,或者特定曲线的地形就没法实现了。

    2)地形不能实时改变。

    不过Unity提供了强大的地形脚本接口,可以弥补上述不足。

    (2)地形结构

    首先要清楚, Terrain地形的包括Heightmap高度图,贴图信息,树信息等几乎所有数据都是储存TerrainData里,而TerrainData可以保存成地形文件,地形文件后缀为.asset。任意工程导入地形文件后,在project窗口下都会显示为地形文件。

    TerrainData的基本属性:

    1.terrainData.heightmapResolution int,高度图的长宽分辨率,一般是2的幂加1,如513

    2.terrainData.baseMapResolution int,Resolution of the base map used for rendering far patches on the terrain

    如513

    3.terrainData.size:   Vector3,地形世界里的尺寸,world unit. 如new Vector3(50, 50, 50);

    4.terrainData.alphamapResolution alphamap的分辨率,如512;

    地形贴图信息储存在Terrain之下的SplatAlpha图里。在project窗口展开一个地形,会看到之下的贴图信息,名称格式为SplatAlpha xx.

    【风宇冲】Unity3D教程宝典之地形

    (3)地形与SplatAlpha

    在SplatAlpha图中

    红=第1张贴图

    绿=第2张贴图

    蓝=第3张贴图

    Alpha=第4张贴图

    第5张贴图开始,会创建新的SplatAlpha图,然后继续 红绿蓝黑 如此循环。

    alphamap:指的是纹理中某通道的颜色, refer to a grayscale p_w_picpath residing in a single channel of a texture

    Splat:一张纹理贴图和其对应的alphamap统称为一个splat。 主要是分块,divide in chunks.所以可以使用LOD等技术

    terrainData.splatPrototypes 就是地形包含的贴图信息

    splatPrototypes 为SplatPrototype[],

    SplatPrototype为单张贴图信息

    SplatPrototype的属性有

    SplatPrototype.texture     Texture2D,地形贴图

    SplatPrototype.tileOffset   Vector2,图块偏移

    SplatPrototype.tileSize     Vector2,图块尺寸(World Unit)

    terrainData.SetAlphamaps(int x,int y,float[,,]) ,其中x,y为起点

    float[i,j,k]为通道信息,i,j为对应的点,k为第几张图,float值储存的是该点该图的灰度值。

    terrainData.splatPrototypes的长度 = 贴图数量 = splatArray (float[,,])的第三维的长度


    二:动态创建地形

    (1)动态创建简单平面地形

    创建地形是不需要using UnityEditor的,这里使用了AssetDatabase,所以需using UnityEditor;

    创建三步:

    1.TerrainData  terrainData = new TerrainData();

    2.设置terrainData的属性

    3.根据terrainData创建地形

      GameObject obj = Terrain.CreateTerrainGameObject(terrainData);

    具体脚本如下:

    1. using 

      UnityEngine;

    2. using 

      System.Collections;

    3. using 

      UnityEditor;


    4. public 

      class 

      Tutor_1_CreateSimpleTerrain : 

      MonoBehaviour 

      {

    5. void 

      Start()

    6. {

    7. CreateTerrain();

    8. }

    9. public 

      Terrain 

      CreateTerrain()

    10. {

    11. TerrainData  terrainData = 

      new 

      TerrainData();

    12. terrainData.heightmapResolution = 

      513;

    13. terrainData.baseMapResolution = 

      513;

    14. terrainData.size = 

      new 

      Vector3(50, 

      50, 

      50);

    15. terrainData.alphamapResolution = 

      512;

    16.      

      terrainData.SetDetailResolution(32, 

      8);

    17. GameObject 

      obj = 

      Terrain.CreateTerrainGameObject(terrainData);

    18. AssetDatabase.CreateAsset(terrainData, 

      "Assets/Tutorial/Tutor_1_SimpleTerrain.asset");

    19.      

      AssetDatabase.SaveAssets();

    20. return  

      obj.GetComponent<</span>Terrain>();

    21. }

    22. }

    (2)动态创建凹凸地形

    接下来改变地形的高度。地形高度是用heightmap存储的。

    代码里通过TerrainData.GetHeights()读取高度图里的二维高度数组,

    通过TerrainData.SetHeights()设置高度图里的二维高度数组。

    TerrainData.GetHeights(int x的起点,int y的起点,int 读取高度的宽度范围, int 读取高度的高度范围),返回float[,] ,二维高度数组

    TerrainData.SetHeights(int x的起点,int y的起点,float[,] 二维高度数组),返回void


    例子:在创建地形前,改变地形的高度,代码如下:

    1. using 

      UnityEngine;

    2. using 

      System.Collections;

    3. using 

      UnityEditor;


    4. public 

      class 

      Tutor_2_CreateTerrain_ModifyHeight : 

      MonoBehaviour 

      {

    5. void 

      Start()

    6. {

    7. CreateTerrain();

    8. }

    9. public 

      Terrain 

      CreateTerrain()

    10. {

    11. TerrainData  terrainData = 

      new 

      TerrainData();

    12. terrainData.heightmapResolution = 

      513;

    13. terrainData.baseMapResolution = 

      513;

    14. terrainData.size = 

      new 

      Vector3(50, 

      50, 

      50);

    15. terrainData.alphamapResolution = 

      512;

    16.      

      terrainData.SetDetailResolution(32, 

      8);

    17. ModifyTerrainDataHeight(terrainData);

    18. GameObject 

      obj = 

      Terrain.CreateTerrainGameObject(terrainData);

    19. AssetDatabase.CreateAsset(terrainData,"Assets/Tutorial/Tutor_2_Terrain_ModifyHeight.asset");

    20.      

      AssetDatabase.SaveAssets();

    21. return  

      obj.GetComponent<</span>Terrain>();

    22. }

    23. public 

      void 

      ModifyTerrainDataHeight(TerrainData 

      terrainData)

    24. {

    25. int 

      width = terrainData.heightmapWidth;

    26. int 

      height = terrainData.heightmapHeight;

    27. float[,] array = 

      new 

      float[width,height];

    28. print ("width:"+ width +" height:"+ height );

    29. for(int 

      i=0; i< width;i++)

    30. for(int 

      j=0; j< height;j++)

    31. {

    32. float 

      f1 = i;

    33. float 

      f2 = width;

    34. float 

      f3 = j;

    35. float 

      f4 = height;

    36. float 

      baseV =  

      (f1/f2 + f3/f4)/2 

      *  

      1;

    37. array[i,j] =baseV*baseV;

    38. }

    39. terrainData.SetHeights(0,0,array);

    40. }

    41. }

     

    (3)利用AnimationCurve创建特殊曲线地形。

    之前风宇冲有一篇关于AnimationCurve的教程,现在我们就来看看如何用AnimationCurve来控制地形的起伏。

    步骤:

    1.创建一个新场景,并新建一个GameObject起名为Manager,新建一个名为Tutor_3_CreateTerrainWithAnimationCurve.cs的脚本并拖至Manager上。

    2.粘贴并覆盖如下脚本至Tutor_3_CreateTerrainWithAnimationCurve里

     

    1. using 

      UnityEngine;

    2. using 

      System.Collections;


    3. public 

      class 

      Tutor_3_CreateTerrainWithAnimationCurve : 

      MonoBehaviour 

      {

    4. public 

      AnimationCurve 

      animationCurve;

    5. }

    3.在Manager的Inspector面板里双击Animation Curve。在弹出曲线绘制界面后,绘制任意曲线,如下。

    【风宇冲】Unity3D教程宝典之地形

    之后还是设置高度,即terrainData.SetHeights(0,0,array);只是对array里高度的赋值变为如下

    array[i,j] = animationCurve.Evaluate(f1/f2); 其中f1是array里的y,f2是整个高度图的高度。具体代码如下:

    1. using 

      UnityEngine;

    2. using 

      System.Collections;

    3. using 

      UnityEditor;


    4. public 

      class 

      Tutor_3_CreateTerrainWithAnimati

      onCurve : 

      MonoBehaviour 

      {

    5. public AnimationCurve 

      animationCurve;

    6. void 

      Start()

    7. {

    8. CreateTerrain();

    9. }

    10. public 

      Terrain 

      CreateTerrain()

    11. {

    12. TerrainData 

       terrainData = 

      new TerrainData();

    13. terrainData.heightmapResolution = 

      513;

    14. terrainData.baseMapResolution = 

      513;

    15. terrainData.size = 

      new 

      Vector3(50, 

      50, 

      50);

    16. terrainData.alphamapResolution = 

      512;

    17.  

        

       

       terrainData.SetDetailResolution(32, 

      8);

    18. ModifyTerrainDataHeight(terrainData);

    19. GameObject 

      obj = 

      Terrain.CreateTerrainGameObject(terrainData);

    20. AssetDatabase.CreateAsset(terrainData,"Assets/Tutorial/Tutor_3_TerrainWithAnimationCurv

      e.asset");

    21.  

        

       

       

      AssetDatabase.SaveAssets();

    22. return 

       obj.GetComponent();

    23. }

    24. public 

      void 

      ModifyTerrainDataHeight(TerrainData 

      terrainData)

    25. {

    26. int 

      width = terrainData.heightmapWidth;

    27. int 

      height = terrainData.heightmapHeight;

    28. float[,] array = 

      new 

      float[width,height];

    29. print ("width:"+ width +" height:"+ height );

    30. for(int 

      i=0; i< width;i++)

    31. for(int 

      j=0; j< height;j++)

    32. {

    33. float 

      f1 = j;

    34. float 

      f2 = height;

    35. array[i,j] = animationCurve.Evaluate(f1/f2);

    36. }

    37. terrainData.SetHeights(0,0,array);

    38. }

    39. }

    最后创建的地形和我们之前设置的曲线一致。

    【风宇冲】Unity3D教程宝典之地形

    (4)动态创建地形,并设置splatPrototypes,最后使用photoShop绘制2D图编辑地形贴图。

    步骤:

    1.创建一个新场景并命名为Tutor_4_CreateTerrainWithSplat,并新建一个GameObject起名为Manager,新建一个名为
    Tutor_4_CreateTerrainWithSplat.cs的脚本并拖至Manager上。

    2.粘贴并覆盖如下脚本至Tutor_4_CreateTerrainWithSplat里,该脚本与上个例子的脚本基本一致。

    1. using 

      UnityEngine;

    2. using 

      System.Collections;

    3. using 

      UnityEditor;


    4. public 

      class 

      Tutor_4_CreateTerrainWithSplat : 

      MonoBehaviour 

      {

    5. public 

      AnimationCurve 

      animationCurve;

    6. void 

      Start()

    7. {

    8. CreateTerrain();

    9. }

    10. public 

      Terrain 

      CreateTerrain()

    11. {

    12. TerrainData  terrainData = 

      new 

      TerrainData();

    13. terrainData.heightmapResolution = 

      513;

    14. terrainData.baseMapResolution = 

      513;

    15. terrainData.size = 

      new 

      Vector3(50, 

      50, 

      50);

    16. terrainData.alphamapResolution = 

      512;

    17.      

      terrainData.SetDetailResolution(32, 

      8);

    18. ModifyTerrainDataHeight(terrainData);

    19. GameObject 

      obj = 

      Terrain.CreateTerrainGameObject(terrainData);

    20. AssetDatabase.CreateAsset(terrainData, 

      "Assets/Tutorial/Tutor_4_TerrainWithSplats.asset");

    21.      

      AssetDatabase.SaveAssets();

    22. return  

      obj.GetComponent<</span>Terrain>();

    23. }

    24. public 

      void 

      ModifyTerrainDataHeight(TerrainData 

      terrainData)

    25. {

    26. int 

      width = terrainData.heightmapWidth;

    27. int 

      height = terrainData.heightmapHeight;

    28. float[,] array = 

      new 

      float[width,height];

    29. print ("width:"+ width +" height:"+ height );

    30. for(int 

      i=0; i< width;i++)

    31. for(int 

      j=0; j< height;j++)

    32. {

    33. float 

      f1 = j;

    34. float 

      f2 = height;

    35. array[i,j] = animationCurve.Evaluate(f1/f2);

    36. }

    37. terrainData.SetHeights(0,0,array);

    38. }

    39. }

    之后添加地形贴图变量,在脚本里加上public Texture2D[] splats;

    然后在Inspector里指定任意一张贴图。

    现在开始添加Splat了。

    核心是SplatPrototype,也就是Splat原型的信息,包含贴图信息和地形块的信息。

    SplatPrototype outSplatPrototype = new SplatPrototype();

    之后设置SplatPrototype的如下属性

    outSplatPrototype.texture: 贴图

    outSplatPrototype.tileOffset:地形块的偏移。

    outSplatPrototype.tileSize:地形块的尺寸

    组成好SplatPrototype[] outSplatPrototypes后,赋予TerrainData.splatPrototypes 即可。

    代码如下。

    1. using 

      UnityEngine;

    2. using 

      System.Collections;

    3. using 

      UnityEditor;


    4. public 

      class 

      Tutor_4_CreateTerrainWithSplat : 

      MonoBehaviour 

      {

    5. public 

      AnimationCurve 

      animationCurve;

    6. public 

      Texture2D[] splats;

    7. void 

      Start()

    8. {

    9. CreateTerrain();

    10. }

    11. public 

      Terrain 

      CreateTerrain()

    12. {

    13. TerrainData  terrainData = 

      new 

      TerrainData();

    14. terrainData.heightmapResolution = 

      513;

    15. terrainData.baseMapResolution = 

      513;

    16. terrainData.size = 

      new 

      Vector3(50, 

      50, 

      50);

    17. terrainData.alphamapResolution = 

      512;

    18.      

      terrainData.SetDetailResolution(32, 

      8);

    19. terrainData.splatPrototypes = CreateSplatPrototypes(splats,new 

      Vector2(15,15),newVector2(0,0)); 

    20. ModifyTerrainDataHeight(terrainData);

    21. GameObject 

      obj = 

      Terrain.CreateTerrainGameObject(terrainData);

    22. AssetDatabase.CreateAsset(terrainData, 

      "Assets/Tutorial/Tutor_4_TerrainWithSplats.asset");

    23.      

      AssetDatabase.SaveAssets();

    24. return  

      obj.GetComponent<</span>Terrain>();

    25. }

    26. public 

      void 

      ModifyTerrainDataHeight(TerrainData 

      terrainData)

    27. {

    28. int 

      width = terrainData.heightmapWidth;

    29. int 

      height = terrainData.heightmapHeight;

    30. float[,] array = 

      new 

      float[width,height];

    31. for(int 

      i=0; i< width;i++)

    32. for(int 

      j=0; j< height;j++)

    33. {

    34. float 

      f1 = j;

    35. float 

      f2 = height;

    36. array[i,j] = animationCurve.Evaluate(f1/f2);

    37. }

    38. terrainData.SetHeights(0,0,array);

    39. }

    40. public 

      SplatPrototype[] CreateSplatPrototypes(Texture2D[] tmpTextures,Vector2 

      tmpTileSize,Vector2 

      tmpOffset)

    41. {

    42. SplatPrototype[] outSplatPrototypes = 

      new 

      SplatPrototype[tmpTextures.Length];

    43. for(int 

      i =0;i

    44. {

    45. outSplatPrototypes[i] = CreateSplatPrototype(tmpTextures[i],tmpTileSize,tmpOffset);

    46. }

    47. return 

      outSplatPrototypes;

    48. }

    49. public 

      SplatPrototype 

      CreateSplatPrototype(Texture2D 

      tmpTexture, 

      Vector2 

      tmpTileSize,Vector2 

      tmpOffset)

    50. {

    51. SplatPrototype 

      outSplatPrototype = 

      new 

      SplatPrototype();

    52. outSplatPrototype.texture = tmpTexture;

    53. outSplatPrototype.tileOffset = tmpOffset;

    54. outSplatPrototype.tileSize = tmpTileSize ;

    55. return 

      outSplatPrototype;

    56. }

    57. }

    之前的例子,创建出来的地形在project界面里一直不能展开,因为没有任何splat信息。而本例中,指定TerrainData.splatPrototypes,即有了splat的原型信息后,就会自动生成splat图,因此地形可以展开了。

    展开出来的SplatAlpha 01为纯红,表示整个地图铺的都是第一张地形贴图。

    【风宇冲】Unity3D教程宝典之地形

    现在我们再进一步,通过Photoshop绘制splat的alpha图。

    1.选中Manager,在Inspector面板里,将Terrain Textures设置为任意两张贴图,这里用的是unity Terrain包里的“Grass&Rock”和 “Grass (Hill)” 两张贴图。

    2.然后脚本里也添加splats属性,public Texture2D[] splatAlphaMaps;

    3.打开photoshop,创建一张512x512的rgb图,先铺满红色,在绘制一些绿色,如下图

    【风宇冲】Unity3D教程宝典之地形
    之后导出为splatAlphaMap1.png

    4.将该图拖进unity,并设置Import Settings里的 Texture Type为Advanced,然后勾选Read/Write Enable。最后把importType设置为Default(importType不能为其他的)。

    【风宇冲】Unity3D教程宝典之地形

    5. Manager的Inspector面板里,splatAlphaMaps,此Texture2D数组设置为1,并指定为splatAlphaMap1

    6.在Tutor_4_CreateTerrainWithSplat脚本里补充以下函数

    1. public float[,,] CreateSplatAlphaArray(Texture2D[] splatAlphaMaps,int numOfSplatPrototypes )

    2. {

    3. List cArray = new List();

    4. int splatAlphaMap_SizeX = splatAlphaMaps[0].width;

    5. int splatAlphaMap_SizeY = splatAlphaMaps[0].height;

    6. float[,,] outSplatAlphaArray = new float[splatAlphaMap_SizeX,splatAlphaMap_SizeY,numOfSplatPrototypes];

    7. //第几张SplatAlphaMap

    8. for(int splatAlphaMapIndex=0; splatAlphaMapIndex

    9. {

    10. //RGBA第几个通道

    11. for(int alphaIndex =0;alphaIndex<4; alphaIndex ++)

    12. {

    13. //Splat ID

    14. int splatIndex = alphaIndex+splatAlphaMapIndex*4;

    15. //仅当Splat ID小于Splat的数量时

    16. if(splatIndex < numOfSplatPrototypes)

    17. {

    18. for (int index_heightmapY = 0; index_heightmapY < splatAlphaMap_SizeY; index_heightmapY++)

    19.  

        

        

        

      {

    20.  

        

        

        

        

       for (int index_heightmapX = 0; index_heightmapX < splatAlphaMap_SizeX; index_heightmapX++)

    21.  

        

        

        

        

        

      {

    22. //取第splatAlphaMapIndex张SplatAlphaMap上的位于index_heightmapY,index_heightmapX的颜色值

    23. Color c =  

      splatAlphaMaps[splatAlphaMapIndex].GetPixel(index_heightmapY,index_heightmapX);

    24. cArray.Add(c);

    25. //赋予outSplatAlphaArray的index_heightmapX,index_heightmapY,splatIndex对应的通道值

    26. outSplatAlphaArray[index_heightmapX, index_heightmapY, splatIndex] = c[ alphaIndex ];

    27. }

    28. }

    29. }

    30. else

    31. {

    32. return outSplatAlphaArray;

    33. }

    34. }

    35. }

    36. return outSplatAlphaArray;

    37. }

     之后在Start函数里的CreateTerrain();后面补充代码如下

    1.  void 

      Start()

    2. {

    3. CreateTerrain();

    4. TerrainData 

      terData =AssetDatabase.LoadAssetAtPath("Assets/Tutorial/Tutor_4_TerrainWithSplats.asset",typeof(TerrainData)) 

      as TerrainData;

    5. float[,,] splatAlphaArray = CreateSplatAlphaArray(splatAlphaMaps, terData.splatPrototypes.Length);

    6. terData.SetAlphamaps(0,0,splatAlphaArray);

    7. }

    之后点击运行,发现地形确实是我们之前在photoshop里绘制的形状,如下

    【风宇冲】Unity3D教程宝典之地形

    注意:

    1.SetAlphamaps函数 必须在创建TerrainData文件,即xxx.asset后,再读取该TerrainData调用。

    (5)动态创建地形,使用photoShop绘制 多张splats

    三张以下的地形贴图一般不会出错,但是超过四张时就要注意了。用photoShop绘制a通道并导入unity是比较容易出错的。

    1.打开Photoshop,新建一张图,如下。

    【风宇冲】Unity3D教程宝典之地形

    2.用黑色平铺整张图后,添加一个通道

    【风宇冲】Unity3D教程宝典之地形

    3.选中Red通道,然后用纯白画笔在顶端画一条横线

    【风宇冲】Unity3D教程宝典之地形
    4.用3.的方法在gba通道依次往下画横线.
    【风宇冲】Unity3D教程宝典之地形 【风宇冲】Unity3D教程宝典之地形
    5.保存成splatAlpha.psd文件并拖入unity工程。

    注意:如果导入的贴图是有a通道的话,一定要保证在Preview里看到的是RGBA,即有A的字样。有时候在photoshop里即使有a,保存成png或者tga再导入unity,有时候会没有A,那么就是错的。

    【风宇冲】Unity3D教程宝典之地形

    6.打开(4)里创建的Tutor_4_CreateTerrainWithSplat场景,另存为Tutor_5_CreateTerrainWithSplat2。

    7.选中Manager,然后将Splats设置为4张并指定贴图。将Splat Alpha Maps设置为一张并指定为splatAlpha.psd

    之后运行,发现新建的地形确实是按splatAlpha.psd里的色带分布。

    【风宇冲】Unity3D教程宝典之地形

    之后我们再进一步,再在Splats里加第5张贴图,那么该splat图就对应第二张splatAlpha图的红色。

    8.photoShop里按上面的方法建张图,画个红色的竖条,并保存为splatAlpha2.psd

    【风宇冲】Unity3D教程宝典之地形
    9.选中Manager,然后将Splats设置为5张,指定第5张贴图。将Splat Alpha Maps设置为2并指定为之前的splatAlpha.psd和splatAlpha2.psd

    之后运行,效果如下
    【风宇冲】Unity3D教程宝典之地形

    三:地形与树

    地形的绘制树功能十分强大,而且不仅可以绘制树,任意物体都可以都可以被当做树来铺在地形上。

    (1)TreePrototypes

    该步风宇冲用代码做总是出错,搜了也找不到解决方法,只好用地形编辑器来添加树的原型。现在把代码贴出来,

    欢迎高手指出问题所在。

    代码如下,unity显示在terrainData.treePrototypes = new TreePrototype[1];这行有null

    1. using 

      UnityEngine;

    2. using 

      System.Collections;

    3. using 

      UnityEditor;


    4. public 

      class 

      Tutor_6_TreePrototype : 

      MonoBehaviour 

      {

    5. public 

      GameObject 

      treePrefab;

    6. public 

      TerrainData 

      terrainData;

    7. void 

      Start()

    8. {

    9. CreateTerrain();

    10. }

    11. public 

      Terrain 

      CreateTerrain()

    12. {

    13. TerrainData  terrainData = 

      new 

      TerrainData();

    14. terrainData.heightmapResolution = 

      513;

    15. terrainData.baseMapResolution = 

      513;

    16. terrainData.size = 

      new 

      Vector3(50, 

      50, 

      50);

    17. terrainData.alphamapResolution = 

      512;

    18.      

      terrainData.SetDetailResolution(32, 

      8);

    19. TreePrototype 

      treePrototype = 

      new 

      TreePrototype();

    20. treePrototype.prefab = treePrefab;

    21. treePrototype.bendFactor = 

      1;

    22. terrainData.treePrototypes = 

      new 

      TreePrototype[1];

    23. terrainData.treePrototypes[0] = treePrototype;

    24. GameObject 

      obj = 

      Terrain.CreateTerrainGameObject(terrainData);

    25. AssetDatabase.CreateAsset(terrainData, 

      "Assets/Tutorial/Tutor_1_SimpleTerrain.asset");

    26.      

      AssetDatabase.SaveAssets();

    27. return  

      obj.GetComponent<</span>Terrain>();

    28. }

    29. }

     

    (2)TreeInstances

    TreeInstances

    步骤:

    1.创建TreeInstance

    TreeInstance tmpTreeInstances = new TreeInstance();

    2.设置TreeInstance属性

    TreeInstance.prototypeindex:使用的prototype序号,从0开始

    TreeInstance.position:在地形里的相对位置(不是世界坐标的位置),范围为[0,1]

    TreeInstance.color:树的颜色

    TreeInstance.lightmapColor:树如果有lightmap的话,lightmap的颜色

    TreeInstance.heightScale:树高的缩放 即y轴上的缩放

    TreeInstance.widthScale:树宽的缩放,即xz轴上的缩放

    3.地形Terrain添加TreeInstance

    Terrain terrain;

    terrain.AddTreeInstance(tmpTreeInstances);

    4.重设碰撞

    TerrainCollider  tc = terrain.GetComponent();

    tc.enabled = false;

    tc.enabled = true;


    例子:在整个地形上创建100个随机位置,大小为[0.8,1]间随机的树。脚本如下:

     

    1. using 

      UnityEngine;

    2. using 

      System.Collections;


    3. public 

      class 

      Tutor_6_TreeInstances : 

      MonoBehaviour 

      {

    4. public 

      Terrain 

      terrain;


    5. void 

      Start () {

    6. AddTrees(terrain,100);

    7. }

    8. public 

      void 

      AddTrees(Terrain 

      terrain,int 

      numOfTrees)

    9. {

    10. if(terrain.terrainData!=null)

    11. {

    12. terrain.terrainData.treeInstances = 

      new 

      TreeInstance[numOfTrees];

    13. for(int 

      i =0;i< numOfTrees;i++)

    14. {

    15. TreeInstance 

      tmpTreeInstances = 

      new 

      TreeInstance();

    16. tmpTreeInstances.prototypeIndex =0; 

      // ID of tree prototype

    17. tmpTreeInstances.position = 

      new 

      Vector3(Random.Range(0f,1f),0,Random.Range(0f,1f)); 

        

      // not regular pos,  [0,1]

    18. tmpTreeInstances.color = 

      new 

      Color(1,1,1,1);

    19. tmpTreeInstances.lightmapColor = 

      new 

      Color(1,1,1,1);//must add

    20. float 

      ss= 

      Random.Range(0.8f,1f);

    21. tmpTreeInstances.heightScale =ss; 

      //same size as prototype

    22. tmpTreeInstances.widthScale =ss;

    23. terrain.AddTreeInstance(tmpTreeInstances);

    24. }

    25. TerrainCollider  

      tc = terrain.GetComponent<</span>TerrainCollider>();

    26. tc.enabled = 

      false;

    27. tc.enabled = 

      true;

    28. }

    29. }

    30. } 

     结语:整个地形教程到此结束,希望对大家有所帮助。


关键字