Unity动态修改Terrain地形及地形纹理(如何破坏地形)

本文介绍如何在Unity中通过代码实现地形的凹凸变化和地形纹理的修改,包括使用SetAlphamaps和SetHeights方法。内容涉及调整地形纹理序号、改变地形基本单位以及处理地形高度问题。同时警告了地形修改后可能会保留,并提醒不支持地形高度为负数,建议使用SetHeight刷高地形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Unity如何通过代码地形凹凸和修改地形纹理(地形贴图)

实现效果(具体形状可以在代码中更改)
在这里插入图片描述

主要方法
SetAlphamaps和SetHeights

部分代码出处:地形贴图控制 地形凹凸控制

using System;
using System.Collections;
using UnityEngine;

public class TerrainUtil
{
   
   

    #region 地形控制

    /** 
     * Terrain的HeightMap坐标原点在左下角
     *   y
     *   ↑
     *   0 → x
     */

    /// <summary>
    /// 返回Terrain上某一点的HeightMap索引。
    /// </summary>
    /// <param name="terrain">Terrain</param>
    /// <param name="point">Terrain上的某点</param>
    /// <returns>该点在HeightMap中的位置索引</returns>
    public static int[] GetHeightmapIndex(Terrain terrain, Vector3 point)
    {
   
   
        TerrainData tData = terrain.terrainData;
        float width = tData.size.x;
        float length = tData.size.z;

        // 根据相对位置计算索引
        int x = (int)((point.x - terrain.GetPosition().x) / width * tData.heightmapWidth);
        int y = (int)((point.z - terrain.GetPosition().z) / length * tData.heightmapHeight);

        //mapX = (int)(((point.x - terrainPosition.x) / terrainData.size.x) * heightmapWidth);
        //mapY = (int)(((point.z - terrainPosition.z) / terrainData.size.z) * heigtmapHeight);


        return new int[2] {
   
    x, y };
    }

    public static float[] GetHeightmapIndex(Terrain terrain, Vector3 point, bool Float)
    {
   
   
        TerrainData tData = terrain.terrainData;
        float width = tData.size.x;
        float length = tData.size.z;

        // 根据相对位置计算索引
        float x = (float)((point.x - terrain.GetPosition().x) / width * tData.heightmapWidth);
        float y = (float)((point.z - terrain.GetPosition().z) / length * tData.heightmapHeight);

        //mapX = (int)(((point.x - terrainPosition.x) / terrainData.size.x) * heightmapWidth);
        //mapY = (int)(((point.z - terrainPosition.z) / terrainData.size.z) * heigtmapHeight);

        return new float[2] {
   
    x, y };
    }

    /// <summary>
    /// 返回GameObject在Terrain上的相对(于Terrain的)位置。
    /// </summary>
    /// <param name="terrain">Terrain</param>
    /// <param name="go">GameObject</param>
    /// <returns>相对位置</returns>
    public static Vector3 GetRelativePosition(Terrain terrain, GameObject go)
    {
   
   
        return go.transform.position - terrain.GetPosition();
    }

    /// <summary>
    /// 返回Terrain上指定点在世界坐标系下的高度。
    /// </summary>
    /// <param name="terrain">Terrain</param>
    /// <param name="point">Terrain上的某点</param>
    /// <param name="vertex">true: 获取最近顶点高度  false: 获取实际高度</param>
    /// <returns>点在世界坐标系下的高度</returns>
    public static float GetPointHeight(Terrain terrain, Vector3 point, bool vertex = false)
    {
   
   
        // 对于水平面上的点来说,vertex参数没有影响
        if (vertex)
        {
   
   
            // GetHeight得到的是离点最近的顶点的高度
            int[] index = GetHeightmapIndex(terrain, point);
            return terrain.terrainData.GetHeight(index[0], index[1]);
        }
        else
        {
   
   
            // SampleHeight得到的是点在斜面上的实际高度
            return terrain.SampleHeight(point);
        }
    }

    /// <summary>
    /// 返回Terrain的HeightMap,这是一个 height*width 大小的二维数组,并且值介于 [0.0f,1.0f] 之间。
    /// </summary>
    /// <param name="terrain">Terrain</param>
    /// <param name="xBase">检索HeightMap时的X索引起点</param>
    /// <param name="yBase">检索HeightMap时的Y索引起点</param>
    /// <param name="width">在X轴上的检索长度</param>
    /// <param name="height">在Y轴上的检索长度</param>
    /// <returns></returns>
    public static float[,] GetHeightMap(Terrain terrain, int xBase = 0, int yBase = 0, int width = 0, int height = 0)
    {
   
   
        if (xBase + yBase + width + height == 0)
        {
   
   
            width = terrain.terrainData.heightmapWidth;
            height = terrain.terrainData.heightmapHeight;
        }

        return terrain.terrainData.GetHeights(xBase, yBase, width, height);
    }

    /// <summary>
    /// 升高Terrain上某点的高度。
    /// </summary>
    /// <param name="terrain">Terrain</param>
    /// <param name="point">Terrain上的点</param>
    /// <param name="opacity">升高的高度</param>
    /// <param name="size">笔刷大小</param>
    /// <param name="amass">当笔刷范围内其他点的高度已经高于笔刷中心点时是否同时提高其他点的高度</param>
    public static void Rise(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值