}//Update


    /// <summary>
    ///  Cast Horizontal ray with respect to "rayLength" sign. SKINWIDTH is added 
    /// to the rayLength here.
    /// </summary>
    /// <param name="rayLength">Length of the ray and the direction (based of
    ///                         its sign) to cast. </param>
    /// <param name="positionIndex">Position of the ray relative to Number of
    ///                             rays count set in Props.</param>
    /// <returns>Casted ray meta data.</returns>
    public RaycastMeta CastHorizontalRay(float rayLength, int positionIndex) {
        float directionX = Mathf.Sign(rayLength);
        rayLength = Mathf.Abs(rayLength) + SKINWIDTH;

        Vector2 rayOrigin = (directionX == -1) ? rayOrigins.bottomLeft : rayOrigins.bottomRight;
        Vector2 direction = Vector2.right * directionX;

        rayOrigin += Vector2.up * (raySpacing.x * positionIndex);
        RaycastHit2D hit = Physics2D.Raycast(rayOrigin, direction, 
                                            rayLength, this.Props.CollisionMask);

        RaycastMeta meta = new RaycastMeta(rayOrigin, direction, hit, rayLength, positionIndex);

#if UNITY_EDITOR
        if (this.DebugProps.On) {
            if (positionIndex == 0)
                Debug.DrawRay(meta.Origin, meta.FullDir, DebugProps.First);
            else
                Debug.DrawRay(meta.Origin, meta.FullDir, DebugProps.NoHit);
            if (hit)
                Debug.DrawRay(meta.Origin, meta.FullDir, DebugProps.Hit);
        }
#endif

        return meta;
    }//Raycast
        }//Update


        public virtual void MovePassangers() {
            if (_cd == null)
                return;
            Vector3 deltaMovement = this.Velocity;
            float direction = 1f;
            deltaMovement.y = direction * 0.3f;

            _cd.UpdateRayOrigin();
            _cd.HorizontalCollisions(ref deltaMovement);
            _cd.VerticalCollisions(ref deltaMovement);

            for (int i = 0; i < _cd.VerticalRayMeta.Length; i++) {
                RaycastMeta meta = _cd.VerticalRayMeta[i];
                if(!meta.Ray)
                    continue;

                float moveX = this.Velocity.x;
                float moveY = this.Velocity.y;
                if (Mathf.Sign(this.Velocity.y) > 0)
                    moveY = Velocity.y - (meta.Ray.distance - 0.055f) * direction;

                //var mvmnt = meta.Ray.collider.GetComponent<MovementControls>();
                //if (mvmnt == null)
                //    continue;

                //var player = meta.Ray.collider.GetComponent<Player>();
                //player.IsOnMovingPlatform = true;

                //meta.Ray.collider.transform.Translate(new Vector3(moveX, moveY));
                //mvmnt.SetVelocity(new Vector2(moveX, moveY));
            }//for

        }//MovePassangers
    }//Raycast


    /// <summary>
    ///  Cast Vertically (down/up) ray with respect to "rayLength" sign. SKINWIDTH is added 
    /// to the rayLength here.
    /// </summary>
    /// <param name="rayLength">Length of the ray and the direction (based of
    ///                         its sign) to cast. </param>
    /// <param name="positionIndex">Position of the ray relative to Number of
    ///                             rays count set in Props.</param>
    /// <returns>Casted ray meta data.</returns>
    public RaycastMeta CastVerticalRay(float rayLength, int positionIndex) {
        float directionY = Mathf.Sign(rayLength); //current movement direction (up/down)
        rayLength = Mathf.Abs(rayLength) + SKINWIDTH;

        Vector2 rayOrigin = (directionY == -1) ? rayOrigins.bottomLeft : rayOrigins.topLeft;
        Vector2 direction = Vector2.up * directionY;

        rayOrigin += Vector2.right * (raySpacing.y * positionIndex);
        RaycastHit2D hit = Physics2D.Raycast(rayOrigin, direction,
                                            rayLength, this.Props.CollisionMask);

        //To ignore raycast hits on itself, unselect the "Queries Start In Colliders"
        //at the "Project Settings -> Physics 2D

        RaycastMeta meta = new RaycastMeta(rayOrigin, direction, hit, rayLength, positionIndex);

#if UNITY_EDITOR
        if (this.DebugProps.On) {
            if (positionIndex == 0)
                Debug.DrawRay(meta.Origin, meta.FullDir, DebugProps.First);
            else
                Debug.DrawRay(meta.Origin, meta.FullDir, DebugProps.NoHit);
            if (hit)
                Debug.DrawRay(meta.Origin, meta.FullDir, DebugProps.Hit);
        }
#endif

        return meta;
    }//Raycast
Beispiel #4
0
    }//RaycastMeta


    public void Set(RaycastMeta meta) {
        this.Origin = meta.Origin;
        this.Direction = meta.Direction;
        this.Ray = meta.Ray;
        this.Length = meta.Length;
        this.Angle = meta.Angle;
        this.Index = meta.Index;
    }
    }//HorizontalCollisions


    /// <summary>
    ///  Raycast vertically with respect to deltaMovement.
    /// This should be called every frame.
    /// </summary>
    public void VerticalCollisions(ref Vector3 deltaMovement) {
        float directionY = Mathf.Sign(deltaMovement.y); //current movement direction (up/down)

        if (this.VerticalRayMeta == null || 
                this.VerticalRayMeta.Length != this.Props.VerticalRays)
            this.VerticalRayMeta = new RaycastMeta[this.Props.VerticalRays];

        int numOfHits = 0;
        for (int i = 0; i < this.Props.VerticalRays; i++) {
            RaycastMeta meta = this.CastVerticalRay(deltaMovement.y, i);

            //Update Global ray Meta.
            if(this.VerticalRayMeta[i] == null)
                this.VerticalRayMeta[i] = new RaycastMeta();
            this.VerticalRayMeta[i].Set(meta);

            //if (meta.Ray && meta.Ray.collider.gameObject.GetHashCode() == this.gameObject.GetHashCode()) {
            //    Debug.Log(meta.Ray.collider.gameObject.name);
            //    continue;
            //}

            //---- NO HIT ----
            if (!meta.Ray) {
                if(i == 0) IsFallingThrough = false;   
                continue;
            }

            if (this.Props.IsIgnoreTag(meta.HitTag)) continue;

            bool isPlatformTag = this.Props.IsPlatformTag(meta.HitTag);
            numOfHits++;

            if (IsFallingThrough && isPlatformTag) continue;
            else IsFallingThrough = false;            

            if (directionY > 0)
                if (!IsFallingThrough && isPlatformTag) continue;

            deltaMovement.y = (meta.Ray.distance - SKINWIDTH) * directionY;

            Below = directionY == -1;
            Above = directionY == 1;
        }//for

        if(numOfHits == 0)
            IsFallingThrough = false;
    }//VerticalCollisions
    }//Raycast


    /// <summary>
    ///  Raycast horizontally (left/right) with respect to deltaMovement.
    /// This should be called every frame.
    /// </summary>
    public void HorizontalCollisions(ref Vector3 deltaMovement) {
        float directionX = Mathf.Sign(deltaMovement.x);

        if (this.HorizontalRayMeta == null || 
                this.HorizontalRayMeta.Length != this.Props.HorizontalRays)
            this.HorizontalRayMeta = new RaycastMeta[this.Props.HorizontalRays];

        for (int i = 0; i < this.Props.HorizontalRays; i++) {
            RaycastMeta meta = this.CastHorizontalRay(deltaMovement.x, i);

            if(this.HorizontalRayMeta[i] == null)
                this.HorizontalRayMeta[i] = new RaycastMeta();
            this.HorizontalRayMeta[i].Set(meta);

            //---- NO HIT ----
            if (!meta.Ray) continue;

            //Ignore rayhit for Platforms or Ignorable tags.
            if(this.Props.IsIgnoreTag(meta.HitTag)) continue;
            if(this.Props.IsPlatformTag(meta.HitTag)) continue;

            float slopeAngle = Vector2.Angle(meta.Ray.normal, Vector2.up);
            this.HorizontalRayMeta[i].Angle = slopeAngle;

            if (i == 0 && slopeAngle <= this.Props.ClimbingSlope) {
                float distanceToSlopeStart = 0;
                if (slopeAngle != slopeAngleLastFrame) {
                    distanceToSlopeStart = meta.Ray.distance - SKINWIDTH;
                    deltaMovement.x -= distanceToSlopeStart * directionX;
                }
                ClimbSlope(ref deltaMovement, slopeAngle);
                deltaMovement.x += distanceToSlopeStart * directionX;
            }//if

            if (!IsOnSlope || slopeAngle > this.Props.ClimbingSlope) {
                deltaMovement.x = (meta.Ray.distance - SKINWIDTH) * directionX;

                if (IsOnSlope)
                    deltaMovement.y = Mathf.Tan(currentSlopeAngle * Mathf.Deg2Rad) * Mathf.Abs(deltaMovement.x);

                Left = directionX == -1;
                Right = directionX == 1;
            }//if

            this.HorizontalRayMeta[i].Length = meta.Ray.distance;
        }//for
    }//HorizontalCollisions
Beispiel #7
0
        }//SnapToLadder


        public bool GetActorGrounded(float distance=0) {
            if (this.Actor == null)
                return false;
            if (this.Actor.CollisionDetectionCmp == null)
                return false;

            CollisionDetection cd = this.Actor.CollisionDetectionCmp;
            bool isGrounded = cd.Below || cd.IsOnSlope;
            //Already grounded? No need to cast rays then...
            if(isGrounded)
                return true;

            if(distance != 0) {
                RaycastMeta rayMeta = cd.CastVerticalRay(distance, cd.Props.VerticalRays / 2);
                return rayMeta.Ray;
            }

            return isGrounded;
        }//CheckGround
Beispiel #8
0
    }//Update

    public bool IsOnPlatform()
    {
        //RaycastMeta[] rays = _raycastGround.OnRaycast();
        RaycastMeta rays  = _cd.CastVerticalRay(-1, 2);
        int         index = (int)(rays.Length / 2);

        if (rays == null || !rays.Ray)
        {
            return(false);
        }

        GameObject hittedObj = rays.Ray.transform.gameObject;

        if (hittedObj == null)
        {
            return(false);
        }

        return(hittedObj.tag.ToLower().Equals(PlatformTag.ToLower()));
    }//IsOnPlatform
    }//InitComponents

    /// <summary>
    ///  Cast multiple rays from center of the sphere to its radius + SkinWidth.
    /// TODO: some useful docs here.
    /// </summary>
    public virtual RaycastMeta[] OnRaycast()
    {
        Vector2 start  = RayOrigin + Offset; //Bottom right corner
        float   length = RayLength;

        this.RayHits = new RaycastMeta[NumberOfRays];

        bIsOnSlope = false;
        for (int i = 0; i < this.NumberOfRays; i++)
        {
            Vector2 rayOrigin = start;
            rayOrigin -= RayDirectionPlacement * (GetRaySpacing() * i);

            var ray = Physics2D.Raycast(rayOrigin, RayDirection, length, CollisionLayer);

            //Saving Ray meta for future use outside of this for loop.
            //Not important for actualy circular raycasting.
            RaycastMeta rayMeta = new RaycastMeta {
                Origin    = start,
                Direction = RayDirection,
                Length    = ray.distance,
                Index     = i,
                Ray       = ray,
                Angle     = Vector2.SignedAngle(ray.normal, Vector2.up)
            };

            this.RayHits[i] = rayMeta;

            Color debugColor = DebugColors.NoHit;
            if (DebugColors.On)
            {
                if (i == 0)
                {
                    debugColor = DebugColors.First;
                }
                if (i == NumberOfRays - 1)
                {
                    debugColor = DebugColors.Last;
                }
            }
            //No soup for this ray.
            if (!ray || ray.collider.gameObject == this.gameObject)
            {
                this.RayHits[i].Angle = 0;
                if (DebugColors.On)
                {
                    Debug.DrawRay(rayOrigin, RayDirection * length, debugColor);
                }
                continue;
            }//if not ray

            if (!bIsOnSlope && rayMeta.Angle != 0)
            {
                if (i < this.NumberOfRays / 2)
                {
                    bIsOnSlope = true;
                }
                //numOfRaysOnSlope++;
            }

            if (DebugColors.On)
            {
                Debug.DrawRay(rayOrigin, RayDirection * ray.distance, DebugColors.Hit); //use red to indicate collision
            }

            if (ray.collider.gameObject != this.gameObject)
            {
                HasCollision = !bIsOnSlope;
            }
        }//for

        return(this.RayHits);
    }//CircularRaycast