原始单位的副本不具有相同的属性? Unity3d

时间:2017-09-11 17:30:23

标签: c# unity3d clone

我目前正在Unity中制作RTS风格的游戏。我有一个控制战争迷雾的脚本,当敌人超出视野范围时使敌人看不见。我面临的问题是,当我有多个单位时,只有我复制的原始内容才会在视野范围内显示敌人。所有其他副本将显示该区域正常,但不是该地区的能量。

以下是我单位的视觉脚本:

public delegate void TargetsVisibilityChange(List<Transform> newTargets);

[ExecuteInEditMode]
public class FieldOfView : MonoBehaviour
{
public float viewRadius;

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

public float viewDepth;

public LayerMask targetMask;
public LayerMask obstacleMask;

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

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


public MeshFilter viewMeshFilter;
public bool debug;
Mesh viewMesh;

public static event TargetsVisibilityChange OnTargetsVisibilityChange;

public FogProjector fogProjector;
public float updateDistance = 1;
Vector3 lastUpdatePos;

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

    fogProjector = fogProjector ?? FindObjectOfType<FogProjector>();

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


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

void LateUpdate()
{
    DrawFieldOfView();
    if (Vector3.Distance(transform.position, lastUpdatePos) > updateDistance || Time.time<.5f)
    {
        lastUpdatePos = transform.position;
        fogProjector.UpdateFog();
    }
}

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

    if (OnTargetsVisibilityChange != null) OnTargetsVisibilityChange(visibleTargets);
}

void DrawFieldOfView()
{
    float stepAngleSize = viewAngle / meshResolution;
    List<Vector3> viewPoints = new List<Vector3>();
    ObstacleInfo oldObstacle = new ObstacleInfo();
    for (int i = 0; i <= meshResolution; i++)
    {
        float angle = transform.eulerAngles.y - viewAngle / 2 + stepAngleSize * i;
        ObstacleInfo newObstacle = FindObstacles(angle);

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


        viewPoints.Add(newObstacle.point);
        oldObstacle = newObstacle;
    }

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

    viewMesh.Clear();

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


EdgeInfo FindEdge(ObstacleInfo minObstacle, ObstacleInfo maxObstacle)
{
    float minAngle = minObstacle.angle;
    float maxAngle = maxObstacle.angle;
    Vector3 minPoint = Vector3.zero;
    Vector3 maxPoint = Vector3.zero;

    for (int i = 0; i < edgeResolveIterations; i++)
    {
        float angle = (minAngle + maxAngle) / 2;
        ObstacleInfo newObstacle = FindObstacles(angle);

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

    return new EdgeInfo(minPoint, maxPoint);
}


ObstacleInfo FindObstacles(float globalAngle)
{
    Vector3 dir = DirFromAngle(globalAngle, true);
    RaycastHit hit;

    if (DebugRayCast(transform.position, dir, out hit, viewRadius, obstacleMask))
    {
        return new ObstacleInfo(true, hit.point + hit.normal * -viewDepth, hit.distance, globalAngle);
    }
    return new ObstacleInfo(false, transform.position + dir * (viewRadius - viewDepth), viewRadius, globalAngle);
}

bool DebugRayCast(Vector3 origin, Vector3 direction, out RaycastHit hit, float maxDistance, int mask)
{
    if (Physics.Raycast(origin, direction, out hit, maxDistance, mask))
    {
        if (debug)
            Debug.DrawLine(origin, hit.point);
        return true;
    }
    if (debug)
        Debug.DrawLine(origin, origin + direction * maxDistance);
    return false;
}

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

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

    public ObstacleInfo(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;
    }
}
}

这是我对敌人的剧本:

public class FogCoverable : MonoBehaviour
{
    Renderer rend;

    void Start()
    {
        rend = GetComponent<Renderer>();
        FieldOfView.OnTargetsVisibilityChange += FieldOfViewOnTargetsVisibilityChange;
    }

    void OnDestroy()
    {
        FieldOfView.OnTargetsVisibilityChange -= FieldOfViewOnTargetsVisibilityChange;
    }

    void FieldOfViewOnTargetsVisibilityChange(List<Transform> newTargets)
    {
        rend.enabled = newTargets.Contains(transform);
    }
}

我不知道原来的愿景是如何能够揭示单位的。 我知道很多代码,但任何帮助都表示赞赏。

0 个答案:

没有答案