Files
2026-03-04 09:37:33 +08:00

164 lines
4.2 KiB
C#

using System.Collections.Generic;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
[ExecuteInEditMode]
public class FitToWaterSurfaceBurst : MonoBehaviour
{
public int count = 50;
public WaterSurface waterSurface;
public bool includeDeformation = true;
public bool excludeSimulation;
public float currentSpeedMultiplier = 1f;
public GameObject prefab;
private List<GameObject> prefabList;
private BoxCollider boxCollider;
private NativeArray<float3> targetPositionBuffer;
private NativeArray<float> errorBuffer;
private NativeArray<float3> candidatePositionBuffer;
private NativeArray<float3> projectedPositionWSBuffer;
private NativeArray<float3> normalWSBuffer;
private NativeArray<float3> directionBuffer;
private NativeArray<int> stepCountBuffer;
private void Start()
{
boxCollider = GetComponent<BoxCollider>();
Reset();
}
private void Reset()
{
OnDestroy();
targetPositionBuffer = new NativeArray<float3>(count, Allocator.Persistent);
errorBuffer = new NativeArray<float>(count, Allocator.Persistent);
candidatePositionBuffer = new NativeArray<float3>(count, Allocator.Persistent);
projectedPositionWSBuffer = new NativeArray<float3>(count, Allocator.Persistent);
normalWSBuffer = new NativeArray<float3>(count, Allocator.Persistent);
stepCountBuffer = new NativeArray<int>(count, Allocator.Persistent);
directionBuffer = new NativeArray<float3>(count, Allocator.Persistent);
prefabList = new List<GameObject>();
prefabList.Clear();
for (int num = base.transform.childCount; num > 0; num--)
{
SmartDestroy(base.transform.GetChild(0).gameObject);
}
for (int i = 0; i < count; i++)
{
GameObject gameObject = Object.Instantiate(prefab);
gameObject.transform.parent = base.transform;
gameObject.transform.localPosition = RandomPointInBounds(GetComponent<Collider>().bounds) - base.transform.position;
gameObject.transform.localEulerAngles = new Vector3(-180f, UnityEngine.Random.Range(0, 360), 0f);
prefabList.Add(gameObject);
}
}
private void Update()
{
if (waterSurface == null)
{
return;
}
if (!targetPositionBuffer.IsCreated)
{
Reset();
}
WaterSimSearchData wsd = default(WaterSimSearchData);
if (waterSurface.FillWaterSearchData(ref wsd))
{
for (int i = 0; i < prefabList.Count; i++)
{
targetPositionBuffer[i] = prefabList[i].transform.position;
}
IJobParallelForExtensions.Schedule(new WaterSimulationSearchJob
{
simSearchData = wsd,
targetPositionWSBuffer = targetPositionBuffer,
startPositionWSBuffer = targetPositionBuffer,
maxIterations = 8,
error = 0.01f,
includeDeformation = includeDeformation,
excludeSimulation = excludeSimulation,
projectedPositionWSBuffer = projectedPositionWSBuffer,
normalWSBuffer = normalWSBuffer,
errorBuffer = errorBuffer,
candidateLocationWSBuffer = candidatePositionBuffer,
directionBuffer = directionBuffer,
stepCountBuffer = stepCountBuffer
}, count, 1).Complete();
for (int j = 0; j < prefabList.Count; j++)
{
float3 float5 = projectedPositionWSBuffer[j];
prefabList[j].transform.position = float5 + Time.deltaTime * directionBuffer[j] * currentSpeedMultiplier;
}
}
}
private Vector3 RandomPointInBounds(Bounds bounds)
{
return new Vector3(UnityEngine.Random.Range(bounds.min.x, bounds.max.x), UnityEngine.Random.Range(bounds.min.y, bounds.max.y), UnityEngine.Random.Range(bounds.min.z, bounds.max.z));
}
private void OnDestroy()
{
if (targetPositionBuffer.IsCreated)
{
targetPositionBuffer.Dispose();
}
if (errorBuffer.IsCreated)
{
errorBuffer.Dispose();
}
if (candidatePositionBuffer.IsCreated)
{
candidatePositionBuffer.Dispose();
}
if (projectedPositionWSBuffer.IsCreated)
{
projectedPositionWSBuffer.Dispose();
}
if (normalWSBuffer.IsCreated)
{
normalWSBuffer.Dispose();
}
if (stepCountBuffer.IsCreated)
{
stepCountBuffer.Dispose();
}
if (directionBuffer.IsCreated)
{
directionBuffer.Dispose();
}
}
private void OnDisable()
{
OnDestroy();
}
public static void SmartDestroy(Object obj)
{
if (!(obj == null))
{
Object.Destroy(obj);
}
}
}