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.

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 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>();
    }
}