protected void DoClimbing()
        {
            float fHorAxis = 0f;
            float fVerAxis = 0f;

            if (GetActionState(eControllerActions.Right))
            {
                fHorAxis += m_horSpeedScale;
            }
            if (GetActionState(eControllerActions.Left))
            {
                fHorAxis -= m_horSpeedScale;
            }
            if (GetActionState(eControllerActions.Up))
            {
                fVerAxis += m_verSpeedScale;
            }
            if (GetActionState(eControllerActions.Down))
            {
                fVerAxis -= m_verSpeedScale;
            }
            if (m_isClimbing)
            {
                if (
                    GetIfActionHasChanged(eControllerActions.Jump) && GetActionState(eControllerActions.Jump) ||
                    GetIfActionHasChanged(eControllerActions.PlatformDropDown) && GetActionState(eControllerActions.PlatformDropDown))
                {
                    m_isClimbing = false;
                    m_currentClimbingCollider = null;
                    m_isGrounded = true;
                    return;
                }

                // isLadder is true when the collider width is small enough to avoid moving horizontal and center the player in the center of the collider.
                // By default, it is true when collider width is less than two times the smart rect collider width
                bool isLadder = m_currentClimbingCollider.bounds.size.x < m_ladderWidthFactor * m_smartCollider.Size.x;

                Vector3 vDisp = new Vector3(isLadder ? 0f : fHorAxis, fVerAxis);

                //debug climbing area
                DebugEx.DebugDrawRect(Vector2.zero, new Rect(m_currentClimbingCollider.bounds.min, m_currentClimbingCollider.bounds.size), Color.blue);


                if (isLadder)
                {
                    // Snap to ladder
                    Vector3 center  = m_currentClimbingCollider.bounds.center;
                    Vector3 snapPos = Vector3.Project(transform.position - center, m_currentClimbingCollider.transform.up); // this allow rotated ladders, like in pirate ship demo
                    snapPos           += center;
                    snapPos.z          = transform.position.z;
                    transform.position = Vector3.Lerp(transform.position, snapPos, 0.5f);
                }

                if (vDisp.magnitude > 0.2f)
                {
                    transform.position += transform.rotation * vDisp * ClimbingSpeed * Time.deltaTime;
                }

                m_isGrounded = m_smartCollider.enabled && m_smartCollider.IsGrounded();
            }

            // Check if going down and there is a climbing collider below
            float      SkinBottomWidthFactor = 1.1f; //NOTE: set a value > 1f to allow climbing down when climb collision and platform collision are close
            Collider2D climbingColliderBelow = GetClimbingColliderBelow(SkinBottomWidthFactor);
            Collider2D climbingColliderAbove = GetClimbingColliderAbove();

            if (fVerAxis < -0.5f && m_currentClimbingCollider == null)
            {
                if (climbingColliderBelow != null)
                {
                    if (m_currentClimbingCollider == null && climbingColliderAbove == null)
                    {
                        //Teleport the player. TeleportTo will skip any collider in between the current position and the new position to skip any platform in between
                        m_smartCollider.TeleportTo(transform.position - transform.up * m_smartCollider.SkinBottomWidth * SkinBottomWidthFactor);
                    }
                    m_currentClimbingCollider = climbingColliderBelow;
                    StartClimbing();
                }
                else
                {
                    StopClimbing();
                }
            }
            // Check if going up and it is inside a climbing collider
            else if (fVerAxis > 0.5f)
            {
                if (climbingColliderAbove != null && !GetIfActionHasChanged(eControllerActions.Jump))
                {
                    m_currentClimbingCollider = climbingColliderAbove;
                    StartClimbing();
                }
                else if (m_smartCollider.SkinBottomRayContacts.Contains(true) || climbingColliderBelow == null)
                {
                    StopClimbing();
                }
            }
            // Stop climbing once the top is reached
            else if (m_isGrounded || (climbingColliderBelow == null && climbingColliderAbove == null))
            {
                StopClimbing();
            }
        }
Example #2
0
        void FixedUpdate()
        {
            // Fix an issue when m_isGrounded is always false the first update if SmartRectCollider2D was not updated first
            if (m_skipFirstFixedUpdate)
            {
                m_skipFirstFixedUpdate = false;
                return;
            }

            Vector3 vLocVelocity = transform.rotation != Quaternion.identity ? Quaternion.Inverse(transform.rotation) * m_smartRectCollider.InstantVelocity : m_smartRectCollider.InstantVelocity;

            m_isGrounded = m_smartRectCollider.enabled &&
                           m_smartRectCollider.IsGrounded() &&
                           vLocVelocity.y <= Vector3.kEpsilon;

            if (m_isGrounded)
            {
                m_fallingJumpToleranceTimer = FallingJumpTolerance;
            }

            if (m_isController)
            {
                if (State != eState.Dying)
                {
                    m_spriteRenderer.color = Color.white;

                    VPad.Update();
                    float fHorAxis = VPad.GetAxis("Horizontal");
                    float fVerAxis = VPad.GetAxis("Vertical");

                    // Fix issue when using keys, because the time to go from 0 to 1 or 1 to 0 is too high by default Unity parameters
                    // So if a moving key is pressed, the horizontal axis will be set to the right value directly
                    if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
                    {
                        fHorAxis = 1f;
                    }
                    else if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
                    {
                        fHorAxis = -1f;
                    }
                    //---

                    if (m_isClimbing)
                    {
                        // isLadder is true when the collider width is small enough to avoid moving horizontal and center the player in the center of the collider.
                        // By default, it is true when collider width is less than two times the smart rect collider width
                        bool isLadder = (m_currentClimbingCollider is BoxCollider2D) && ((BoxCollider2D)m_currentClimbingCollider).size.x < 2 * m_smartRectCollider.Size.x;

                        Vector3 vDisp = new Vector3(isLadder ? 0f : fHorAxis, fVerAxis);

                        if (isLadder)
                        {
                            // Snap to ladder
                            BoxCollider2D box2DCollider = (BoxCollider2D)m_currentClimbingCollider;
                            Vector3       center        = box2DCollider.transform.TransformPoint(box2DCollider.offset);
                            Vector3       snapPos       = Vector3.Project(transform.position - center, m_currentClimbingCollider.transform.up); // this allow rotated ladders, like in pirate ship demo
                            snapPos           += center;
                            snapPos.z          = transform.position.z;
                            transform.position = Vector3.Lerp(transform.position, snapPos, 0.5f);
                        }

                        if (vDisp.magnitude > 0.2f)
                        {
                            transform.position += transform.rotation * vDisp * ClimbingSpeed * Time.deltaTime;
                            SetNextState(eState.Climbing);
                        }
                        else
                        {
                            SetNextState(eState.ClimbingIdle);
                        }
                    }
                    else // normal walking
                    {
                        bool isWalking = (Mathf.Abs(fHorAxis) > 0.7f);
                        fHorAxis = Mathf.Sign(fHorAxis) * Mathf.Max(Mathf.Abs(fHorAxis), 0.4f);
                        if (isWalking)
                        {
                            SetNextState(m_isGrounded ? eState.Walking : (m_smartRectCollider.InstantVelocity.y > 0f ? eState.Jumping : eState.Falling));
                            float walkAcc     = fHorAxis > 0 ? WalkAcc : -WalkAcc;
                            float fHorAxisAbs = Mathf.Abs(fHorAxis);
                            if (Mathf.Sign(fHorAxis) != Mathf.Sign(m_walkVeloc.x) && m_walkVeloc.x != 0)
                            {
                                m_walkVeloc.x += walkAcc + walkAcc * WalkReactivity * fHorAxisAbs;
                            }
                            else
                            {
                                m_walkVeloc.x += walkAcc;
                            }
                            float walkSpeed = m_isSwimming ? WalkSpeed / 2 : WalkSpeed;
                            m_walkVeloc.x = Mathf.Clamp(m_walkVeloc.x, -walkSpeed * fHorAxisAbs, walkSpeed * fHorAxisAbs);
                            float movingSign = (IsSpriteFacingRight ? Mathf.Sign(m_walkVeloc.x) : -Mathf.Sign(m_walkVeloc.x));
                            if (movingSign != Mathf.Sign(transform.localScale.x))
                            {
                                Vector3 tempScale = transform.localScale;
                                tempScale.x          = -tempScale.x; // flip player
                                transform.localScale = tempScale;
                            }
                        }
                        else
                        {
                            SetNextState(m_isGrounded ? eState.Idle : (m_smartRectCollider.InstantVelocity.y > 0f ? eState.Jumping : eState.Falling));
                            m_walkVeloc *= Mathf.Clamp01(1 - m_rigidBody2D.drag * Time.deltaTime);
                        }

                        // Apply walk velocity
                        Vector3 locWalkVeloc = transform.rotation != Quaternion.identity ? transform.rotation * m_walkVeloc : m_walkVeloc;
                        transform.position += locWalkVeloc * Time.deltaTime;

                        // Apply jump speed
                        if (m_jumpSpeed > 0f)
                        {
                            Vector3 gravity      = Physics2D.gravity * (m_rigidBody2D.gravityScale == 0f ? 1f : m_rigidBody2D.gravityScale);
                            Vector3 locJumpVeloc = m_jumpSpeed * transform.up;
                            transform.position += locJumpVeloc * Time.deltaTime + 0.5f * gravity * Time.deltaTime * Time.deltaTime;
                            m_jumpSpeed         = Mathf.Max(0f, m_jumpSpeed - (gravity.magnitude + m_rigidBody2D.drag * JumpDragFactor) * Time.deltaTime);
                            if (m_jumpSpeed < Vector3.kEpsilon)
                            {
                                m_jumpSpeed = 0f;
                            }
                        }
                    }

                    // Check if going down and there is a climbing collider below
                    float      SkinBottomWidthFactor = 1.1f; //NOTE: set a value > 1f to allow climbing down when climb collision and platform collision are close
                    Collider2D climbingColliderBelow = GetClimbingColliderBelow(SkinBottomWidthFactor);
                    Collider2D climbingColliderAbove = GetClimbingColliderAbove();
                    if (fVerAxis < -0.5f && m_currentClimbingCollider == null)
                    {
                        if (climbingColliderBelow != null)
                        {
                            if (m_currentClimbingCollider == null)
                            {
                                m_smartRectCollider.TeleportTo(transform.position - transform.up * m_smartRectCollider.SkinBottomWidth * SkinBottomWidthFactor);
                            }
                            m_currentClimbingCollider = climbingColliderBelow;
                            StartClimbing();
                        }
                        else
                        {
                            StopClimbing();
                        }
                    }
                    // Check if going up and it is inside a climbing collider
                    else if (fVerAxis > 0.5f)
                    {
                        if (climbingColliderAbove != null)
                        {
                            m_currentClimbingCollider = climbingColliderAbove;
                            StartClimbing();
                        }
                        else if (m_smartRectCollider.SkinBottomRayContacts.Contains(true) || climbingColliderBelow == null)
                        {
                            StopClimbing();
                        }
                    }
                    // Stop climbing once the top is reached
                    else if (m_isGrounded || (climbingColliderBelow == null && climbingColliderAbove == null))
                    {
                        StopClimbing();
                    }

                    /*/ Used to teleport player to mouse position and test collisions with world
                     * if( Input.GetMouseButton(0) )
                     * {
                     *  Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                     *  pos.z = transform.position.z;
                     *  transform.position = pos;
                     * }
                     * //*/
                }
            }
            else
            {
            }
        }