Unity在不同地板发出不同的声音(上)
本文为该功能的上半部分,文章有参考很多大佬的文档,具体会在本文最后标注参考内容
这个功能的目的是为了实现一个功能,让角色在不同的地面发出不同的声音

原理
Unity搭建的场景一般有两种情况,一种是Terrain即用地形工具刷出来的地形,另一种是模型,即非地形工具的单独模型,所以需要把地形与非地形分开
非地形的可以直接通过Layer来判断声音,而地形的则只能通过RGB颜色来判断声音,RGB颜色判断不是那么方便,但是地形也只能这样判断,实在没找到别的办法
这里的实现方式是通过标记Layer来区分不同的材质,其中地形设置成一个单独的Layer
可能有人有个问题,是不是可以获取物体的材质名字来识别具体是什么材质,这样的话就可以不用标记Layer了,可以是可以,但是实际运用中不少物体拥有一堆材质,并不是一个单独材质,所以用Layer更靠谱

获得物体Layer
public RaycastHit rh;
public float distance = 10.0f;
public void LyaerCheck()
{
if (Physics.Raycast(transform.position, Vector3.down, out rh, distance))
{
//LayerMask.LayerToName 可以获得Layer的名字,如果直接rh.transform.gameObject.layer,返回的是编号
Debug.Log(LayerMask.LayerToName(rh.transform.gameObject.layer));
}
}
这个功能挂载在角色身上,就可以获得角色踩在的Layer的名字,但是要怎么触发呢,这里通过的方式是在动画上挂载事件的方式执行的,这个属于动画基础部分了,这里就不详细讲了

我们可以用一个代码来实现它
public void setFootStepRunSound()
{
//执行LyaerCheck()
}

设置物体Lyaer
既然我们可以获得物体的Layer了,所以我们可以为不同的Layer设置不同的声音,比如我这有个木楼梯,我可以设置成Wood,即木头的声音

我们用一个简单的代码就可以实现以下效果
public void LyaerCheck()
{
if (Physics.Raycast(transform.position, Vector3.down, out rh, distance))
{
switch (LayerMask.LayerToName(rh.transform.gameObject.layer))
{
case "Wood":
Debug.Log("发出木头的声音");
break;
case "Front":
Debug.Log("发出地形的声音");
break;
default:
Debug.Log("发出默认的声音");
break;
}
}
}


通过RGB判断地形
我们用一个简单的代码就可判断地形的RGBA颜色
public Transform playerTransform;
public Terrain t;
public int posX;
public int posZ;
public float[] textureValues;
void Start()
{
t = Terrain.activeTerrain;
playerTransform = gameObject.transform;
}
//在需要的地方运行GetTerrainTexture()即可获得地面的颜色
public void GetTerrainTexture()
{
ConvertPosition(playerTransform.position);
CheckTexture();
}
void ConvertPosition(Vector3 playerPosition)
{
Vector3 terrainPosition = playerPosition - t.transform.position;
Vector3 mapPosition = new Vector3
(terrainPosition.x / t.terrainData.size.x, 0,
terrainPosition.z / t.terrainData.size.z);
float xCoord = mapPosition.x * t.terrainData.alphamapWidth;
float zCoord = mapPosition.z * t.terrainData.alphamapHeight;
posX = (int)xCoord;
posZ = (int)zCoord;
}
void CheckTexture()
{
float[,,] aMap = t.terrainData.GetAlphamaps(posX, posZ, 1, 1);
textureValues[0] = aMap[0, 0, 0];
textureValues[1] = aMap[0, 0, 1];
textureValues[2] = aMap[0, 0, 2];
textureValues[3] = aMap[0, 0, 3];
}
我们运行一下游戏,在地上跑一下,记录一下RGBA值
然后修改下代码
public void LyaerCheck()
{
if (Physics.Raycast(transform.position, Vector3.down, out rh, distance))
{
switch (LayerMask.LayerToName(rh.transform.gameObject.layer))
{
case "Wood":
Debug.Log("发出木头的声音");
break;
case "Front":
checkTerrainTexture.GetTerrainTexture();
//草地
if (checkTerrainTexture.textureValues[1] > 0.8f)
Debug.Log("发出草地的声音");
else if (checkTerrainTexture.textureValues[2] > 0.8f)
Debug.Log("发出沙地的声音");
else
Debug.Log("发出默认的声音");
break;
default:
Debug.Log("发出默认的声音");
break;
}
}
}

本期就到这里了,下一期我们将分享如何把这些发出的声音注释用Fmod来接入
参考资料:
在 Unity 中使用 FMOD 实现脚步 – 亚历山德罗·法马 (alessandrofama.com)
注:之后会发个视频教程,这个是用来参考的笔记,如果看不懂可以点我头像查找相关视频,如果找不到视频那就是视频还没发