You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何检测射线投射指定网格区域是否存在凸起?

Can This Be Done in Unity?

Absolutely! This is totally achievable in Unity—let’s break down two solid approaches to implement this feature, depending on your needs for precision and performance:

Approach 1: Direct Mesh Vertex Analysis (Precise)

This method works directly with the target mesh’s vertex data to check for bumps in your defined square region.

Step 1: Grab Raycast Hit Data

First, you’ll need to get the mesh associated with your raycast hit, plus convert the world-space hit point to the mesh’s local space for easier calculations:

RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
{
    MeshFilter meshFilter = hit.collider.GetComponent<MeshFilter>();
    if (meshFilter == null) return; // Skip if there's no mesh attached
    
    Mesh targetMesh = meshFilter.mesh;
    Vector3 hitPointLocal = hit.collider.transform.InverseTransformPoint(hit.point);
    Vector3 hitNormalLocal = hit.collider.transform.InverseTransformDirection(hit.normal);
}

Step 2: Define Your Square Region

Set the size of your square, then calculate two orthogonal axes (U and V) perpendicular to the hit normal—these will be the "sides" of your square:

float halfSquareSize = 1f; // *Adjust this to control how big your scan area is*
// Generate U axis (perpendicular to normal)
Vector3 uAxis = Vector3.Cross(hitNormalLocal, Vector3.up);
if (uAxis.magnitude < 0.01f) uAxis = Vector3.Cross(hitNormalLocal, Vector3.right);
uAxis.Normalize();
// Generate V axis (perpendicular to both normal and U)
Vector3 vAxis = Vector3.Cross(hitNormalLocal, uAxis).Normalize();

Step 3: Check Vertices for Bumps

Loop through the mesh’s vertices, filter those inside the square, and compare their height relative to the hit point to detect bumps:

float heightThreshold = 0.1f; // *Adjust this to set how "high" a bump needs to be to count*
bool hasBump = false;
List<Vector3> localVertices = new List<Vector3>();
targetMesh.GetVertices(localVertices);

float hitHeight = Vector3.Dot(hitPointLocal, hitNormalLocal);

foreach (Vector3 vert in localVertices)
{
    Vector3 offset = vert - hitPointLocal;
    // Check if vertex is inside the square region
    float uDistance = Vector3.Dot(offset, uAxis);
    float vDistance = Vector3.Dot(offset, vAxis);
    
    if (Mathf.Abs(uDistance) <= halfSquareSize && Mathf.Abs(vDistance) <= halfSquareSize)
    {
        float vertHeight = Vector3.Dot(vert, hitNormalLocal);
        // If vertex is higher than the hit point by more than our threshold
        if (vertHeight - hitHeight > heightThreshold)
        {
            hasBump = true;
            break; // No need to check further once we find a bump
        }
    }
}

Debug.Log(hasBump ? "Found a bump in the region!" : "No bumps detected.");

Performance Tip: If your mesh has thousands of vertices, optimize this by only checking vertices in the triangle that was hit (use hit.triangleIndex to get the relevant triangle’s vertex indices).

Approach 2: Ray Grid Scan (Simpler, No Mesh Access Needed)

If you don’t need precise vertex-level data, this method uses a grid of rays over your square region to check for height differences. It works with any collider, even if you don’t have direct access to the mesh.

int rayGridSize = 5; // *5x5 grid of rays—increase for more precision*
float halfSquareSize = 1f;
float rayStep = (halfSquareSize * 2) / (rayGridSize - 1);
bool hasBump = false;
float heightThreshold = 0.1f;

// Generate U/V axes same as Approach 1
Vector3 uAxis = Vector3.Cross(hit.normal, Vector3.up);
if (uAxis.magnitude < 0.01f) uAxis = Vector3.Cross(hit.normal, Vector3.right);
uAxis.Normalize();
Vector3 vAxis = Vector3.Cross(hit.normal, uAxis).Normalize();

for (int i = 0; i < rayGridSize; i++)
{
    for (int j = 0; j < rayGridSize; j++)
    {
        // Calculate the origin of the current ray in world space
        Vector3 localOffset = uAxis * (-halfSquareSize + i * rayStep) + vAxis * (-halfSquareSize + j * rayStep);
        Vector3 rayOrigin = hit.collider.transform.TransformPoint(hitPointLocal + localOffset);
        Ray scanRay = new Ray(rayOrigin, hit.normal);
        
        if (Physics.Raycast(scanRay, out RaycastHit subHit, 2f))
        {
            float heightDiff = Vector3.Dot(subHit.point - hit.point, hit.normal);
            if (heightDiff > heightThreshold)
            {
                hasBump = true;
                goto EndScan; // Exit both loops early
            }
        }
    }
}
EndScan:

Debug.Log(hasBump ? "Bump detected in the scan area!" : "No bumps found.");

Both methods work great—pick the one that fits your project’s precision and performance needs!

内容的提问来源于stack exchange,提问作者Vivek Rajagopal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 10:12:40