/// <summary>
        /// Removes the meshes from the memory.
        /// </summary>
        private void ClearMeshes() {
            if (_meshFilter != null) {
                DestroyImmediate(_meshFilter.sharedMesh);
            }

            if (_waterMeshSimple != null) {
                _waterMeshSimple.FreeMesh();
                _waterMeshSimple = null;
            }

            if (_waterMesh != null) {
                _waterMesh.FreeMesh();
                _waterMesh = null;
            }
        }
        /// <summary>
        /// Called when any property that defines the water simulation, changes.
        /// </summary>
        private void UpdateProperties() {
            // Calculating the grid parameters
            _resolution = Mathf.RoundToInt(_quality * MaxResolution() / 256f);
            GridMath.CalculateGrid(_resolution, Size, out _grid, out _nodeSize);

            // Determining what Solver instance do we have to use
            // and destroy other instances
            if (Application.isPlaying) {
                _waterSolver = null;

                DynamicWaterSolver[] solverComponents = GetComponents<DynamicWaterSolver>();
                foreach (DynamicWaterSolver solverComponent in solverComponents) {
                    if (_waterSolver == null) {
                        _waterSolver = solverComponent;
                    } else {
                        Destroy(solverComponent);
                    }
                }

                if (solverComponents.Length > 1) {
                    Debug.LogWarning(
                        "More than one DynamicWaterSolver component present. Using the first one, others are destroyed",
                        this);
                }

                // Creating the default solver, if no one is found
                if (_waterSolver == null) {
                    _waterSolver = gameObject.AddComponent<DynamicWaterSolverSimulation>();
                }

                _waterSolver.Initialize(_grid);

                // Recalculate the static obstruction objects
                if (_useObstructions) {
                    RecalculateObstructions();
                }
            }

            // Clearing the old meshes, if any
            ClearMeshes();

            // Creating the simple mesh substitute for when Solver is not in dirty state
            const int simpleMeshResolution = 6;
            _waterMeshSimple = new DynamicWaterMesh(simpleMeshResolution, Size, this);

            // Creating the actual water mesh
            _waterMesh = new DynamicWaterMesh(_resolution, Size, this, _waterSolver != null ? _waterSolver.FieldObstruction : null);

            // Assigning the mesh
            _meshFilter = gameObject.GetComponent<MeshFilter>();
            _meshFilter.mesh = _waterMesh.Mesh;

            // Precache for faster conversion
            _nodeSizeNormalized.x = 1f / Size.x * _grid.x;
            _nodeSizeNormalized.y = 1f / Size.y * _grid.y;

            // Update the collider bound
            UpdateCollider();

            // Create the child gameObject for interacting with water plane
            if (Application.isPlaying && UsePlaneCollider) {
                CreatePlaneCollider();
            }

            _prevIsDirty = true;
        }