This commit is contained in:
2025-10-15 20:13:48 +08:00
parent 0fd74a1a45
commit 1b17489c11
27 changed files with 3196 additions and 302 deletions

View File

@@ -0,0 +1,183 @@
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.Rendering.Universal;
public class ShadowColliderSystem : MonoBehaviour
{
[Header("系统设置")]
public Light shadowLight;
public Transform shadowWall;
public string shadowLayerName = "Shadow";
public LayerMask obstacleLayerMask = -1;
[Header("生成设置")]
public bool generateOnStart = true;
public bool updateInRealTime = false;
public float updateInterval = 0.1f;
[Header("阴影碰撞器")]
public List<ShadowCollider> shadowColliders = new List<ShadowCollider>();
private ShadowProjector projector;
private ShadowMeshGenerator meshGenerator;
private MarchingSquaresProcessor marchingSquares;
private float updateTimer;
void Start()
{
InitializeComponents();
if (generateOnStart)
{
GenerateAllShadowColliders();
}
}
void Update()
{
if (updateInRealTime)
{
updateTimer += Time.deltaTime;
if (updateTimer >= updateInterval)
{
UpdateAllShadowColliders();
updateTimer = 0f;
}
}
}
void InitializeComponents()
{
// 自动查找必要的组件
if (shadowLight == null) shadowLight = ShadowUtils.FindMainLight();
if (shadowWall == null) shadowWall = ShadowUtils.FindMainWall();
// 初始化子系统
projector = new ShadowProjector(shadowLight, shadowWall, obstacleLayerMask);
meshGenerator = new ShadowMeshGenerator();
marchingSquares = new MarchingSquaresProcessor();
}
[ContextMenu("生成所有阴影碰撞器")]
public void GenerateAllShadowColliders()
{
ClearAllShadowColliders();
var shadowObjects = ShadowUtils.FindObjectsInLayer(shadowLayerName);
foreach (GameObject obj in shadowObjects)
{
GenerateShadowCollider(obj);
}
Debug.Log($"生成了 {shadowColliders.Count} 个阴影碰撞器");
}
[ContextMenu("更新所有阴影碰撞器")]
public void UpdateAllShadowColliders()
{
foreach (var shadowCollider in shadowColliders)
{
if (shadowCollider != null)
{
UpdateShadowCollider(shadowCollider);
}
}
}
public void GenerateShadowCollider(GameObject shadowCaster)
{
if (!IsValidShadowCaster(shadowCaster)) return;
try
{
// 1. 投影网格到墙面
var projectedMesh = projector.ProjectMeshToWall(shadowCaster);
if (!projectedMesh.IsValid)
{
Debug.LogWarning($"无法为 {shadowCaster.name} 生成有效投影网格");
return;
}
// 2. 生成阴影密度网格
var densityGrid = meshGenerator.GenerateDensityGrid(projectedMesh, shadowWall);
// 3. 使用Marching Squares提取轮廓
var contours = marchingSquares.ExtractContours(densityGrid);
if (contours == null || contours.Count == 0)
{
Debug.LogWarning($"无法为 {shadowCaster.name} 提取轮廓");
return;
}
// 4. 创建阴影碰撞器对象
var shadowCollider = CreateShadowColliderObject(shadowCaster.name, contours);
shadowCollider.sourceObject = shadowCaster;
shadowColliders.Add(shadowCollider);
Debug.Log($"成功为 {shadowCaster.name} 生成阴影碰撞器,包含 {contours.Count} 个轮廓");
}
catch (System.Exception e)
{
Debug.LogError($"为 {shadowCaster.name} 生成阴影碰撞器时出错: {e.Message}");
}
}
public void UpdateShadowCollider(ShadowCollider shadowCollider)
{
if (shadowCollider.sourceObject == null) return;
var projectedMesh = projector.ProjectMeshToWall(shadowCollider.sourceObject);
var densityGrid = meshGenerator.GenerateDensityGrid(projectedMesh, shadowWall);
var contours = marchingSquares.ExtractContours(densityGrid);
shadowCollider.UpdateCollider(contours);
}
[ContextMenu("清空所有阴影碰撞器")]
public void ClearAllShadowColliders()
{
foreach (var collider in shadowColliders)
{
if (collider != null && collider.gameObject != null)
{
DestroyImmediate(collider.gameObject);
}
}
shadowColliders.Clear();
}
bool IsValidShadowCaster(GameObject obj)
{
return obj != null &&
obj.activeInHierarchy &&
obj.GetComponent<MeshFilter>() != null;
}
ShadowCollider CreateShadowColliderObject(string name, List<List<Vector2>> contours)
{
GameObject colliderObj = new GameObject($"{name}_ShadowCollider");
colliderObj.transform.SetParent(shadowWall);
colliderObj.transform.localPosition = Vector3.zero;
colliderObj.transform.localRotation = Quaternion.identity;
var shadowCollider = colliderObj.AddComponent<ShadowCollider>();
shadowCollider.Initialize(contours);
return shadowCollider;
}
void OnDestroy()
{
ClearAllShadowColliders();
}
#if UNITY_EDITOR
void OnDrawGizmosSelected()
{
if (marchingSquares != null && shadowWall != null)
{
marchingSquares.DrawGridGizmos(shadowWall);
}
}
#endif
}