/// <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; } }
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); } } } }