internal void ResolveCollision(Collider2D objectCollider, bool isObjectEnteringWater) { if ((isObjectEnteringWater && !_isOnWaterEnterRipplesActive) || (!isObjectEnteringWater && !_isOnWaterExitRipplesActive)) { return; } if (_collisionMask != (_collisionMask | (1 << objectCollider.gameObject.layer))) { return; } Vector3[] vertices = _meshModule.Vertices; float[] velocities = _simulationModule.Velocities; float stiffnessSquareRoot = _simulationModule.StiffnessSquareRoot; Vector3 raycastDirection = _mainModule.UpDirection; int surfaceVerticesCount = _meshModule.SurfaceVerticesCount; int subdivisionsPerUnit = _meshModule.SubdivisionsPerUnit; Bounds objectColliderBounds = objectCollider.bounds; float minColliderBoundsX = _mainModule.TransformWorldToLocal(objectColliderBounds.min).x; float maxColliderBoundsX = _mainModule.TransformWorldToLocal(objectColliderBounds.max).x; int firstSurfaceVertexIndex = _simulationModule.IsUsingCustomBoundaries ? 1 : 0; int lastSurfaceVertexIndex = _simulationModule.IsUsingCustomBoundaries ? surfaceVerticesCount - 2 : surfaceVerticesCount - 1; float firstSurfaceVertexPosition = vertices[firstSurfaceVertexIndex].x; int startIndex = Mathf.Clamp(Mathf.RoundToInt((minColliderBoundsX - firstSurfaceVertexPosition) * subdivisionsPerUnit), firstSurfaceVertexIndex, lastSurfaceVertexIndex); int endIndex = Mathf.Clamp(Mathf.RoundToInt((maxColliderBoundsX - firstSurfaceVertexPosition) * subdivisionsPerUnit), firstSurfaceVertexIndex, lastSurfaceVertexIndex); int hitPointsCount = 0; float hitPointsVelocitiesSum = 0f; Vector2 hitPointsPositionsSum = new Vector2(0f, 0f); for (int surfaceVertexIndex = startIndex; surfaceVertexIndex <= endIndex; surfaceVertexIndex++) { Vector2 surfaceVertexPosition = _mainModule.TransformLocalToWorld(vertices[surfaceVertexIndex]); RaycastHit2D hit = Physics2D.Raycast(surfaceVertexPosition, raycastDirection, _collisionRaycastMaximumDistance, _collisionMask, _collisionMinimumDepth, _collisionMaximumDepth); if (hit.collider == objectCollider && hit.rigidbody != null) { float velocity = hit.rigidbody.GetPointVelocity(surfaceVertexPosition).y *_velocityMultiplier; velocity = Mathf.Clamp(Mathf.Abs(velocity), _minimumDisturbance, _maximumDisturbance); velocities[surfaceVertexIndex] += velocity * stiffnessSquareRoot * (isObjectEnteringWater ? -1f : 1f); hitPointsVelocitiesSum += velocity; hitPointsPositionsSum += hit.point; hitPointsCount++; } } if (hitPointsCount > 0) { _simulationModule.MarkVelocitiesArrayAsChanged(); Vector2 hitPointsPositionsMean = hitPointsPositionsSum / hitPointsCount; Vector3 spawnPosition = new Vector3(hitPointsPositionsMean.x, hitPointsPositionsMean.y, _mainModule.Position.z); float hitPointsVelocitiesMean = hitPointsVelocitiesSum / hitPointsCount; float disturbanceFactor = Mathf.InverseLerp(_minimumDisturbance, _maximumDisturbance, hitPointsVelocitiesMean); if (isObjectEnteringWater) { OnWaterEnterRipplesParticleEffect.PlayParticleEffect(spawnPosition); OnWaterEnterRipplesSoundEffect.PlaySoundEffect(spawnPosition, disturbanceFactor); if (_onWaterEnter != null) { _onWaterEnter.Invoke(); } } else { OnWaterExitRipplesParticleEffect.PlayParticleEffect(spawnPosition); OnWaterExitRipplesSoundEffect.PlaySoundEffect(spawnPosition, disturbanceFactor); if (_onWaterExit != null) { _onWaterExit.Invoke(); } } } }
private void CreateWaterEnterExitRipples(Collider2D objectCollider, bool isObjectEnteringWater) { Vector3[] vertices = _meshModule.Vertices; Vector3 raycastDirection = _mainModule.UpDirection; int surfaceVerticesCount = _meshModule.SurfaceVerticesCount; int subdivisionsPerUnit = _meshModule.SubdivisionsPerUnit; Bounds objectColliderBounds = objectCollider.bounds; float minColliderBoundsX = _mainModule.TransformPointWorldToLocal(objectColliderBounds.min).x; float maxColliderBoundsX = _mainModule.TransformPointWorldToLocal(objectColliderBounds.max).x; int firstSurfaceVertexIndex = _simulationModule.IsUsingCustomBoundaries ? 1 : 0; int lastSurfaceVertexIndex = _simulationModule.IsUsingCustomBoundaries ? surfaceVerticesCount - 2 : surfaceVerticesCount - 1; float firstSurfaceVertexPosition = vertices[firstSurfaceVertexIndex].x; int startIndex = Mathf.Clamp(Mathf.RoundToInt((minColliderBoundsX - firstSurfaceVertexPosition) * subdivisionsPerUnit), firstSurfaceVertexIndex, lastSurfaceVertexIndex); int endIndex = Mathf.Clamp(Mathf.RoundToInt((maxColliderBoundsX - firstSurfaceVertexPosition) * subdivisionsPerUnit), firstSurfaceVertexIndex, lastSurfaceVertexIndex); int hitPointCount = 0; float hitPointsVelocitiesSum = 0f; Vector2 hitPointsPositionsSum = new Vector2(0f, 0f); bool queriesStartInColliders = Physics2D.queriesStartInColliders; Physics2D.queriesStartInColliders = true; float raycastOriginYPos; var boxCollider = _attachedComponentsModule.BoxCollider; if (boxCollider != null && _attachedComponentsModule.BoxColliderTopEdgeLocation != WaterAttachedComponentsModule.BoxCollider2DTopEdgeLocation.WaterTopEdge) { raycastOriginYPos = boxCollider.offset.y + boxCollider.size.y * 0.5f; } else { raycastOriginYPos = _mainModule.Height * 0.5f; } for (int surfaceVertexIndex = startIndex; surfaceVertexIndex <= endIndex; surfaceVertexIndex++) { Vector2 surfaceVertexPosition = _mainModule.TransformPointLocalToWorld(new Vector3(vertices[surfaceVertexIndex].x, raycastOriginYPos)); var hitCount = Physics2D.RaycastNonAlloc(surfaceVertexPosition, raycastDirection, _raycastResults, _collisionRaycastMaximumDistance, _collisionMask, _collisionMinimumDepth, _collisionMaximumDepth); if (hitCount > 0) { int index = GetObjectColliderIndexInRaycastResults(objectCollider, hitCount); if (index < 0) { continue; } RaycastHit2D hit = _raycastResults[index]; float velocity = hit.rigidbody.GetPointVelocity(hit.point).y *_velocityMultiplier; velocity = Mathf.Clamp(Mathf.Abs(velocity), _minimumDisturbance, _maximumDisturbance); _simulationModule.DisturbSurfaceVertex(surfaceVertexIndex, velocity * (isObjectEnteringWater ? -1f : 1f)); hitPointsVelocitiesSum += velocity; hitPointsPositionsSum += hit.point; hitPointCount++; } } Physics2D.queriesStartInColliders = queriesStartInColliders; if (hitPointCount > 0) { Vector2 hitPointsPositionsMean = hitPointsPositionsSum / hitPointCount; Vector3 spawnPosition = new Vector3(hitPointsPositionsMean.x, hitPointsPositionsMean.y, _mainModule.Position.z); float hitPointsVelocitiesMean = hitPointsVelocitiesSum / hitPointCount; float disturbanceFactor = Mathf.InverseLerp(_minimumDisturbance, _maximumDisturbance, hitPointsVelocitiesMean); if (isObjectEnteringWater) { OnWaterEnterRipplesParticleEffect.PlayParticleEffect(spawnPosition); OnWaterEnterRipplesSoundEffect.PlaySoundEffect(spawnPosition, disturbanceFactor); if (_onWaterEnter != null) { _onWaterEnter.Invoke(); } if (_onWaterEnterExit != null) { _onWaterEnterExit.Invoke(_waterObject, objectCollider, true); } } else { OnWaterExitRipplesParticleEffect.PlayParticleEffect(spawnPosition); OnWaterExitRipplesSoundEffect.PlaySoundEffect(spawnPosition, disturbanceFactor); if (_onWaterExit != null) { _onWaterExit.Invoke(); } if (_onWaterEnterExit != null) { _onWaterEnterExit.Invoke(_waterObject, objectCollider, false); } } } }