Physics.Raycast无法识别网格对撞机

时间:2017-08-30 03:08:26

标签: unity3d collision-detection mesh

我在让Physics.Raycast识别网格对撞机时遇到问题。我有一个自定义创建的网格模拟地形,以及一个可以用键盘和鼠标控制的相机对象。我试图在相机和地形之间实现碰撞,这样相机就无法在地形中移动。

这是生成网格的脚本。它附加到具有MeshCollider和MeshFilter组件的GameObject。请特别注意这些组件在脚本中设置meshsharedMesh属性的位置。

var divisions : int;
var size : float;
var height : float;

private var vertices : Vector3[];
private var numVertices : int;

private var cameraStartVertex : Vector3;

function Start () {
    InitTerrain();
}

function InitTerrain() {
    numVertices = (divisions + 1) * (divisions + 1);
    vertices = new Vector3[numVertices];

    var UVs : Vector2[] = new Vector2[numVertices];
    var triangles : int[] = new int[divisions * divisions * 6];

    var halfTerrainSize : float = size / 2;
    var divisionSize : float = size / divisions;

    //LOOK HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    var mesh : Mesh = new Mesh();
    GetComponent.<MeshFilter>().mesh = mesh;
    GetComponent.<MeshCollider>().sharedMesh = mesh;
    GetComponent.<MeshCollider>().isTrigger = true;

    var triangleOffset : int = 0;

    for (var i = 0; i <= divisions; i++) {
        for (var j = 0; j <= divisions; j++) {
            vertices[i * (divisions+1) + j] = new Vector3(-halfTerrainSize + j * divisionSize, 0.0f, halfTerrainSize - i * divisionSize);
            UVs[i * (divisions+1) + j] = new Vector2(parseFloat(i / divisions), parseFloat(j / divisions));

            if (i < divisions && j < divisions) {
                var topLeft : int = i * (divisions + 1) + j;
                var bottomLeft : int = (i + 1) * (divisions + 1) + j;

                // First triangle of square
                triangles[triangleOffset] = topLeft;
                triangles[triangleOffset + 1] = topLeft + 1;
                triangles[triangleOffset + 2] = bottomLeft + 1;

                // Second triangle of square
                triangles[triangleOffset + 3] = topLeft;
                triangles[triangleOffset + 4] = bottomLeft + 1;
                triangles[triangleOffset + 5] = bottomLeft;

                triangleOffset += 6;
            }
        }
    }

    initDiamondSquareCornerVertices();

    performDiamondSquare();

    mesh.vertices = vertices;
    mesh.uv = UVs;
    mesh.triangles = triangles;

    mesh.RecalculateBounds();
    mesh.RecalculateNormals();
}


function initDiamondSquareCornerVertices(){
    vertices[0].y = Random.Range(-height, height);
    vertices[divisions].y = Random.Range(-height, height);
    vertices[vertices.length - 1].y = Random.Range(-height, height);
    vertices[vertices.length - 1 - divisions].y = Random.Range(-height, height);
}

function performDiamondSquare(){
    var numIterations : int = parseInt(Mathf.Log(divisions, 2));
    var numSquares : int = 1;
    var squareSize : int = divisions;

    for (var i = 0; i < numIterations; i++){ // the iteration we're on
        var row : int = 0;

        for (var j = 0; j < numSquares; j++){
            var column : int = 0;

            for (var k = 0; k < numSquares; k++) {
                diamondSquareStep(row, column, squareSize, height);
                column += squareSize;
            }

            row += squareSize;
        }

        numSquares *= 2;
        squareSize /= 2;
        height *= 0.4f;
    }
}

function diamondSquareStep(row : int, column : int, size : int, offset : float) {

    var halfSize : int = parseInt(size * 0.5f);
    var topLeft : int = row * (divisions + 1) + column;
    var bottomLeft : int = (row + size) * (divisions + 1) + column;
    var middle : int = parseInt((row + halfSize) * (divisions + 1) + parseInt(column + halfSize));


    vertices[middle].y = (vertices[topLeft].y + vertices[topLeft + size].y + vertices[bottomLeft].y + vertices[bottomLeft+size].y) / 4 + Random.Range(-offset, offset);


    vertices[topLeft + halfSize].y = (vertices[topLeft].y + vertices[topLeft + size].y + vertices[middle].y) / 3 + Random.Range(-offset, offset);
    vertices[middle - halfSize].y = (vertices[topLeft].y + vertices[bottomLeft].y + vertices[middle].y) / 3 + Random.Range(-offset, offset);
    vertices[middle + halfSize].y = (vertices[topLeft + size].y + vertices[bottomLeft + size].y + vertices[middle].y) / 3 + Random.Range(-offset, offset);
    vertices[bottomLeft + halfSize].y = (vertices[bottomLeft].y + vertices[bottomLeft + size].y + vertices[middle].y) / 3 + Random.Range(-offset, offset);
}

这是附加到我的相机对象的脚本,它控制着相机的移动:

#pragma strict

var translationSensitivity : float = 15.0f;

private var mouseX : float;
private var mouseY : float;

function Start () {
    rotX = 0;
    rotZ = 0;
}

function Update () {

    //Translation...
     if(Input.GetKey(KeyCode.D)) {
         var trans : Vector3 = new Vector3(translationSensitivity * Time.deltaTime,0,0);
         if (!checkCollisionImminent(Vector3.right)){
             transform.Translate(trans);
         }
     }
     if(Input.GetKey(KeyCode.A)) {
         trans = new Vector3(-translationSensitivity * Time.deltaTime,0,0);
         if (!checkCollisionImminent(Vector3.left)){
             transform.Translate(trans);
         }
     }
     if(Input.GetKey(KeyCode.S)) {
         trans = new Vector3(0,0,-translationSensitivity * Time.deltaTime);
         if (!checkCollisionImminent(Vector3.back)){
             transform.Translate(trans);
         }
     }
     if(Input.GetKey(KeyCode.W)) {
         trans = new Vector3(0,0,translationSensitivity * Time.deltaTime);
         if (!checkCollisionImminent(Vector3.forward)){
             transform.Translate(trans);
         }
     }
}

function checkCollisionImminent(direction : Vector3) {
    return Physics.Raycast(transform.position, direction, 2);
}

你可以看到我设置了碰撞检查。但是相机对象继续直接穿过网格,我根本看不到问题。我做错了什么?

1 个答案:

答案 0 :(得分:0)

如果你隔离checkCollisionImminent()并使其独立于按键,那会更好。现在的方式是,在移动方向以外的方向上的任何光线投射都不会触发。我会相应地更改update()函数:

function Update () {
    var trans;
    var w, s, a, d;

    //Translation...
     if(Input.GetKey(KeyCode.D)) {
         trans = new Vector3(translationSensitivity * Time.deltaTime,0,0);
     }
     if(Input.GetKey(KeyCode.A)) {
         trans = new Vector3(-translationSensitivity * Time.deltaTime,0,0);
     }
     if(Input.GetKey(KeyCode.S)) {
         trans = new Vector3(0,0,-translationSensitivity * Time.deltaTime);
     }
     if(Input.GetKey(KeyCode.W)) {
         trans = new Vector3(0,0,translationSensitivity * Time.deltaTime);
     }

     //Check collisions
     w = checkCollisionImminent(Vector3.forward);
     s = checkCollisionImminent(Vector3.back);
     a = checkCollisionImminent(Vector3.left);
     d = checkCollisionImminent(Vector3.right);

     //Do nothing if there is a collision
     if(w || s || a || d) {
         return;
     }

     transform.Translate(trans);
}

我没有测试过这段代码,但它应该可以正常工作。如果这有帮助,请告诉我们。