/// <summary>
        /// Generate a ripple at a particular position.
        /// </summary>
        /// <param name="position">Ripple position.</param>
        /// <param name="disturbanceFactor">Range: [0..1]: The disturbance is linearly interpolated between the minimum disturbance and the maximum disturbance by this factor.</param>
        /// <param name="pullWaterDown">Pull water down or up?</param>
        /// <param name="playSoundEffect">Play the sound effect.</param>
        /// <param name="playParticleEffect">Play the particle effect.</param>
        /// <param name="smoothRipple">Disturb neighbor vertices to create a smoother ripple (wave).</param>
        /// <param name="smoothingFactor">Range: [0..1]: The amount of disturbance to apply to neighbor vertices.</param>
        public void GenerateRipple(Vector2 position, float disturbanceFactor, bool pullWaterDown, bool playSoundEffect, bool playParticleEffect, bool smoothRipple, float smoothingFactor = 0.5f)
        {
            float xPosition = _mainModule.TransformPointWorldToLocal(position).x;

            float leftBoundary                = _simulationModule.LeftBoundary;
            float rightBoundary               = _simulationModule.RightBoundary;
            int   surfaceVertexCount          = _meshModule.SurfaceVerticesCount;
            int   leftMostSurfaceVertexIndex  = _simulationModule.IsUsingCustomBoundaries ? 1 : 0;
            int   rightMostSurfaceVertexIndex = _simulationModule.IsUsingCustomBoundaries ? surfaceVertexCount - 2 : surfaceVertexCount - 1;

            if (xPosition < leftBoundary || xPosition > rightBoundary)
            {
                return;
            }

            float disturbance = (pullWaterDown ? -1f : 1f) * Mathf.Lerp(_minimumDisturbance, _maximumDisturbance, Mathf.Clamp01(disturbanceFactor));

            float subdivisionsPerUnit = (surfaceVertexCount - (_simulationModule.IsUsingCustomBoundaries ? 3 : 1)) / (rightBoundary - leftBoundary);
            float delta = (xPosition - leftBoundary) * subdivisionsPerUnit;
            int   nearestVertexIndex = leftMostSurfaceVertexIndex + Mathf.RoundToInt(delta);

            _simulationModule.DisturbSurfaceVertex(nearestVertexIndex, disturbance);

            if (smoothRipple)
            {
                smoothingFactor = Mathf.Clamp01(smoothingFactor);
                float smoothedDisturbance = disturbance * smoothingFactor;

                int previousNearestIndex = nearestVertexIndex - 1;
                if (previousNearestIndex >= leftMostSurfaceVertexIndex)
                {
                    _simulationModule.DisturbSurfaceVertex(previousNearestIndex, smoothedDisturbance);
                }

                int nextNearestIndex = nearestVertexIndex + 1;
                if (nextNearestIndex <= rightMostSurfaceVertexIndex)
                {
                    _simulationModule.DisturbSurfaceVertex(nextNearestIndex, smoothedDisturbance);
                }
            }

            Vector3 spawnPosition = _mainModule.TransformPointLocalToWorld(new Vector3(xPosition, _mainModule.Height * 0.5f));

            if (playParticleEffect)
            {
                _particleEffect.PlayParticleEffect(spawnPosition);
            }

            if (playSoundEffect)
            {
                _soundEffect.PlaySoundEffect(spawnPosition, disturbanceFactor);
            }
        }
        internal void PhysicsUpdate(float deltaTime)
        {
            if (!_isActive || (!_updateWhenOffscreen && !_mainModule.IsVisible))
            {
                return;
            }

            _elapsedTime += deltaTime;

            if (_elapsedTime >= _currentInterval)
            {
                if (_randomizeRipplesSourcePositions)
                {
                    RandomizeIndices();
                }

                int surfaceVerticesCount = _meshModule.SurfaceVerticesCount;
                int startIndex           = _simulationModule.IsUsingCustomBoundaries ? 1 : 0;
                int endIndex             = _simulationModule.IsUsingCustomBoundaries ? surfaceVerticesCount - 2 : surfaceVerticesCount - 1;

                Vector3[] vertices = _meshModule.Vertices;

                bool playSoundEffect    = _soundEffect.IsActive;
                bool playParticleEffect = _particleEffect.IsActive;

                for (int i = 0, imax = _ripplesSourcesIndices.Count; i < imax; i++)
                {
                    int index = _ripplesSourcesIndices[i];

                    float disturbance = _randomizeDisturbance ? Random.Range(_minimumDisturbance, _maximumDisturbance) : _disturbance;

                    _simulationModule.DisturbSurfaceVertex(index, -disturbance);

                    if (_smoothRipples)
                    {
                        float smoothedDisturbance = disturbance * _smoothingFactor;
                        int   previousIndex, nextIndex;
                        previousIndex = index - 1;
                        nextIndex     = index + 1;

                        if (previousIndex >= startIndex)
                        {
                            _simulationModule.DisturbSurfaceVertex(previousIndex, -smoothedDisturbance);
                        }

                        if (nextIndex <= endIndex)
                        {
                            _simulationModule.DisturbSurfaceVertex(nextIndex, -smoothedDisturbance);
                        }
                    }

#if UNITY_EDITOR
                    if (!Application.isPlaying)
                    {
                        continue;
                    }
#endif

                    if (_soundEffect.IsActive || _particleEffect.IsActive)
                    {
                        Vector3 spawnPosition = _mainModule.TransformPointLocalToWorld(vertices[index]);

                        if (playParticleEffect)
                        {
                            _particleEffect.PlayParticleEffect(spawnPosition);
                        }

                        if (playSoundEffect)
                        {
                            float disturbanceFactor = Mathf.InverseLerp(_minimumDisturbance, _maximumDisturbance, disturbance);
                            _soundEffect.PlaySoundEffect(spawnPosition, disturbanceFactor);
                        }
                    }
                }

                _currentInterval = _randomizeTimeInterval ? Random.Range(_minimumTimeInterval, _maximumTimeInterval) : _timeInterval;
                _elapsedTime     = 0f;
            }
        }
Exemple #3
0
        internal void CreateRipples(Vector2 left, Vector2 right, float disturbance, float spread, bool smooth, float smoothingFactor = 0.5f)
        {
            Vector2 leftVertexPos  = _mainModule.TransformPointWorldToLocal(left);
            Vector2 rightVertexPos = _mainModule.TransformPointWorldToLocal(right);

            float halfWaterHeight = _mainModule.Height * 0.5f;

            if (leftVertexPos.y > halfWaterHeight)
            {
                return;
            }

            int leftVertexIndex;
            int rightVertexIndex;

            float leftBoundary         = _simulationModule.LeftBoundary;
            float rightBoundary        = _simulationModule.RightBoundary;
            int   surfaceVerticesCount = _meshModule.SurfaceVerticesCount;
            int   startIndex           = _simulationModule.IsUsingCustomBoundaries ? 1 : 0;
            int   endIndex             = _simulationModule.IsUsingCustomBoundaries ? surfaceVerticesCount - 2 : surfaceVerticesCount - 1;

            if (leftVertexPos.x > leftBoundary)
            {
                leftVertexIndex = startIndex + Mathf.RoundToInt((leftVertexPos.x - leftBoundary) * _meshModule.SubdivisionsPerUnit);
                if (leftVertexIndex > endIndex)
                {
                    leftVertexIndex = endIndex;
                }
            }
            else
            {
                leftVertexIndex = startIndex;
            }

            if (rightVertexPos.x < rightBoundary)
            {
                rightVertexIndex = startIndex + Mathf.RoundToInt((rightVertexPos.x - leftBoundary) * _meshModule.SubdivisionsPerUnit);
                if (rightVertexIndex < startIndex)
                {
                    rightVertexIndex = startIndex;
                }
            }
            else
            {
                rightVertexIndex = endIndex;
            }

            if (leftVertexIndex == rightVertexIndex)
            {
                return;
            }

            var vertices = _meshModule.Vertices;

            _affectedVerticesIndices.Clear();

            int affectedVerticesCount = Mathf.CeilToInt(Mathf.Abs(rightVertexIndex - leftVertexIndex) * spread);

            for (int i = 0; i < affectedVerticesCount + 1;)
            {
                int vertexIndex = Random.Range(leftVertexIndex, rightVertexIndex + 1);

                if (!_affectedVerticesIndices.Contains(vertexIndex))
                {
                    _affectedVerticesIndices.Add(vertexIndex);
                    i++;
                }
            }

            for (int i = 0; i < affectedVerticesCount; i++)
            {
                int vertexIndex = _affectedVerticesIndices[i];

                _simulationModule.DisturbSurfaceVertex(vertexIndex, -disturbance);
                if (smooth)
                {
                    smoothingFactor = Mathf.Clamp01(smoothingFactor);
                    float smoothedDisturbance = disturbance * smoothingFactor;

                    int previousNearestIndex = vertexIndex - 1;
                    if (previousNearestIndex >= startIndex)
                    {
                        _simulationModule.DisturbSurfaceVertex(previousNearestIndex, -smoothedDisturbance);
                    }

                    int nextNearestIndex = vertexIndex + 1;
                    if (nextNearestIndex <= endIndex)
                    {
                        _simulationModule.DisturbSurfaceVertex(nextNearestIndex, -smoothedDisturbance);
                    }
                }
            }
        }