#57 - Character footstep sound based on terrain texture

Data: 2019-04-20 12:00 - c#

Simple class for Unity that gets the texture behind the character's position and plays the appropriate footstep sound.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FootstepAudio : MonoBehaviour {
	public AudioSource footstepSource;

	public void PlayFootstep() {
		AudioClip clip = SoundManager.Instance.defaultFootstep;

		RaycastHit hitInfo;
		if (Physics.Raycast(transform.position, Physics.gravity, out hitInfo, 0.4f)) {
			Terrain terrain = hitInfo.transform.GetComponent<Terrain>();
			if (terrain != null) {
				int textureIndex = terrain.GetMainTextureIndex(transform.position);
				SoundManager soundManager = SoundManager.Instance;
				if (textureIndex < soundManager.textureFootsteps.Count) {
					clip = soundManager.textureFootsteps[textureIndex];
				}
			}
		}

		footstepSource.clip = clip;
		footstepSource.volume = 0.7f;
		footstepSource.pitch = Random.Range(0.9f, 1.2f);
		footstepSource.Play();
	}

	void FootR() {
		PlayFootstep();
	}

	void FootL() {
		PlayFootstep();
	}
}

// Extension class to extend Terrain
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

static public class MethodExtensionForTerrain {
	static public float[] GetTextureMix(this Terrain terrain, Vector3 worldPosition) {
		Vector3 terrainPosition = terrain.transform.position;
		Vector3 terrainSize = terrain.terrainData.size;
		float mapX = ((worldPosition.x - terrainPosition.x) / terrainSize.x) * terrain.terrainData.alphamapWidth;
		float mapZ = ((worldPosition.z - terrainPosition.z) / terrainSize.z) * terrain.terrainData.alphamapHeight;

		float[,,] splatmapData = terrain.terrainData.GetAlphamaps((int) mapX, (int) mapZ, 1, 1);
		float[] cellMix = new float[splatmapData.GetUpperBound(2) + 1];
		for (int i = 0; i < cellMix.Length; i++) {
			cellMix[i] = splatmapData[0, 0, i];
		}
		return cellMix;
	}

	static public int GetMainTextureIndex(this Terrain terrain, Vector3 worldPosition) {
		float[] mix = terrain.GetTextureMix(worldPosition);

		float maxMix = 0.0f;
		int maxIndex = 0;
		for (int i = 0; i < mix.Length; i++) {
			if (mix[i] > maxMix) {
				maxIndex = i;
				maxMix = mix[i];
			}
		}

		return maxIndex;
	}
}

// This is the singleton that contains the actual sounds... you can add the list to the other class if you wish
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SoundManager : Singleton<SoundManager> {
	public AudioClip defaultFootstep;
	public List<AudioClip> textureFootsteps;
}

Previous snippet | Next snippet