82 lines
2.5 KiB
C#
82 lines
2.5 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
|
|||
|
|
public class RaycastShadowCollider : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
public Light spotLight; // <20>۹<EFBFBD><DBB9><EFBFBD>
|
|||
|
|
public GameObject shadowCaster; // Ͷ<><CDB6><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
public int rayCount = 36; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
public float maxShadowDistance = 10f;
|
|||
|
|
|
|||
|
|
private PolygonCollider2D shadowCollider;
|
|||
|
|
|
|||
|
|
void Start()
|
|||
|
|
{
|
|||
|
|
shadowCollider = GetComponent<PolygonCollider2D>();
|
|||
|
|
if (shadowCollider == null)
|
|||
|
|
shadowCollider = gameObject.AddComponent<PolygonCollider2D>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Update()
|
|||
|
|
{
|
|||
|
|
UpdateShadowCollider();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void UpdateShadowCollider()
|
|||
|
|
{
|
|||
|
|
List<Vector2> shadowPoints = new List<Vector2>();
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƹⷽ<C6B9><E2B7BD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
Bounds bounds = shadowCaster.GetComponent<Renderer>().bounds;
|
|||
|
|
Vector3[] boundPoints = GetBoundPoints(bounds);
|
|||
|
|
|
|||
|
|
foreach (Vector3 point in boundPoints)
|
|||
|
|
{
|
|||
|
|
Vector3 toLight = (spotLight.transform.position - point).normalized;
|
|||
|
|
Ray ray = new Ray(point, toLight);
|
|||
|
|
RaycastHit hit;
|
|||
|
|
|
|||
|
|
if (Physics.Raycast(ray, out hit, maxShadowDistance))
|
|||
|
|
{
|
|||
|
|
if (hit.collider.gameObject == gameObject) // <20><><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD>
|
|||
|
|
{
|
|||
|
|
// ת<><D7AA><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD>ľֲ<C4BE><D6B2><EFBFBD><EFBFBD><EFBFBD>ϵ
|
|||
|
|
Vector3 localHit = transform.InverseTransformPoint(hit.point);
|
|||
|
|
shadowPoints.Add(new Vector2(localHit.x, localHit.y));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <20>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>γ<EFBFBD><EFBFBD><CDB9>
|
|||
|
|
if (shadowPoints.Count > 2)
|
|||
|
|
{
|
|||
|
|
List<Vector2> convexHull = ComputeConvexHull(shadowPoints);
|
|||
|
|
shadowCollider.SetPath(0, convexHull);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Vector3[] GetBoundPoints(Bounds bounds)
|
|||
|
|
{
|
|||
|
|
return new Vector3[]
|
|||
|
|
{
|
|||
|
|
bounds.min,
|
|||
|
|
bounds.max,
|
|||
|
|
new Vector3(bounds.min.x, bounds.min.y, bounds.max.z),
|
|||
|
|
new Vector3(bounds.min.x, bounds.max.y, bounds.min.z),
|
|||
|
|
new Vector3(bounds.max.x, bounds.min.y, bounds.min.z),
|
|||
|
|
new Vector3(bounds.min.x, bounds.max.y, bounds.max.z),
|
|||
|
|
new Vector3(bounds.max.x, bounds.min.y, bounds.max.z),
|
|||
|
|
new Vector3(bounds.max.x, bounds.max.y, bounds.min.z)
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// <><CDB9><EFBFBD>㷨<EFBFBD><E3B7A8>Graham Scan<61><6E>
|
|||
|
|
List<Vector2> ComputeConvexHull(List<Vector2> points)
|
|||
|
|
{
|
|||
|
|
if (points.Count < 3) return points;
|
|||
|
|
|
|||
|
|
// ʵ<><CAB5><EFBFBD><CDB9><EFBFBD>㷨...
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Unity<74><79>Collider2D.CreatePrimitive<76><65><EFBFBD>ߵ<EFBFBD><DFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
return points; // <20><EFBFBD><F2BBAFB7><EFBFBD>
|
|||
|
|
}
|
|||
|
|
}
|