Как перевернуть сетку - PullRequest
0 голосов
/ 12 октября 2018

Я использую скрипт из этого урока https://www.youtube.com/watch?v=73Dc5JTCmKI, который показывает поле зрения.Но я хочу обратить внимание на то, что место, где вы не можете видеть белую сетку, будет белой сеткой вместо того, что у меня сейчас,

Как инвертировать сетку так, чтобы там, где был зеленый цвет (ничего), не было быбыть сеткой и там, где есть сетка, там не будет сетки.

enter image description here

Мой сценарий:

using UnityEngine;

с использованием System.Коллекции;using System.Collections.Generic;

открытый класс FieldOfView: MonoBehaviour {

public float viewRadius;
[Range(0,360)]
public float viewAngle;

public LayerMask targetMask;
public LayerMask obstacleMask;

[HideInInspector]
public List<Transform> visibleTargets = new List<Transform>();

public float meshResolution;
public int edgeResolveIterations;
public float edgeDstThreshold;

public float maskCutawayDst = .1f;

public MeshFilter viewMeshFilter;
Mesh viewMesh;

void Start() {
    viewMesh = new Mesh ();
    viewMesh.name = "View Mesh";
    viewMeshFilter.mesh = viewMesh;

    StartCoroutine ("FindTargetsWithDelay", .2f);
}


IEnumerator FindTargetsWithDelay(float delay) {
    while (true) {
        yield return new WaitForSeconds (delay);
        FindVisibleTargets ();
    }
}

void LateUpdate() {
    DrawFieldOfView ();
}

void FindVisibleTargets() {
    visibleTargets.Clear ();
    Collider[] targetsInViewRadius = Physics.OverlapSphere (transform.position, viewRadius, targetMask);

    for (int i = 0; i < targetsInViewRadius.Length; i++) {
        Transform target = targetsInViewRadius [i].transform;
        Vector3 dirToTarget = (target.position - transform.position).normalized;
        if (Vector3.Angle (transform.forward, dirToTarget) < viewAngle / 2) {
            float dstToTarget = Vector3.Distance (transform.position, target.position);
            if (!Physics.Raycast (transform.position, dirToTarget, dstToTarget, obstacleMask)) {
                visibleTargets.Add (target);
            }
        }
    }
}

void DrawFieldOfView() {
    int stepCount = Mathf.RoundToInt(viewAngle * meshResolution);
    float stepAngleSize = viewAngle / stepCount;
    List<Vector3> viewPoints = new List<Vector3> ();
    ViewCastInfo oldViewCast = new ViewCastInfo ();
    for (int i = 0; i <= stepCount; i++) {
        float angle = transform.eulerAngles.y - viewAngle / 2 + stepAngleSize * i;
        ViewCastInfo newViewCast = ViewCast (angle);

        if (i > 0) {
            bool edgeDstThresholdExceeded = Mathf.Abs (oldViewCast.dst - newViewCast.dst) > edgeDstThreshold;
            if (oldViewCast.hit != newViewCast.hit || (oldViewCast.hit && newViewCast.hit && edgeDstThresholdExceeded)) {
                EdgeInfo edge = FindEdge (oldViewCast, newViewCast);
                if (edge.pointA != Vector3.zero) {
                    viewPoints.Add (edge.pointA);
                }
                if (edge.pointB != Vector3.zero) {
                    viewPoints.Add (edge.pointB);
                }
            }

        }


        viewPoints.Add (newViewCast.point);
        oldViewCast = newViewCast;
    }

    int vertexCount = viewPoints.Count + 1;
    Vector3[] vertices = new Vector3[vertexCount];
    int[] triangles = new int[(vertexCount-2) * 3];

    vertices [0] = Vector3.zero;
    for (int i = 0; i < vertexCount - 1; i++) {
        vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;

        if (i < vertexCount - 2) {
            triangles [i * 3] = 0;
            triangles [i * 3 + 1] = i + 1;
            triangles [i * 3 + 2] = i + 2;
        }
    }

    viewMesh.Clear ();

    viewMesh.vertices = vertices;
    viewMesh.triangles = triangles;
    viewMesh.RecalculateNormals ();
}


EdgeInfo FindEdge(ViewCastInfo minViewCast, ViewCastInfo maxViewCast) {
    float minAngle = minViewCast.angle;
    float maxAngle = maxViewCast.angle;
    Vector3 minPoint = Vector3.zero;
    Vector3 maxPoint = Vector3.zero;

    for (int i = 0; i < edgeResolveIterations; i++) {
        float angle = (minAngle + maxAngle) / 2;
        ViewCastInfo newViewCast = ViewCast (angle);

        bool edgeDstThresholdExceeded = Mathf.Abs (minViewCast.dst - newViewCast.dst) > edgeDstThreshold;
        if (newViewCast.hit == minViewCast.hit && !edgeDstThresholdExceeded) {
            minAngle = angle;
            minPoint = newViewCast.point;
        } else {
            maxAngle = angle;
            maxPoint = newViewCast.point;
        }
    }

    return new EdgeInfo (minPoint, maxPoint);
}


ViewCastInfo ViewCast(float globalAngle) {
    Vector3 dir = DirFromAngle (globalAngle, true);
    RaycastHit hit;

    if (Physics.Raycast (transform.position, dir, out hit, viewRadius, obstacleMask)) {
        return new ViewCastInfo (true, hit.point, hit.distance, globalAngle);
    } else {
        return new ViewCastInfo (false, transform.position + dir * viewRadius, viewRadius, globalAngle);
    }
}

public Vector3 DirFromAngle(float angleInDegrees, bool angleIsGlobal) {
    if (!angleIsGlobal) {
        angleInDegrees += transform.eulerAngles.y;
    }
    return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad),0,Mathf.Cos(angleInDegrees * Mathf.Deg2Rad));
}

public struct ViewCastInfo {
    public bool hit;
    public Vector3 point;
    public float dst;
    public float angle;

    public ViewCastInfo(bool _hit, Vector3 _point, float _dst, float _angle) {
        hit = _hit;
        point = _point;
        dst = _dst;
        angle = _angle;
    }
}

public struct EdgeInfo {
    public Vector3 pointA;
    public Vector3 pointB;

    public EdgeInfo(Vector3 _pointA, Vector3 _pointB) {
        pointA = _pointA;
        pointB = _pointB;
    }
}

}

Я знаю, что мне нужно что-то изменить с помощью треугольников, но я незнаю, как их настроить.

    vertices [0] = Vector3.zero;
for (int i = 0; i < vertexCount - 1; i++) {
    vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;

    if (i < vertexCount - 2) {
        triangles [i * 3] = 0;
        triangles [i * 3 + 1] = i + 1;
        triangles [i * 3 + 2] = i + 2;
    }
}

viewMesh.Clear ();

viewMesh.vertices = vertices;
viewMesh.triangles = triangles;
viewMesh.RecalculateNormals ();

Извините, но я не знаю, как объяснить это более понятно.

РЕДАКТИРОВАТЬ Так что у меня все еще есть некоторые проблемыс этим.Ваше решение не работает для меня.Прежде всего, здесь нет «circleRadius», поэтому я использую viewRadius вместо этого.Во-вторых, это постоянно дает мне аргумент вне диапазона.Мой код немного изменился, и вот как он выглядит:

        int vertexCount = viewPoints.Count + 1;
    var vertices = new Vector3[vertexCount];
    var triangles = new int[(vertexCount - 2) * 3];

    vertices[0] = Vector3.zero;
    for (int i = 0; i < vertexCount - 1; i++)
    {
        vertices[i + 1] = transform.InverseTransformPoint(viewPoints[i]);

        if (i < vertexCount - 2)
        {
            triangles[i * 3] = 0;
            triangles[i * 3 + 1] = i + 1;
            triangles[i * 3 + 2] = i + 2;
        }
    }

Так что в этом случае я должен изменить его на?:

        int vertexCount = viewPoints.Count + 1;
    Vector3[] vertices = new Vector3[(vertexCount) * 2];
    int[] triangles = new int[(vertexCount) * 6];

    for (int i = 0; i < (vertexCount - 1) * 2; i += 2)
    {
        vertices[i] = transform.InverseTransformPoint(viewPoints[i]);
        vertices[i + 1] = Vector3.Normalize(viewPoints[i]) * viewRadius;
    }
    for (int i = 0; i < (vertexCount - 3) * 2; i += 1)
    {
        triangles[i * 6 + 0] = i * 4;
        triangles[i * 6 + 1] = i * 4 + 1;
        triangles[i * 6 + 2] = i * 4 + 2;
        triangles[i * 6 + 3] = i * 4 + 1;
        triangles[i * 6 + 4] = i * 4 + 2;
        triangles[i * 6 + 5] = i * 4 + 3;
    }

РЕДАКТИРОВАТЬ 2

Итак, я изменил свой код, и все в порядке, но когда я тестирую его в режиме воспроизведения, он выдает ошибку:

ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
FieldOfViews.DrawFieldOfView () (at Assets/_Game/FieldOfView.cs:111)

и он в сети:

vertices[i] = transform.InverseTransformPoint(viewPoints[i]) + Vector3.forward * maskCutawayDst;

Когда я удалил эту полосу в целях тестирования, она также выдает ту же ошибку:

vertices[i + 1] = Vector3.Normalize(viewPoints[i]) * circleRadius;

Я не знаю, еслиэто может вызвать проблемы, но мой maskCutawayDst равен 0.1, а circleRadius равен 15.

1 Ответ

0 голосов
/ 12 октября 2018

С кодом:

  int vertexCount = viewPoints.Count + 1;
    Vector3[] vertices = new Vector3[vertexCount];
    int[] triangles = new int[(vertexCount-2) * 3];

    vertices [0] = Vector3.zero;
    for (int i = 0; i < vertexCount - 1; i++) {
        vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;

        if (i < vertexCount - 2) {
            triangles [i * 3] = 0;
            triangles [i * 3 + 1] = i + 1;
            triangles [i * 3 + 2] = i + 2;
        }
    }

Изменить на

        int vertexCount = viewPoints.Count + 1;
        Vector3[] vertices = new Vector3[(vertexCount) * 2];
        int[] triangles = new int[(vertexCount) * 6];

        for (int i = 0; i < vertexCount; i++)
        {
            Vector3 vertex = transform.InverseTransformPoint(viewPoints[(i == viewPoints.Count) ? 0 : i]);
            vertices[i * 2] = vertex;
            vertices[i * 2 + 1] = vertex.normalized * viewRadius;
        }
        for (int i = 0; i < (vertexCount); i++)
        {
            int j = (vertexCount - 1 == i) ? 0 : i;
            triangles[i * 6 + 0] = j * 2 + 0;
            triangles[i * 6 + 1] = j * 2 + 1;
            triangles[i * 6 + 2] = j * 2 + 2;
            triangles[i * 6 + 3] = j * 2 + 1;
            triangles[i * 6 + 4] = j * 2 + 3;
            triangles[i * 6 + 5] = j * 2 + 2;
        }

Объяснение:

Рисунок 1: Часть того, что происходит

A slice of what is happening

Первая программа создала треугольник в красной области.Это было между серединой и двумя пересекающимися лучами (пересекаются с красной линией).Чтобы «инвертировать» это, мы должны соединить две линии в виде квадрата с внешней точкой на фиксированном расстоянии.Вектор нормализуется, чтобы иметь единичную длину, а затем умножается, чтобы иметь фиксированное расстояние со всеми точками.Это делается с помощью кода

   for (int i = 0; i < vertexCount; i++)
        {
            Vector3 vertex = transform.InverseTransformPoint(viewPoints[(i == viewPoints.Count) ? 0 : i]);
            vertices[i * 2] = vertex;
            vertices[i * 2 + 1] = vertex.normalized * viewRadius;
        }

, после чего эти вершины превращаются в два треугольника (для представления четырехугольника).со следующим кодом.Которые создают зеленую зону.

for (int i = 0; i < (vertexCount); i++)
{
    int j = (vertexCount - 1 == i) ? 0 : i;
    triangles[i * 6 + 0] = j * 2 + 0;
    triangles[i * 6 + 1] = j * 2 + 1;
    triangles[i * 6 + 2] = j * 2 + 2;
    triangles[i * 6 + 3] = j * 2 + 1;
    triangles[i * 6 + 4] = j * 2 + 3;
    triangles[i * 6 + 5] = j * 2 + 2;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...