- Home /
Combine terrain and water plane colliders
Hi all. I'm trying to implement some kind of strategic game map layout and need to detect the tile which user clicked with mouse button. The simpliest way I could find is using Collider.Raycast method with ray created from mouse position on the screen to terrain collider. The problem that I have water plane partially hiding my terrain and to be precise in tile detection on water areas I should perform raycasting on it's collider instead of terrain collider. Of course I can do raycasting twice and use RaycastHit which is closer to the camera but this looks like workaround and not a solution. I was tried to combine both colliders with Mesh.CombineMeshes and creating new MeshCollider. To get terrain mesh I'm using this script (changed it to generate mesh at runtime) but it unable to generate mesh for my 1025 X 1025 heighmap terrain as it exceeds unity polygons limit. So it seems not a solition also. Physics.Raycast is also not an option because I want to ignore map objects like trees or buildings.
Is anyone know better way to combine colliders or raycasting twice is only way to do what I want?
Thanks in advance.
I'm not sure if it is the answer you are looking for, but it seems that you could find the position of the raycast collision with water and mathematically map that to the tile location in which that water area resides?
Unfortunately I can't think of how this can be made mathematically. Below is image where I tried to explain the problem.
Answer by Efril · Dec 22, 2013 at 09:21 PM
I finally find the appropriate solution for this problem. To merge terrain collider and water plane collider we should create new TerrainData which is the copy of original TerrainData of our terrain. The heighmap of this new terrain data should be updated so all underwater points moved up to be on the same level as water plane. Then this updated TerrainData is used with terrain collider instead of original TerrainData. Below is the script to create such TerrainData:
[ExecuteInEditMode]
[RequireComponent(typeof(Terrain))]
public class CompositeTerrainColliderDataCreator : MonoBehaviour
{
private Terrain _terrain;
public MeshFilter WaterPlaneMesh;
public void GenerateColliderTerrainData()
{
TerrainData terrainData = (TerrainData)TerrainData.Instantiate(_terrain.terrainData);
float waterPlaneYPosition = WaterPlaneMesh.transform.position.y;
//Calculate water plane Y position related to terrain heightmap
waterPlaneYPosition = WaterPlaneMesh.transform.position.y / terrainData.size.y;
float[,] heightmap = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight);
for (int x = 0; x < terrainData.heightmapWidth; x++)
{
for (int y = 0; y < terrainData.heightmapHeight; y++)
{
if (heightmap[x, y] < waterPlaneYPosition) heightmap[x, y] = waterPlaneYPosition;
}
}
terrainData.SetHeights(0, 0, heightmap);
//Save updated terrain data to assets
string terrainDataAssetPath="Assets/UpdatedTerrainData.asset";
AssetDatabase.CreateAsset(terrainData, terrainDataAssetPath);
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
}
// Use this for initialization
void Start()
{
_terrain = GetComponent<UnityEngine.Terrain>();
}
}
Answer by Spinnernicholas · Dec 21, 2013 at 07:25 AM
If you are using tiles, make tile colliders and put them on their own layer. Then raycast on just that layer.
Then the boundary of the terrain meshes,trees, buildings, etc.... don't matter.
I probably was not correcly used 'Tile' word. I mean cells of grid which represents logical model of my map. The word 'Node' is more appropriate here I think.
Your answer
Follow this Question
Related Questions
Generated Terrain not colliding! HALP. 0 Answers
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Terrain with lots of objects 1 Answer
Any way to solve capsule collider + rigidbody movement on Terrains? It's very 'stuttery' 2 Answers
Player falling through Terrain collider 0 Answers