- Home /
Get height of a Mesh by X and Z coordinates
Hi,
well I create a mesh dynamically and I set its height by code:
private Tile GenerateTile(int x, int z) {
var Pink = seedBeta;
var n = new CoherentNoise.Generation.Fractal.PinkNoise(Pink); //213321
GameObject plane =
(GameObject)Instantiate(terrainPlane, new Vector3(x * planeSize, 0, z * planeSize), Quaternion.identity);
plane.transform.localScale = new Vector3(planeSize * 0.1f, 1, planeSize * 0.1f);
plane.transform.parent = transform;
plane.name = "Chunk_"+x+","+z;
// Get the planes vertices
Mesh mesh = plane.GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
// alter vertex Y position depending on simplex noise)
for (int v = 0; v < vertices.Length; v++) {
// generate the height for current vertex
Vector3 vertexPosition = plane.transform.position + vertices[v] * planeSize / 10f;
float height = n.GetValue(vertexPosition.x * detailScale, vertexPosition.z * detailScale, 0);
// scale it with the heightScale field
vertices[v].y = height * heightScale + baseLine;
}
mesh.vertices = vertices;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
plane.AddComponent<MeshCollider>();
Tile tile = new Tile();
tile.gameObject = plane;
tile.tileX = x;
tile.tileZ = z;
return tile;
}
And well I have some problems with the generation, because sometimes when the terrain is generated the player falls through the terrain because it's very high...
I want to do a function that calculates the Y value only putting the X and Z coordinates... To set the player at the same height as the terrain..
I want to make an equivalent of TerrainData.GetHeights... But I don't know where I can start... I found before RayCast and I have been doing some tests... But It wasn't so useful...
So what can I do?
Thanks in advance. Bye.
planeCollider.RayCast() straight down + some safety distance should work just fine no? Is there a reason you dont want to use raycast?
No, because I don't how to use it... And it's not useful, because you can only use -Vector.up... How do you get the height of the plane? If get first the height of the plane, why I will use a Raycast?? It's only set "some safety distance" when I get the height of the plane..
Answer by robertbu · Jan 02, 2014 at 09:07 AM
You can use Collider.Raycast(). This will Raycast() only against the specific collider rather than everything in the scene like a Physics.Raycast() would do. Say you have a height that is above any possible height in your plane and an X and Z defining a coordinate, you can do:
RaycastHit hit;
Ray ray = new Ray(new Vector3(x,maxHeight,y), Vector3.down);
if (plane.collider.Raycast(ray, out hit, 2.0f * maxHeight)) {
Debug.Log("Hit point: "+hit.point);
}
Well my plane has not Collider, how can I do that? It's added at runtime, but Unity cannot access it... :/
You do have a collider. You add it on line 29:
plane.AddComponent<$$anonymous$$eshCollider>();
Note that a mesh is one sided. Any chance you wound your triangles backwards? What kind of object is a 'terrainPlane'?
Well I had tested 3 things, and everytime it says Hit point: (0.0, 0.0, 0.0)... Except when I touch the ground...
I tested, Physics.RayCast, and I try to add the terrain plane instantiated gameobject at runtime and I use Find and GetComponent to find the Chunk I'm at... And all works only when I touch the ground... :/
The code that I used:
float PlaneSize = GameObject.Find ("GameScripts").GetComponent<TerrainGenerator>().planeSize;
float maxHeight = 25;
float x = PlayerObject.transform.position.x;
float z = PlayerObject.transform.position.z;
$$anonymous$$eshCollider mc = GameObject.Find("Chunk_"+((int)(x/PlaneSize)).ToString()+","+((int)(z/PlaneSize)).ToString()).GetComponent<$$anonymous$$eshCollider>();
RaycastHit hit;
Ray ray = new Ray(new Vector3(x,maxHeight,z), Vector3.down);
if (mc.collider.Raycast(ray, out hit, 2.0f * maxHeight)) {
Debug.Log("Hit point: "+hit.point);
}
I updated the upper code with the new things... How can I do that without touching the ground?? Or it's not possible...
I solve it with:
private bool PlayerLoaded = false;
private GameObject player;
private bool playerposChanged = false;
public void SetPlayerOnGround(GameObject PlayerObject)
{
float PlaneSize = GameObject.Find ("GameScripts").GetComponent<TerrainGenerator>().planeSize;
float maxHeight = GameObject.Find ("GameScripts").GetComponent<TerrainGenerator>().heightScale;
float x = PlayerObject.transform.position.x;
float z = PlayerObject.transform.position.z;
if (!PlayerLoaded) {
player = (GameObject)GameObject.Instantiate (Resources.Load ("prefabs/Player"), new Vector3(x, maxHeight + 5, z), Quaternion.identity);
PlayerLoaded = true;
}
if(!playerposChanged) {
player.transform.position = new Vector3 (PlayerObject.transform.position.x, player.transform.position.y, PlayerObject.transform.position.z);
float distance = Vector3.Distance (PlayerObject.transform.position, player.transform.position);
PlayerObject.transform.position = new Vector3(PlayerObject.transform.position.x, player.transform.position.z+5, PlayerObject.transform.position.z);
GameObject.Destroy(player);
playerposChanged = true;
}
}
Simply, I create another player with more Gravity hover the maxDistance, and when It touches the ground, the player position is setted...
But thanks anyway by the code... :P