Example #1
0
    protected override void GeneratePath()
    {
        CEdgeCastInfo info = m_ControlledCollider.GetEdgeCastInfo();

        m_Path.Clear();
        CapsuleTransform copy = m_ControlledCollider.GetCapsuleTransformCopy();

        //First node is in edgehang alignment, moving away from the edge mildly
        CapsuleMovementPathNode newNode = m_Path.CreateFirstNode(copy);
        Vector3 upCenter = info.GetProposedHeadPoint();

        upCenter += m_ControlledCollider.GetEdgeCastInfo().GetWallNormal() * 0.03f;
        copy.SetUpCenter(upCenter);
        copy.Rotate(info.GetUpDirection(), RotateMethod.FromTop);
        newNode = m_Path.DuplicateAndAddLastNode();
        newNode.CopyFromTransform(copy);

        //Second node moves up along local up, until the bottom can slide over the edge
        newNode            = m_Path.DuplicateAndAddLastNode();
        newNode.m_Duration = m_MoveUpTime;
        float contactDot  = Vector3.Dot(info.GetEdgeNormal(), info.GetEdgePoint());
        float bottomDot   = Vector3.Dot(info.GetEdgeNormal(), copy.GetDownCenter()) - m_ControlledCollider.GetRadius() - m_MoveUpMargin;
        float normalDot   = Vector3.Dot(info.GetEdgeNormal(), copy.GetUpDirection());
        float rawDistance = contactDot - bottomDot;
        float distance    = rawDistance / normalDot;

        newNode.m_Position += copy.GetUpDirection() * distance;
        newNode.ApplyEntireMovement(copy);
        //Third node snaps the capsule to the "upright" position for the ground it's going to stand on
        newNode                = m_Path.DuplicateAndAddLastNode();
        newNode.m_Duration     = 0.0f;
        newNode.m_UpDirection  = (m_CharacterController.GetAlignsToGround()) ? info.GetEdgeNormal() : Vector3.up;
        newNode.m_RotateMethod = RotateMethod.FromBottom;
        newNode.ApplyEntireMovement(copy);
        newNode.m_Position = copy.GetPosition();
        //Final node moves the capsule over the ground
        newNode            = m_Path.DuplicateAndAddLastNode();
        newNode.m_Duration = m_MoveSideTime;
        Vector3 direction = CState.GetDirectionAlongNormal(-info.GetWallNormal(), info.GetEdgeNormal());

        newNode.m_Position += direction * m_MoveSideDistance;
        newNode.ApplyEntireMovement(copy);
    }
Example #2
0
 //Query whether this module can be active, given the current state of the character controller (velocity, isGrounded etc.)
 //Called every frame when inactive (to see if it could be) and when active (to see if it should not be)
 public override bool IsApplicable()
 {
     if (m_ControlledCollider.IsGrounded() || (DoesInputExist("Crouch") && GetButtonInput("Crouch").m_IsPressed) || GetDirInput("Move").m_Direction == DirectionInput.Direction.Down || m_CharacterController.DidJustJump())
     {
         return(false);
     }
     //Prevent overriding walljumps
     if (GetDirInput("Move").IsInThisDirection(m_ControlledCollider.GetEdgeCastInfo().GetWallNormal()))
     {
         return(false);
     }
     if ((m_CharacterController.GetJumpIsCached()) && m_ControlledCollider.IsTouchingEdge())
     {
         //Move up to avoid transitioning into a wallrun.
         //Also used to prevent small distance jumps.
         CEdgeCastInfo    edgeInfo = m_ControlledCollider.GetEdgeCastInfo();
         CapsuleTransform copy     = m_ControlledCollider.GetCapsuleTransformCopy();
         Vector3          headStartDisplacement = edgeInfo.GetEdgeNormal() * (m_ControlledCollider.GetRadius() + 0.1f) + edgeInfo.GetWallNormal() * 0.015f;
         if (!copy.CanMove(headStartDisplacement, true))
         {
             return(false);
         }
         copy.Move(headStartDisplacement);
         m_ProposedNewPosition = copy.GetPosition();
         return(true);
     }
     return(false);
 }
Example #3
0
    //Query whether this module can be active, given the current state of the character controller (velocity, isGrounded etc.)
    //Called every frame when inactive (to see if it could be) and when active (to see if it should not be)
    public override bool IsApplicable()
    {
        if (!m_IsActive)
        {
            //Character can't touch ground, has to touch edge and might be disabled if it is moving upwards
            if (m_ControlledCollider.IsGrounded())
            {
                return(false);
            }
            if (!m_ControlledCollider.IsTouchingEdge())
            {
                return(false);
            }
            CEdgeCastInfo info = m_ControlledCollider.GetEdgeCastInfo();
            if (GetDirInput("Move").m_Direction == DirectionInput.Direction.Up || GetDirInput("Move").IsInThisDirection(-info.GetWallNormal()))
            {
                float angle = Vector3.Angle(info.GetEdgeNormal(), Vector3.up);
                if (angle >= m_ControlledCollider.GetMaxGroundedAngle())
                {
                    return(false);
                }

                GeneratePath();
                if (m_Path.IsPossible(m_ControlledCollider.GetCapsuleTransform()))
                {
                    return(true);
                }
            }
        }
        else
        {
            //If the referencepoint slope is too steep to cling on to (during motion), interrupt movement
            float angle = Vector3.Angle(m_ReferencePoint.m_Transform.up, Vector3.up);
            if (angle >= m_ControlledCollider.GetMaxGroundedAngle())
            {
                return(false);
            }
            if (m_WasInterrupted)
            {
                return(false);
            }
            if (Time.time - m_StartTime >= m_Path.GetTotalTime() || m_Path.IsDone())
            {
                return(false);
            }
            return(true);
        }
        return(false);
    }