예제 #1
0
    /*
     * Check light range for LightSensors that should be lit
     */
    public override void LightSensorCheck()
    {
        litObjects = new List <GameObject>();

        if (!light.enabled)
        {
            return;
        }

        Vector3 position   = transform.position;
        Vector3 forward    = transform.forward;
        float   lightAngle = light.spotAngle * 0.5f;
        float   lightRange = light.range;
        float   radius     = Mathf.Tan(lightAngle * Mathf.Deg2Rad) * lightRange;
        float   coneHyp    = Mathf.Sqrt(lightRange * lightRange + radius * radius);

        Collider[] cols = Physics.OverlapCapsule(position + (forward * radius), position + (forward * lightRange), radius, layerMask,
                                                 QueryTriggerInteraction.Ignore);

        foreach (Collider col in cols)
        {
            // Check object has a LightSensor
            LightSensor sensor = col.GetComponent <LightSensor>();
            if (sensor == null)
            {
                continue;
            }

            RaycastHit hitInfo;
            // perform initial position check
            Vector3 sensorPos = sensor.transform.position;
            float   hitAngle  = Vector3.Angle(forward, sensorPos - position);
            float   rayLength = Utilities.MapValues(hitAngle, 0f, lightAngle, lightRange, coneHyp);
            if (hitAngle <= lightAngle && Physics.Raycast(position, sensorPos - position, out hitInfo, rayLength,
                                                          layerMask))
            {
                if (hitInfo.transform == sensor.transform)
                {
                    litObjects.Add(sensor.gameObject);
                    sensor.LightObject(GetIntensity(hitInfo.point));
                    continue;
                }
            }
            // if no custom points defined, can just skip expanded check logic
            if (!sensor.UseCustomPoints())
            {
                continue;
            }

            // TODO: This section will finish when the first lit point is found.
            // Thus the intensity returned will be the first one found, rather then the highest of all points hit.
            // Unsure what ways around this there might be without constantly needing to check every point.
            // TODO: Somehow order points by distance from light????
            List <Vector3> points = sensor.GetLightCheckPoints(sensorPos - position);
            foreach (Vector3 point in points)
            {
                // check if the point is within the spot angle
                Vector3 dir = point - position;
                hitAngle = Vector3.Angle(forward, dir);
                if (hitAngle > lightAngle)
                {
                    continue;
                }

                Ray ray = new Ray(position, dir);
                rayLength = Utilities.MapValues(hitAngle, 0f, lightAngle, lightRange, coneHyp);
                if (Physics.Raycast(ray, out hitInfo, rayLength, layerMask, QueryTriggerInteraction.Ignore))
                {
                    // only trigger 'lit' status if raycast hits the sensor object
                    if (hitInfo.transform == sensor.transform)
                    {
                        litObjects.Add(sensor.gameObject);
                        sensor.LightObject(GetIntensity(hitInfo.point));
                        break;
                    }
                }
            }
        }
    }
    /*
     * Check light range for LightSensors that should be lit
     */
    public override void LightSensorCheck()
    {
        litObjects = new List <GameObject>();

        if (!light.enabled)
        {
            return;
        }

        Vector3 position = transform.position;
        float   range    = light.range;

        Collider[] cols = Physics.OverlapSphere(position, range, layerMask,
                                                QueryTriggerInteraction.Ignore);

        foreach (Collider col in cols)
        {
            // check object has a LightSensor
            LightSensor sensor = col.gameObject.GetComponent <LightSensor>();
            if (sensor == null)
            {
                continue;
            }

            Vector3    colPos = col.transform.position;
            RaycastHit hitInfo;
            if (Physics.Raycast(position, colPos - position, out hitInfo, range, layerMask))
            {
                // perform initial position check
                if (hitInfo.transform == col.transform)
                {
                    litObjects.Add(sensor.gameObject);
                    sensor.LightObject(GetIntensity(hitInfo.point));
                    continue;
                }
            }
            // if no custom points defined, can just skip next bit of logic
            if (!sensor.UseCustomPoints())
            {
                continue;
            }

            // TODO: This section will finish when the first lit point is found.
            // Thus the intensity returned will be the first one found, rather then the highest of all points hit.
            // Unsure what ways around this there might be without constantly needing to check every point.
            // TODO: Somehow order points by distance from light????
            List <Vector3> points = sensor.GetLightCheckPoints(colPos - position);
            foreach (Vector3 point in points)
            {
                Ray ray = new Ray(position, point - position);
                if (Physics.Raycast(ray, out hitInfo, range, layerMask, QueryTriggerInteraction.Ignore))
                {
                    // only trigger 'lit' status if raycast hits the sensor object
                    if (hitInfo.transform == col.transform)
                    {
                        litObjects.Add(sensor.gameObject);
                        sensor.LightObject(GetIntensity(hitInfo.point));
                        break;
                    }
                }
            }
        }
    }