EnergyEfficiencyManagement/Assets/Zion/Scripts/EnhancedModelExploder.cs

328 lines
9.9 KiB
C#

using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
public class EnhancedModelExploder : MonoBehaviour
{
[Header("爆炸效果设置")]
[SerializeField] private float explodeStrength = 2.5f;
[SerializeField] private float animationDuration = 1.5f;
[SerializeField] private Ease easeType = Ease.OutBack;
[Header("随机效果设置")]
[SerializeField] private float rotationRandomness = 180f;
[SerializeField] private float positionRandomness = 0.3f;
[SerializeField] private float depthMultiplier = 0.5f;
[Header("调试选项")]
[SerializeField] private bool debugMode = false;
[SerializeField] private Color debugColor = Color.cyan;
private class TransformData
{
public Vector3 localPosition;
public Quaternion localRotation;
public Vector3 localScale;
public Transform parent;
public int depth;
}
private Dictionary<Transform, TransformData> originalTransforms = new Dictionary<Transform, TransformData>();
private bool isInitialized = false;
private bool isExploded = false;
private void CollectAllChildrenRecursive(Transform current, int currentDepth = 0)
{
if (current == this.transform && currentDepth == 0)
{
}
else
{
originalTransforms[current] = new TransformData
{
localPosition = current.localPosition,
localRotation = current.localRotation,
localScale = current.localScale,
parent = current.parent,
depth = currentDepth
};
}
for (int i = 0; i < current.childCount; i++)
{
Transform child = current.GetChild(i);
CollectAllChildrenRecursive(child, currentDepth + 1);
}
}
private void InitializeTransforms(Transform modelRoot)
{
if (isInitialized) return;
originalTransforms.Clear();
CollectAllChildrenRecursive(modelRoot, 0);
if (debugMode)
{
Debug.Log($"已收集 {originalTransforms.Count} 个子物体的变换数据");
foreach (var kvp in originalTransforms)
{
Debug.Log($"物体: {kvp.Key.name}, 深度: {kvp.Value.depth}, 父物体: {kvp.Value.parent?.name ?? "null"}");
}
}
isInitialized = true;
}
public void ToggleExplode(Transform modelRoot, bool shouldExplode)
{
if (modelRoot == null)
{
Debug.LogWarning("模型根节点为空!");
return;
}
Debug.Log($"{isExploded}_{shouldExplode}_{isInitialized}");
if (isExploded != shouldExplode)
{
if (shouldExplode)
{
Debug.Log($"正在展开模型: {modelRoot.name}");
ExplodeModel(modelRoot);
}
else
{
Debug.Log($"正在折叠模型: {modelRoot.name}");
CollapseModel(modelRoot);
}
isExploded = shouldExplode;
}
}
private void ExplodeModel(Transform modelRoot)
{
InitializeTransforms(modelRoot);
int processedCount = 0;
foreach (var kvp in originalTransforms)
{
Transform child = kvp.Key;
TransformData data = kvp.Value;
if (child == modelRoot) continue;
Vector3 explodeDirection = CalculateExplodeDirection(child, modelRoot, data);
float depthFactor = 1f + (data.depth * depthMultiplier);
Vector3 targetPosition = data.localPosition + explodeDirection * explodeStrength * depthFactor;
Vector3 randomOffset = Random.insideUnitSphere * positionRandomness;
targetPosition += randomOffset;
Transform originalParent = child.parent;
if (child.parent != modelRoot)
{
child.SetParent(modelRoot, true);
}
child.DOLocalMove(targetPosition, animationDuration)
.SetEase(easeType)
.OnStart(() => {
if (debugMode)
{
Debug.Log($"开始展开: {child.name}, 深度: {data.depth}, 目标位置: {targetPosition}");
}
});
Vector3 randomRotation = new Vector3(
Random.Range(-rotationRandomness, rotationRandomness),
Random.Range(-rotationRandomness, rotationRandomness),
Random.Range(-rotationRandomness, rotationRandomness)
);
child.DOLocalRotate(child.localEulerAngles + randomRotation, animationDuration, RotateMode.LocalAxisAdd)
.SetEase(Ease.OutQuad);
child.DOScale(data.localScale * 1.1f, animationDuration * 0.5f)
.SetLoops(2, LoopType.Yoyo)
.SetEase(Ease.InOutSine);
processedCount++;
}
if (debugMode)
{
Debug.Log($"已处理 {processedCount} 个子物体的爆炸动画");
}
}
private Vector3 CalculateExplodeDirection(Transform child, Transform modelRoot, TransformData data)
{
Vector3 directionFromCenter = (child.position - modelRoot.position).normalized;
Vector3 directionFromParent = Vector3.zero;
if (data.parent != null && data.parent != modelRoot)
{
directionFromParent = (child.position - data.parent.position).normalized;
}
Vector3 forwardDirection = child.forward;
Vector3 finalDirection = directionFromCenter;
if (directionFromCenter.magnitude < 0.1f)
{
finalDirection = forwardDirection;
}
if (directionFromParent.magnitude > 0.1f)
{
finalDirection = (finalDirection + directionFromParent * 0.5f).normalized;
}
if (finalDirection.magnitude < 0.01f)
{
finalDirection = Vector3.up + Random.insideUnitSphere * 0.5f;
}
return finalDirection.normalized;
}
private void CollapseModel(Transform modelRoot)
{
if (!isInitialized) return;
int processedCount = 0;
foreach (var kvp in originalTransforms)
{
Transform child = kvp.Key;
TransformData data = kvp.Value;
if (child == modelRoot) continue;
child.DOKill();
if (child.parent != data.parent)
{
child.SetParent(data.parent, true);
}
child.DOLocalMove(data.localPosition, animationDuration)
.SetEase(easeType)
.OnStart(() => {
if (debugMode)
{
Debug.Log($"开始合并: {child.name}, 目标位置: {data.localPosition}");
}
});
child.DOLocalRotateQuaternion(data.localRotation, animationDuration)
.SetEase(Ease.InOutQuad);
child.DOScale(data.localScale, animationDuration)
.SetEase(Ease.InOutSine);
processedCount++;
}
if (debugMode)
{
Debug.Log($"已处理 {processedCount} 个子物体的合并动画");
}
}
public void Explode(Transform modelRoot)
{
ToggleExplode(modelRoot, true);
}
public void Collapse(Transform modelRoot)
{
ToggleExplode(modelRoot, false);
}
public void ResetImmediately(Transform modelRoot)
{
if (!isInitialized) return;
foreach (var kvp in originalTransforms)
{
Transform child = kvp.Key;
TransformData data = kvp.Value;
child.DOKill();
if (child.parent != data.parent)
{
child.SetParent(data.parent, false);
}
child.localPosition = data.localPosition;
child.localRotation = data.localRotation;
child.localScale = data.localScale;
}
isExploded = false;
if (debugMode)
{
Debug.Log($"已立即重置 {originalTransforms.Count} 个子物体的变换");
}
}
private void OnDrawGizmosSelected()
{
if (!debugMode || !isExploded) return;
foreach (var kvp in originalTransforms)
{
Transform child = kvp.Key;
TransformData data = kvp.Value;
if (child == null || data == null) continue;
Vector3 originalWorldPos = data.parent != null ?
data.parent.TransformPoint(data.localPosition) : data.localPosition;
Gizmos.color = debugColor;
Gizmos.DrawLine(originalWorldPos, child.position);
Gizmos.DrawWireCube(child.position, Vector3.one * 0.1f);
Gizmos.color = Color.red;
Gizmos.DrawSphere(originalWorldPos, 0.05f);
}
}
[ContextMenu("测试爆炸效果")]
public void TestExplosion()
{
if (Application.isPlaying)
{
Explode(this.transform);
}
else
{
Debug.Log("请在运行模式下测试爆炸效果");
}
}
[ContextMenu("测试合并效果")]
public void TestCollapse()
{
if (Application.isPlaying)
{
Collapse(this.transform);
}
else
{
Debug.Log("请在运行模式下测试合并效果");
}
}
[ContextMenu("立即重置")]
public void TestReset()
{
ResetImmediately(this.transform);
}
}