Exemplo n.º 1
0
        internal void Validate(WaterCollisionRipplesModuleParameters parameters)
        {
            IsOnWaterEnterRipplesActive = parameters.ActivateOnWaterEnterRipples;
            IsOnWaterExitRipplesActive  = parameters.ActivateOnWaterExitRipples;
            MinimumDisturbance          = parameters.MinimumDisturbance;
            MaximumDisturbance          = parameters.MaximumDisturbance;
            VelocityMultiplier          = parameters.VelocityMultiplier;
            CollisionMask                   = parameters.CollisionMask;
            CollisionMinimumDepth           = parameters.CollisionMinimumDepth;
            CollisionMaximumDepth           = parameters.CollisionMaximumDepth;
            CollisionRaycastMaximumDistance = parameters.CollisionRaycastMaxDistance;
            OnWaterEnter = parameters.OnWaterEnter;
            OnWaterExit  = parameters.OnWaterExit;

            OnWaterEnterRipplesParticleEffect.Validate(parameters.WaterEnterParticleEffectParameters);
            OnWaterEnterRipplesSoundEffect.Validate(parameters.WaterEnterSoundEffectParameters);
            OnWaterExitRipplesParticleEffect.Validate(parameters.WaterExitParticleEffectParameters);
            OnWaterExitRipplesSoundEffect.Validate(parameters.WaterExitSoundEffectParameters);
        }
Exemplo n.º 2
0
        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();
                    }
                }
            }
        }
Exemplo n.º 3
0
        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);
                    }
                }
            }
        }