diff --git a/Editor/BuoyantObjectEditor.cs b/Editor/BuoyantObjectEditor.cs index e8093c2..64c15b5 100644 --- a/Editor/BuoyantObjectEditor.cs +++ b/Editor/BuoyantObjectEditor.cs @@ -7,32 +7,38 @@ namespace WaterSystem.Physics [CustomEditor(typeof(BuoyantObject))] public class BuoyantObjectEditor : Editor { - private BuoyantObject obj; + private BuoyantObject Obj => serializedObject.targetObject as BuoyantObject; + [SerializeField] private bool _heightsDebugBool; + [SerializeField] private bool _generalSettingsBool; - private void OnEnable() - { - obj = serializedObject.targetObject as BuoyantObject; - } - public override void OnInspectorGUI() { - _generalSettingsBool = EditorGUILayout.Foldout(_generalSettingsBool, "General Settings"); + if (!EditorApplication.isPlaying) + { + base.OnInspectorGUI(); + return; + } + + _generalSettingsBool = EditorGUILayout.BeginFoldoutHeaderGroup(_generalSettingsBool, "General Settings"); + EditorGUILayout.EndFoldoutHeaderGroup(); if (_generalSettingsBool) { base.OnInspectorGUI(); } - if (EditorGUILayout.BeginFoldoutHeaderGroup(_heightsDebugBool, "Height Debug Values")) + _heightsDebugBool = EditorGUILayout.BeginFoldoutHeaderGroup(_heightsDebugBool, "Height Debug Values"); + EditorGUILayout.EndFoldoutHeaderGroup(); + if (_heightsDebugBool) { - if (obj.Heights != null) + if (Obj.Heights != null) { - for (var i = 0; i < obj.Heights.Length; i++) + for (var i = 0; i < Obj.Heights.Length; i++) { - var h = obj.Heights[i]; + var h = Obj.Heights[i]; EditorGUILayout.LabelField($"{i})Wave(heights):", $"X:{h.x:00.00} Y:{h.y:00.00} Z:{h.z:00.00}"); } } @@ -41,7 +47,6 @@ public override void OnInspectorGUI() EditorGUILayout.HelpBox("Height debug info only available in playmode.", MessageType.Info); } } - EditorGUILayout.EndFoldoutHeaderGroup(); } } } diff --git a/Runtime/GerstnerWavesJobs.cs b/Runtime/GerstnerWavesJobs.cs index 71e9e83..873e199 100644 --- a/Runtime/GerstnerWavesJobs.cs +++ b/Runtime/GerstnerWavesJobs.cs @@ -78,7 +78,9 @@ public static void Cleanup() _waterHeightHandle.Complete(); DepthGenerator.CleanUp(); - + + Registry.Clear(); + //Cleanup native arrays _waveData.Dispose(); _positions.Dispose(); diff --git a/Runtime/Physics/BuoyantObject.cs b/Runtime/Physics/BuoyantObject.cs index aa989ae..4d0a13b 100644 --- a/Runtime/Physics/BuoyantObject.cs +++ b/Runtime/Physics/BuoyantObject.cs @@ -48,6 +48,9 @@ public class BuoyantObject : MonoBehaviour private DebugDrawing[] _debugInfo; // For drawing force gizmos [NonSerialized] public float PercentSubmerged; + private bool IsPhysicsBased => _buoyancyType == BuoyancyType.Physical || _buoyancyType == BuoyancyType.PhysicalVoxel; + private bool IsVoxelBased => _buoyancyType == BuoyancyType.NonPhysicalVoxel || _buoyancyType == BuoyancyType.PhysicalVoxel; + [ContextMenu("Initialize")] private void Init() { @@ -82,7 +85,7 @@ private void Init() private void SetupVoxels() { - if (_buoyancyType == BuoyancyType.NonPhysicalVoxel || _buoyancyType == BuoyancyType.PhysicalVoxel) + if (IsVoxelBased) { SliceIntoVoxels(); } @@ -106,6 +109,8 @@ private void OnEnable() _guid = gameObject.GetInstanceID(); Init(); LocalToWorldConversion(); + + StartCoroutine(LateFixedUpdate()); } private void SetupColliders() @@ -121,35 +126,31 @@ private void SetupColliders() private void Update() { + if (IsPhysicsBased) + return; + #if STATIC_EVERYTHING var dt = 0.0f; #else var dt = Time.deltaTime; #endif + switch (_buoyancyType) { case BuoyancyType.NonPhysical: - { - _samplePoints[0] = transform.position; - var t = transform; - var vec = t.position; - vec.y = Heights[0].y + waterLevelOffset; - t.position = vec; - var up = t.up; - t.up = Vector3.Slerp(up, _normals[0], dt); - break; - } + { + _samplePoints[0] = transform.position; + var t = transform; + var vec = t.position; + vec.y = Heights[0].y + waterLevelOffset; + t.position = vec; + var up = t.up; + t.up = Vector3.Slerp(up, _normals[0], dt); + break; + } case BuoyancyType.NonPhysicalVoxel: // do the voxel non-physical break; - case BuoyancyType.Physical: - LocalToWorldJob.CompleteJob(_guid); - GetVelocityPoints(); - break; - case BuoyancyType.PhysicalVoxel: - LocalToWorldJob.CompleteJob(_guid); - GetVelocityPoints(); - break; default: throw new ArgumentOutOfRangeException(); } @@ -160,38 +161,51 @@ private void Update() private void FixedUpdate() { + if (!IsPhysicsBased) + return; + var submergedAmount = 0f; - + + LocalToWorldJob.CompleteJob(_guid); + GetVelocityPoints(); + GerstnerWavesJobs.UpdateSamplePoints(ref _samplePoints, _guid); + GerstnerWavesJobs.GetData(_guid, ref Heights, ref _normals); + switch (_buoyancyType) { case BuoyancyType.PhysicalVoxel: - { - LocalToWorldJob.CompleteJob(_guid); - //Debug.Log("new pass: " + gameObject.name); - UnityPhysics.autoSyncTransforms = false; - - for (var i = 0; i < _voxels.Length; i++) - BuoyancyForce(_samplePoints[i], _velocity[i], Heights[i].y + waterLevelOffset, ref submergedAmount, ref _debugInfo[i]); - UnityPhysics.SyncTransforms(); - UnityPhysics.autoSyncTransforms = true; - UpdateDrag(submergedAmount); - break; - } + { + var autoSyncTransforms = UnityPhysics.autoSyncTransforms; + UnityPhysics.autoSyncTransforms = false; + + for (var i = 0; i < _voxels.Length; i++) + BuoyancyForce(_samplePoints[i], _velocity[i], Heights[i].y + waterLevelOffset, ref submergedAmount, ref _debugInfo[i]); + + UnityPhysics.SyncTransforms(); + UnityPhysics.autoSyncTransforms = autoSyncTransforms; + + UpdateDrag(submergedAmount); + break; + } case BuoyancyType.Physical: - //LocalToWorldJob.CompleteJob(_guid); BuoyancyForce(Vector3.zero, _velocity[0], Heights[0].y + waterLevelOffset, ref submergedAmount, ref _debugInfo[0]); //UpdateDrag(submergedAmount); break; - case BuoyancyType.NonPhysical: - break; - case BuoyancyType.NonPhysicalVoxel: - break; default: throw new ArgumentOutOfRangeException(); } } - private void LateUpdate() { LocalToWorldConversion(); } + private static readonly WaitForFixedUpdate YieldLateFixedUpdate = new WaitForFixedUpdate(); + private System.Collections.IEnumerator LateFixedUpdate() + { + while (true) + { + yield return YieldLateFixedUpdate; + + LocalToWorldConversion(); + } + } private void OnDestroy() { @@ -200,7 +214,9 @@ private void OnDestroy() void CleanUp() { - if (_buoyancyType == BuoyancyType.Physical || _buoyancyType == BuoyancyType.PhysicalVoxel) + StopAllCoroutines(); + + if (IsPhysicsBased) { LocalToWorldJob.Cleanup(_guid); } @@ -212,7 +228,7 @@ void CleanUp() private void LocalToWorldConversion() { - if (_buoyancyType != BuoyancyType.Physical && _buoyancyType != BuoyancyType.PhysicalVoxel) return; + if (!IsPhysicsBased) return; var transformMatrix = transform.localToWorldMatrix; LocalToWorldJob.ScheduleJob(_guid, transformMatrix); @@ -258,6 +274,7 @@ private void SliceIntoVoxels() var size = t.localScale; t.SetPositionAndRotation(Vector3.zero, Quaternion.identity); t.localScale = Vector3.one; + UnityPhysics.SyncTransforms(); _voxels = null; var points = new List(); @@ -294,6 +311,8 @@ private void SliceIntoVoxels() _voxels = points.ToArray(); t.SetPositionAndRotation(pos, rot); t.localScale = size; + UnityPhysics.SyncTransforms(); + var voxelVolume = Mathf.Pow(voxelResolution, 3f) * _voxels.Length; var rawVolume = rawBounds.size.x * rawBounds.size.y * rawBounds.size.z; volume = Mathf.Min(rawVolume, voxelVolume); @@ -387,7 +406,7 @@ private void OnDrawGizmosSelected() water.y = debug.WaterHeight; Gizmos.DrawLine(debug.Position, water); // draw the water line Gizmos.DrawSphere(water, gizmoSize * 4f); - if(_buoyancyType == BuoyancyType.Physical || _buoyancyType == BuoyancyType.PhysicalVoxel) + if(IsPhysicsBased) { Gizmos.color = Color.red; Gizmos.DrawRay(debug.Position, debug.Force / _rb.mass); // draw force