Пример #1
0
    private bool AttemptReground()
    {
        int maxSize = 5;

        bool prevQueriesHitTriggers = Physics2D.queriesHitTriggers;

        Physics2D.queriesHitTriggers = false;

        RaycastHit2D[] hits = new RaycastHit2D[maxSize];
        int            numHits;

        if ((numHits = capCol.Cast(Vector2.down, hits, stepMax)) > 0)
        {
            Physics2D.queriesHitTriggers = prevQueriesHitTriggers;

            if (numHits > maxSize)
            {
                numHits = maxSize;
            }

            float distance = stepMax;
            foreach (RaycastHit2D hit in hits)
            {
                if (hit.distance < distance && hit.distance != 0)
                {
                    distance = hit.distance;
                }
            }

            Vector2 slopeNormal = Vector2.zero;
            foreach (RaycastHit2D hit in hits)
            {
                if (hit.distance > distance)
                {
                    break;
                }

                if (CheckGroundableSlope(hit.normal))
                {
                    slopeNormal += hit.normal;
                }
            }
            slopeNormal.Normalize();

            if (slopeNormal != Vector2.zero)
            {
                HandleReground(mover.Move(distance * Vector2.down), slopeFromNormal(slopeNormal));

                return(true);
            }
            else
            {
                return(false);
            }
        }
        else
        {
            return(false);
        }
    }
Пример #2
0
    // Update is called once per frame
    void Update()
    {
        if (!isAlive)
        {
            return;
        }

        if (playerFeetCollider != null && playerLowerBodyCollider)
        {
            // Suprisingly this is the simplest way I could find to tell if we are on the ground
            // We cast the foot collider down and then catch up to 10 things it hits
            // If one of them have a tag of ground, then we know we are on or at least very close to the ground
            castFeetCollisions = new RaycastHit2D[ARRAY_LENGTH];
            playerFeetCollider.Cast(Vector2.down, castFeetCollisions, .05f);

            castLowerBodyCollisions = new RaycastHit2D[ARRAY_LENGTH];
            playerLowerBodyCollider.Cast(Vector2.down, castLowerBodyCollisions, .05f);

            for (int i = 0; i < ARRAY_LENGTH; i++)
            {
                if ((castFeetCollisions[i].collider != null && castFeetCollisions[i].collider.tag == "Ground") ||
                    (castLowerBodyCollisions[i].collider != null && castLowerBodyCollisions[i].collider.tag == "Ground"))
                {
                    isOnTheGround = true;
                    break;
                }
                else
                {
                    isOnTheGround = false;
                }
            }
        }

        // Handle Horizontal Movement
        float xMovement = Input.GetAxisRaw("Horizontal");

        if (xMovement > .2f)
        {
            if (currentAction != Actions.Walking)
            {
                playerAnimator.SetBool("IsWalking", true);
                currentAction = Actions.Walking;
            }

            if (rb2d.velocity.x < MAX_VELOCITY)
            {
                rb2d.AddForce(Vector2.right * xMovement * Time.deltaTime * MOVEMENT_SPEED);
            }

            if (playerRenderer.flipX)
            {
                playerRenderer.flipX = false;
            }
        }
        else if (xMovement < -.2f)
        {
            if (currentAction != Actions.Walking)
            {
                playerAnimator.SetBool("IsWalking", true);
                currentAction = Actions.Walking;
            }

            if (rb2d.velocity.x > -MAX_VELOCITY)
            {
                rb2d.AddForce(Vector2.right * xMovement * Time.deltaTime * MOVEMENT_SPEED);
            }

            if (!playerRenderer.flipX)
            {
                playerRenderer.flipX = true;
            }
        }
        else
        {
            if (currentAction != Actions.Standing)
            {
                playerAnimator.SetBool("IsWalking", false);
                currentAction = Actions.Standing;
            }

            if (isOnTheGround)                                // Stop the player from sliding on the ground
            {
                rb2d.velocity = Vector2.up * rb2d.velocity.y; // We still should hold onto vertical velocity
            }
        }

        // Handle Vertical Movement
        float jumpMovement = Input.GetAxis("Jump");

        timeSinceLastJump += Time.deltaTime;

        if (jumpMovement > .5 && isOnTheGround && timeSinceLastJump > JUMP_COOLDOWN)
        {
            // Erase any negative vertical velocity, but keep the horizontal velocity
            if (rb2d.velocity.y < 0)
            {
                rb2d.velocity = Vector2.right * rb2d.velocity.x;
            }

            rb2d.AddForce(Vector2.up * JUMP_FORCE);
            isOnTheGround     = false;
            timeSinceLastJump = 0;
        }
    }
Пример #3
0
        protected void UpdateGroundDetection(float deltaTime)
        {
            // Ground Check
            WasGrounded = IsGrounded;
            FSMController.Fsm.GetFsmBool("isGroundedFSM").Value = IsGrounded = false;
            Vector2 dir = Vector2.down;

            RaycastHit2D[] hits = new RaycastHit2D[4];
            capsuleCollider.Cast(dir, hits, _skinWidth);
            for (int i = 0; i < hits.Length; i++)
            {
                if (hits[i].collider == null)
                {
                    break;
                }
                var go = hits[i].collider.attachedRigidbody
                    ? hits[i].collider.attachedRigidbody.gameObject
                    : hits[i].collider.gameObject;
                if (go != this.gameObject)
                {
                    var point = hits[i].point;
                    var norm  = hits[i].normal;

                    var dot   = Vector2.Dot(Vector2.up, norm);
                    var angle = Mathf.Rad2Deg * Mathf.Acos(dot);
                    CurrentSlopeAngle = angle;
                    if (angle < _slopeLimit)
                    {
                        Debug.DrawLine(point, point + norm, Color.cyan, 0.5f);
                        FSMController.Fsm.GetFsmBool("isGroundedFSM").Value = IsGrounded = true;
                        CurrentGroundNormal = norm;
                        break;
                    }
                    else
                    {
                        Debug.DrawLine(point, point + norm, Color.magenta, 0.5f);
                    }
                }
            }
            if (WasGrounded != IsGrounded)
            {
                if (IsGrounded)
                {
                    OnBecomeGrounded();
                }
                else
                {
                    OnBecomeUngrounded();
                }
            }
            // Ceiling Check
            WasOnCeiling = IsOnCeiling;
            IsOnCeiling  = false;
            dir          = Vector2.up;
            hits         = new RaycastHit2D[4];
            capsuleCollider.Cast(dir, hits, _skinWidth);
            for (int i = 0; i < hits.Length; i++)
            {
                if (hits[i].collider == null)
                {
                    break;
                }
                var go = hits[i].collider.attachedRigidbody
                    ? hits[i].collider.attachedRigidbody.gameObject
                    : hits[i].collider.gameObject;
                if (go != this.gameObject)
                {
                    var dot   = Vector2.Dot(Vector2.down, hits[i].normal); // Angle against ceiling downward
                    var angle = Mathf.Rad2Deg * Mathf.Acos(dot);
                    if (angle < _ceilingSlopeLimit)
                    {
                        IsOnCeiling = true;
                        break;
                    }
                }
            }
        }