private void Update()
    {
        if (LocalQueryPositions.Length != this.ResultsHeight.Length)
        {
            this.ResultsHeight = new float[LocalQueryPositions.Length];
        }

        ShapeGerstnerJobs.CompleteJobs();
        ShapeGerstnerJobs.RetrieveResultHeights(guid, ref ResultsHeight);

        if (ShowDebug)
        {
            for (int i = 0; i < ResultsHeight.Length; i++)
            {
                Vector3 point = this.transform.TransformPoint(LocalQueryPositions[i]);
                point.y = ResultsHeight[i];

                Draw3DCross(point, Color.magenta, Spacing / 2);
            }
        }

        // Schedule the next rounds jobs since the data is a frame old
        ShapeGerstnerJobs.UpdateQueryPoints(guid, this.transform, LocalQueryPositions);
    }
    private void FixedUpdate()
    {
#if UNITY_EDITOR
        // Sum weights every frame when running in editor in case weights are edited in the inspector.
        CalcTotalWeight();
#endif

#if USE_JOBS
        // Get the job data back.
        EnsureJobDataAllocated();
        ShapeGerstnerJobs.CompleteJobs();
        ShapeGerstnerJobs.RetrieveResultHeights(_guid, ref _resultHeights);
#endif

        // Trigger processing of displacement textures that have come back this frame. This will be processed
        // anyway in Update(), but FixedUpdate() is earlier so make sure it's up to date now.
        if (OceanRenderer.Instance._simSettingsAnimatedWaves.CollisionSource == SimSettingsAnimatedWaves.CollisionSources.OceanDisplacementTexturesGPU && GPUReadbackDisps.Instance)
        {
            GPUReadbackDisps.Instance.ProcessRequests();
        }

        var collProvider = OceanRenderer.Instance.CollisionProvider;
        var thisRect     = GetWorldAABB();
        if (!collProvider.GetSamplingData(ref thisRect, _minSpatialLength, _samplingData))
        {
            // No collision coverage for the sample area, in this case use the null provider.
            collProvider = CollProviderNull.Instance;
        }

        var     position = transform.position;
        Vector3 undispPos;
        if (!collProvider.ComputeUndisplacedPosition(ref position, _samplingData, out undispPos))
        {
            // If we couldn't get wave shape, assume flat water at sea level
            undispPos   = position;
            undispPos.y = OceanRenderer.Instance.SeaLevel;
        }

        Vector3 displacement, waterSurfaceVel;
        bool    dispValid, velValid;
        collProvider.SampleDisplacementVel(ref undispPos, _samplingData, out displacement, out dispValid, out waterSurfaceVel, out velValid);
        if (dispValid)
        {
            DisplacementToBoat = displacement;
        }

        if (GPUReadbackFlow.Instance)
        {
            GPUReadbackFlow.Instance.ProcessRequests();

            var flowRect = new Rect(position.x, position.z, 0f, 0f);
            if (GPUReadbackFlow.Instance.GetSamplingData(ref flowRect, _minSpatialLength, _samplingDataFlow))
            {
                Vector2 surfaceFlow;
                GPUReadbackFlow.Instance.SampleFlow(ref position, _samplingDataFlow, out surfaceFlow);
                waterSurfaceVel += new Vector3(surfaceFlow.x, 0, surfaceFlow.y);

                GPUReadbackFlow.Instance.ReturnSamplingData(_samplingDataFlow);
            }
        }

        FixedUpdateBuoyancy(collProvider);
        FixedUpdateDrag(collProvider, waterSurfaceVel);
        FixedUpdateEngine();

        collProvider.ReturnSamplingData(_samplingData);
    }