protected virtual void Update()
        {
            if (m_deltaLadderJumpTimeThreshold > 0f)
            {
                m_deltaLadderJumpTimeThreshold -= Time.deltaTime;
            }
            DoClimbing();

            if (!m_isClimbing)
            {
                // Jumping Action
                if (GetActionState(eControllerActions.Jump))
                {
                    bool jumpActionDown = GetIfActionHasChanged(eControllerActions.Jump);
                    int  wallPushFactor = 0;
                    if (jumpActionDown && !IsGrounded)
                    {
                        wallPushFactor = m_smartCollider.SkinRightRayContacts.Contains(true) ? -1 : m_smartCollider.SkinLeftRayContacts.Contains(true) ? 1 : 0;
                        if (transform.localScale.x < 0)
                        {
                            wallPushFactor = -wallPushFactor;
                        }
                    }
                    //wall jump
                    if (jumpActionDown && !IsGrounded && (m_jumpingAdditionalParameters.wallJumps < 0 || m_jumpingAdditionalParameters.wallJumps > m_wallJumpsCounter) &&
                        m_smartCollider.SkinRightRayContacts.Contains(true) || m_smartCollider.SkinLeftRayContacts.Contains(true))    // isMovingAgainstAWall
                    {
                        ++m_wallJumpsCounter;
                        ++m_airJumpsCounter;
                        m_jumpingTimer           = JumpingAccTime;
                        m_platformPhysics.VSpeed = JumpingSpeed;
                        m_platformPhysics.HSpeed = wallPushFactor * m_jumpingAdditionalParameters.wallPushSpeed;
                    }
                    //air jump
                    else if (jumpActionDown && !IsGrounded && (m_jumpingAdditionalParameters.airJumps < 0 || m_jumpingAdditionalParameters.airJumps > m_airJumpsCounter))
                    {
                        ++m_airJumpsCounter;
                        m_jumpingTimer           = JumpingAccTime;
                        m_platformPhysics.VSpeed = JumpingSpeed;
                    }
                    // ground jump
                    else if (
                        IsGrounded &&
                        //GetIfActionHasChanged(eControllerActions.Jumping) && //NOTE: if not commented, player needs to release and press jump to jump
                        m_jumpingTimer == -1 //NOTE: if not commented, player jumps only once if holding jumping while in air
                        )
                    {
                        m_jumpingTimer           = JumpingAccTime;
                        m_platformPhysics.VSpeed = JumpingSpeed;
                        m_isGrounded             = false;
                    }
                }
                else if (!GetActionState(eControllerActions.Jump))
                {
                    m_jumpingTimer = -1f;
                }

                // Moving Action
                if (GetActionState(eControllerActions.Right))
                {
                    m_platformPhysics.AddAcceleration(Vector2.right * HorizontalMovingAcc * m_horSpeedScale);
                }
                if (GetActionState(eControllerActions.Left))
                {
                    m_platformPhysics.AddAcceleration(-Vector2.right * HorizontalMovingAcc * m_horSpeedScale);
                }

                // Platform Drop Down Action
                if (m_isGrounded && m_platformDropTimer <= 0f && GetActionState(eControllerActions.PlatformDropDown))
                {
                    //NOTE: for this to work, OneWayCollisionDown should be removed from LayerCollisions
                    m_smartCollider.LayerCollision      = m_smartCollider.LayerCollision & ~m_smartCollider.OneWayCollisionDown;
                    m_smartCollider.OneWayCollisionDown = 0;
                    m_platformDropTimer = PlatformDropTime;
                }

                // Jumping
                if (m_jumpingTimer > 0f)
                {
                    m_jumpingTimer -= Time.deltaTime;
                    m_platformPhysics.Acceleration += transform.up * m_jumpingAcc;
                }

                // Platform Drop Down
                if (m_platformDropTimer > 0f)
                {
                    m_platformDropTimer -= Time.deltaTime;
                    if (m_platformDropTimer <= 0f)
                    {   // Restore the One Way Down collision again after the time is over
                        m_smartCollider.OneWayCollisionDown = m_savedOneWayCollisionDown;
                    }
                }
                m_instantVelocity           = (transform.position - m_prevPos) / Time.deltaTime;
                m_prevPos                   = transform.position;
                m_platformPhysics.Drag      = new Vector2(m_walkingDrag, 0f);
                m_platformPhysics.MaxHSpeed = MaxWalkingSpeed * m_horSpeedScale;
                m_platformPhysics.Position  = transform.position;
                m_platformPhysics.UpdatePhysics(Time.deltaTime);
                m_groundDist = _CalculateGroundDist();
                bool wasGrounded = m_isGrounded;
                m_isGrounded = m_smartCollider.enabled && m_smartCollider.IsGrounded() && m_platformPhysics.DeltaDisp.y <= 0f;

                // NOTE: Unity 5.4 has a bug in TransformDirection being affected by scale (x is negated to flip the sprite).
                // So instead of calling TransformDirection I will rotate it directly.
                transform.position = transform.position + transform.rotation * (m_platformPhysics.Position - transform.position);

                //+++ Do slopes
                // If over a slope, move the character in the slope direction
                if (m_slopeAngle != 0f)
                {
                    if (Mathf.Abs(m_slopeAngle) <= Mathf.Round(m_maxSlope))
                    {
                        transform.position += transform.up * m_platformPhysics.DeltaDisp.x * Mathf.Tan(m_slopeAngle * Mathf.Deg2Rad);
                        m_isGrounded        = true;
                    }
                    else if (Mathf.Sign(m_slopeAngle) == Mathf.Sign(m_platformPhysics.DeltaDisp.x))
                    {
                        // Avoid climbing up the slope
                        transform.position       = m_platformPhysics.Position = new Vector3(m_prevPos.x, transform.position.y, transform.position.z);
                        m_platformPhysics.HSpeed = 0f;
                        m_isGrounded             = true;
                    }
                }
                // if not over a slope, check if there is a slope under the character to place it to the ground
                else if (!m_isGrounded && wasGrounded && m_platformPhysics.DeltaDisp.y <= 0f)
                {
                    m_groundDist = _CalculateGroundDist();
                    float magneticDist = Mathf.Abs(m_platformPhysics.DeltaDisp.x * Mathf.Tan((m_maxSlope) * Mathf.Deg2Rad));
                    if (m_groundDist <= magneticDist)
                    {
                        m_isGrounded        = true;
                        m_groundDist       += SmartRectCollider2D.k_SkinMinWidth;
                        transform.position += -transform.up * m_groundDist;
                    }
                }
                if (m_isGrounded)
                {
                    m_wallJumpsCounter = m_airJumpsCounter = 0;
                }
                m_slopeAngle = 0f;
                //---
            }

            //Update Actions
            m_actionChanged   = m_prevActionFlags ^ m_actionFlags;
            m_prevActionFlags = m_actionFlags;
        }
Ejemplo n.º 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
            {
            }
        }