Hello! Again, thanks so much for your time.
After a time trying to do my own “steps sounds” scripts, I am very close to finish it. Here it is (sorry if I forget translate some spanish words, if it is an issue for understand my problem I’ll change itimmediately).
First my Script for check texture:
public class CheckingTexture : MonoBehaviour {
private static string GetTerrainTexture(Vector3 posToCheck, bool nameOrID, Terrain terrainToCheck)
{
string texture;
//Saving the Terrain data where we are.
TerrainData mTerrainData = terrainToCheck.terrainData;
//Debug.Log ("The Terrain name is... " + Terrain.activeTerrain);
//Now we get the width and Height of the terrain.
//Look like if "control texture resoluion" in Terrain settings is changed, the values here change with it.
int alphamapWidth = mTerrainData.alphamapWidth;
int alphamapHeight = mTerrainData.alphamapHeight;
//Debug.Log ("The Value of alphamapWidth is " + alphamapWidth + " and the value of alphamapHeight is " + alphamapHeight);
//Now we create an array with all possibles textures.
float[,,] mSplatmapData = mTerrainData.GetAlphamaps(0, 0, alphamapWidth, alphamapHeight);
//And we save the lenght of the arrain in a int for the for later
int mNumTextures = mSplatmapData.Length / (alphamapWidth * alphamapHeight);
//Debug.Log ("The terrain have ... " + mNumTextures + " textures");
//Creating a new vector
Vector3 terrainCoords = new Vector3();
terrainCoords.x = ((posToCheck.x - terrainToCheck.transform.position.x) / terrainToCheck.terrainData.size.x) * terrainToCheck.terrainData.alphamapWidth;
terrainCoords.z = ((posToCheck.z - terrainToCheck.transform.position.z) / terrainToCheck.terrainData.size.z) * terrainToCheck.terrainData.alphamapHeight;
//So lets check, finally, the index and the name for the texture
for (int i = 0; i < mNumTextures; i++)
{
if (0 < mSplatmapData [(int)terrainCoords.z, (int)terrainCoords.x, i]) {
if (nameOrID == true)
texture = i.ToString();
else
texture = mTerrainData.splatPrototypes [i].texture.ToString ();
}
}
return texture;
}
//True
public static string GetTerrainID(Vector3 posToCheck, Terrain terrainToCheck)
{
return GetTerrainTexture (posToCheck, true, terrainToCheck);
}
//False
public static string GetTerrainName(Vector3 posToCheck, Terrain terrainToCheck)
{
return GetTerrainTexture (posToCheck, false, terrainToCheck);
}
/*void Update () {
Debug.Log("The ID and name of my texture is... " + GetTerrainID(transform.position, terrainToCheck) + "<<>>" + GetTerrainName(transform.position, terrainToCheck));
}*/
}
Now the Script where I check what Sound I should use:
public class ImprovedStepSounds : MonoBehaviour {
[Header("Terrain that I Want check")]
public Terrain terrainToCheck;
[Space(10)]
[Header("Sin Sonido")]
public List<AudioClip> noSoundList;
public AudioClip noSoundJump;
public AudioClip noSoundLand;
[Space(10)]
[Header("Texture Default (when not found a texture)")]
public List<AudioClip> idDStepsList;
public AudioClip idDJumps;
public AudioClip idDLand;
[Space(10)]
[Header("Texture ID 0 / Cliff")]
public List<AudioClip> id0StepsList;
public AudioClip id0Jumps;
public AudioClip id0Land;
[Space(10)]
[Header("Texture ID 1 / Arena ")]
public List<AudioClip> id1StepsList;
public AudioClip id1Jumps;
public AudioClip id1Land;
[Space(10)]
[Header("Texture ID 2 / Césped ")]
public List<AudioClip> id2StepsList;
public AudioClip id2Jumps;
public AudioClip id2Land;
[Space(10)]
[Header("Texture ID 3 / Grava")]
public List<AudioClip> id3StepsList;
public AudioClip id3Jumps;
public AudioClip id3Land;
[Space(10)]
[Header("Texture ID 4 / Tierra")]
public List<AudioClip> id4StepsList;
public AudioClip id4Jumps;
public AudioClip id4Land;
[Space(10)]
[Header("Water")]
public List<AudioClip> waterList;
public AudioClip waterJump;
public AudioClip waterLand;
[Space(10)]
[Header("Wood")]
public List<AudioClip> woodFenceList;
public AudioClip woodFenceJump;
public AudioClip woodFenceLand;
private bool manualSound = false;
private float distToGround = 5f;
private float distToTop = 50f;
private RaycastHit hitObject = new RaycastHit();
private RaycastHit hitObjectTop = new RaycastHit();
private RaycastHit hitObjectSphere = new RaycastHit();
private int lastStepsSelected = -1;
private int newStepsSelected = -1;
void Start()
{
NewStepsSounds(idDStepsList, idDJumps, idDLand);
}
//The ID of textures go between -1 (default sounds) to 999 (for example)
//The ID for manual sounds will start in 1000
//99999 is for when I don't want sounds at all
void Update() {
CheckingRaycastOrTexture ();
//I tryed the sphere too.
/*if (Physics.SphereCast (transform.position, 25f, transform.position, out hitObjectSphere, 5f)) {
if (hitObjectSphere.transform.tag == "MANUAL_STEPS") {
SettingSoundsByName (hitObjectSphere);
} else {
CheckingRayCastOnTop ();
}
} else {
CheckingRayCastOnTop ();
}*/
}
//==========================
void CheckingRaycastOrTexture()
{
if (Physics.Raycast (transform.position, Vector3.down, out hitObject, distToGround)) {
Debug.Log(hitObject.transform.name);
if (hitObject.transform.tag == "MANUAL_STEPS") {
SettingSoundsByName(hitObject);
} else {
//Calling to check the Texture
newStepsSelected = int.Parse (CheckingTexture.GetTerrainID (transform.position, terrainToCheck));
SettingSoundsByTexture();
}
}
}
/*
//Not using ATM
void CheckingRayCastOnTop()
{
//Check to Up
if (Physics.Raycast (transform.position, Vector3.up, out hitObjectTop, distToTop)) {
if (hitObjectTop.transform.tag == "MANUAL_STEPS") {
SettingSoundsByName (hitObjectTop);
}
} else {
CheckingRaycastOrTexture ();
}
}
*/
void SettingSoundsByTexture(){
//Default, just in case
if (newStepsSelected == -1 || newStepsSelected>= 5 && newStepsSelected<=999) {
NewStepsSounds(idDStepsList, idDJumps, idDLand);
}
//ID 0 stone
if (newStepsSelected == 0) {
NewStepsSounds (id0StepsList, id0Jumps, id0Land);
}
//ID 1 sand
if (newStepsSelected == 1) {
NewStepsSounds (id1StepsList, id1Jumps, id1Land);
}
//ID 2 grass
if (newStepsSelected == 2) {
NewStepsSounds (id2StepsList, id2Jumps, id2Land);
}
//ID 3 gravel
if (newStepsSelected == 3) {
NewStepsSounds (id3StepsList, id3Jumps, id3Land);
}
//ID 4 Earth
if (newStepsSelected == 4) {
NewStepsSounds (id4StepsList, id4Jumps, id4Land);
}
}
void SettingSoundsByName(RaycastHit hit)
{
if (hit.transform.name == "House_No_Sound") {
NewStepsSounds (noSoundList, noSoundJump, noSoundLand);
newStepsSelected = 99999;
}
if (hit.transform.name == "water") {
NewStepsSounds (waterList, waterJump, waterLand);
newStepsSelected = 1000;
}
if ( hit.transform.name == "Wood Fence"
|| hit.transform.name == "Medieval_House"
|| hit.transform.name == "Wood Fence Top"
|| hit.transform.name == "House_Wood"
)
{
NewStepsSounds (woodFenceList, woodFenceJump, woodFenceLand);
newStepsSelected = 1001;
}
if (hit.transform.name == "Stairs_color_StairCollider") {
NewStepsSounds (id0StepsList, id0Jumps, id0Land);
newStepsSelected = 1002;
}
}
void NewStepsSounds(List<AudioClip> newSounds, AudioClip newJumpSound, AudioClip newLandSound)
{
//This is a very simple method that I did in the FirstPersonController
GetComponent<FirstPersonController> ().ChangeStepsSounds (newSounds, newJumpSound, newLandSound);
}
}
Btw, the “newStepsSelect” is a variable that is “work in progress” that I will use later to check if is the same id than before, so in that case the call to change the steps isn’t needed. But still not implemented. And “Manual_Steps” can be removed completly with some tweaks, so I’ll do it too.
Well, with terrain and decorations game objects the code works pretty well. The problem starts when I want use a water steps. If my water have a Collision, it works perfectly, but I want the player can go at half height or totally underwater. It will depend of terrain height.
In this case the RayCast to Down improved it a bit, but still in some places isn’t taking the water correctly and it go to use texture sounds.
Then I tryed the Sphere, and it worked pretty well! Too pretty well… It was taking the elements around, even if I was too far away (I tryed differents radius values, but it needed to be that big to work fine).
Of course before all of this I tryed a box collider with a trigger and it worked but it wasn’t very accurate to the water area. In essence all geometric gameobjects aren’t enought for an non geometric area. Oh, well, they could if I spend alot hours placing alot of them in order to fill all the area and to do a perfect borders.
I thought too check the player Y coordenate, but maybe in some points could be not correct because player could go to that Y coordenate but in an area without water.
Well, that’s is. I really ill appreciate any help and suggestion. Thanks so much for your time and help and sorry my bad English.