public bool CanApplyEntireMovement(CapsuleTransform a_Transform)
 {
     if (a_Transform.GetPosition() != m_Position)
     {
         if (!a_Transform.CanMove(m_Position - a_Transform.GetPosition(), true))
         {
             return(false);
         }
     }
     if (a_Transform.GetUpDirection() != m_UpDirection)
     {
         if (!a_Transform.CanRotate(m_UpDirection, m_RotateMethod))
         {
             return(false);
         }
     }
     if (a_Transform.GetLength() != m_Length)
     {
         if (!a_Transform.CanBeResized(m_Length, m_ResizeMethod))
         {
             return(false);
         }
     }
     return(true);
 }
    //Calld by GroundedAnimatedAbilityModule to move a capsuletransform along the path
    public void ApplyMotion(CapsuleTransform a_Transform, float a_Time)
    {
        if (m_CurrentPathNode == null)
        {
            return;
        }
        if (m_CurrentIndex == 0)
        {
            m_CurrentPathNode.ApplyEntireMovement(a_Transform);
            return;
        }
        if (m_CurrentPathNode.m_Duration == 0)
        {
            m_CurrentPathNode.ApplyEntireMovement(a_Transform);
        }
        else
        {
            float factor = Mathf.Clamp01(a_Time / m_CurrentPathNode.m_Duration);

            CapsuleMovementPathNode newPoint = new CapsuleMovementPathNode();
            newPoint.InterpolationBetweenTwoNodes(m_PathNodes[m_CurrentIndex - 1], m_CurrentPathNode, factor);

            newPoint.ApplyEntireMovement(a_Transform);
        }
    }
Esempio n. 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_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);
 }
 //Apply the final transform state (when exiting the path)
 public void ApplyFinalNode(CapsuleTransform a_Transform)
 {
     if (m_PathNodes.Count == 0)
     {
         return;
     }
     m_PathNodes[m_PathNodes.Count - 1].ApplyEntireMovement(a_Transform);
 }
Esempio n. 5
0
    public CapsuleTransform CreateCopy()
    {
        CapsuleTransform copy = new CapsuleTransform();

        copy.OverrideValues(this);
        copy.m_IsCopy = true;
        return(copy);
    }
    //Creation functions for the path
    public CapsuleMovementPathNode CreateFirstNode(CapsuleTransform a_Transform)
    {
        CapsuleMovementPathNode node = new CapsuleMovementPathNode();

        node.CopyFromTransform(a_Transform);
        AddNode(node);
        m_CurrentPathNode = node;
        m_CurrentIndex    = 0;
        return(node);
    }
Esempio n. 7
0
    public void OverrideValues(CapsuleTransform a_ToCopyFrom)
    {
        m_CapsuleCollider  = a_ToCopyFrom.m_CapsuleCollider;
        m_Position         = a_ToCopyFrom.m_Position;
        m_UpDirection      = a_ToCopyFrom.m_UpDirection;
        m_Length           = a_ToCopyFrom.m_Length;
        m_LastResizeMethod = a_ToCopyFrom.m_LastResizeMethod;

        if (!m_IsCopy && m_CapsuleCollider != null)
        {
            m_CapsuleCollider.transform.position = m_Position;
            m_CapsuleCollider.transform.rotation = GetRotation();
        }
    }
 public void ApplyEntireMovement(CapsuleTransform a_Transform)
 {
     if (a_Transform.GetPosition() != m_Position)
     {
         a_Transform.SetPosition(m_Position);
     }
     if (a_Transform.GetUpDirection() != m_UpDirection)
     {
         a_Transform.Rotate(m_UpDirection, m_RotateMethod);
     }
     if (a_Transform.GetLength() != m_Length)
     {
         a_Transform.SetLength(m_Length, m_ResizeMethod);
     }
 }
    //Check if the entire path can be applied
    public bool IsPossible(CapsuleTransform a_Transform)
    {
        CapsuleTransform transform  = a_Transform.CreateCopy();
        bool             isPossible = true;

        for (int i = 0; i < m_PathNodes.Count; i++)
        {
            if (m_PathNodes[i].CanApplyEntireMovement(transform))
            {
                m_PathNodes[i].ApplyEntireMovement(transform);
            }
            else
            {
                return(false);
            }
        }
        return(isPossible);
    }
Esempio n. 10
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);
    }
Esempio n. 11
0
    //Apply a capsule transform to the actual collider object. Update contextual information
    public void ApplyCapsuleTransform(CapsuleTransform a_CapsuleTransform)
    {
        m_CapsuleTransform.OverrideValues(a_CapsuleTransform);

        UpdateContextInfo();
    }
Esempio n. 12
0
    //Called for every fixedupdate that this module is active
    public override void FixedUpdateModule()
    {
        float currentTransitionTime = Time.time - m_TransitionStartTime;

        //A MovingColPoint is used to move and rotate the animation path when the collider it starts on is moved
        //This allows animated abilities to work on moving colliders
        if (m_ReferencePoint != null)
        {
            //Position
            CapsuleTransform copy = m_ControlledCollider.GetCapsuleTransformCopy();
            Vector3          diff = m_ReferencePoint.m_Transform.position - m_ReferencePoint.m_PrevPoint;
            copy.Move(diff);
            m_Path.Move(diff);

            //Rotation
            Quaternion rotationDifference = Quaternion.FromToRotation(m_ReferencePoint.m_PrevRot * Vector3.up, m_ReferencePoint.m_Transform.rotation * Vector3.up);
            copy.Rotate(rotationDifference * copy.GetUpDirection(), RotateMethod.FromCenter);
            m_Path.Rotate(rotationDifference, m_ReferencePoint.m_PrevPoint);

            //Offset for rotation
            Vector3 newRelativePoint   = rotationDifference * m_ReferencePoint.m_PointRelativeToThis;
            Vector3 relativeDifference = newRelativePoint - m_ReferencePoint.m_PointRelativeToThis;

            copy.Move(relativeDifference);

            m_ReferencePoint.m_PrevPoint           = m_ReferencePoint.m_Transform.position;
            m_ReferencePoint.m_PrevRot             = m_ReferencePoint.m_Transform.rotation;
            m_ReferencePoint.m_PointRelativeToThis = m_ReferencePoint.m_Transform.position - m_ControlledCollider.GetCapsuleTransform().GetPosition();
            m_ReferencePoint.m_Normal = Quaternion.FromToRotation(m_ReferencePoint.m_PrevRot * Vector3.up, m_ReferencePoint.m_Transform.rotation * Vector3.up) * m_ReferencePoint.m_Normal;

            if (copy.CanExistHere())
            {
                m_ControlledCollider.ApplyCapsuleTransform(copy);
            }
            else
            {
                m_WasInterrupted = true;
                return;
            }
        }
        m_ControlledCollider.SetVelocity(Vector2.zero);
        //Move along the nodes as long as they can be applied (either they are finished or their duration is 0)
        while (!m_Path.IsDone() && m_Path.m_CurrentPathNode != null && (m_Path.m_CurrentPathNode.m_Duration == 0 || Time.time - m_TransitionStartTime >= m_Path.m_CurrentPathNode.m_Duration))
        {
            if (m_Path.m_CurrentPathNode.CanApplyEntireMovement(m_ControlledCollider.GetCapsuleTransform()))
            {
                m_TransitionStartTime += m_Path.m_CurrentPathNode.m_Duration;
                currentTransitionTime -= m_Path.m_CurrentPathNode.m_Duration;
                m_Path.m_CurrentPathNode.ApplyEntireMovement(m_ControlledCollider.GetCapsuleTransform());
                m_Path.IncrementCurrentNode();
            }
            else
            {
                m_WasInterrupted = true;
                return;
            }
        }
        //Move along the current node
        if (m_Path.CanApplyMotion(m_ControlledCollider.GetCapsuleTransform(), currentTransitionTime))
        {
            m_Path.ApplyMotion(m_ControlledCollider.GetCapsuleTransform(), currentTransitionTime);
        }
        else
        {
            m_WasInterrupted = true;
            return;
        }
        m_ControlledCollider.UpdateContextInfo();
    }
Esempio n. 13
0
 public void CopyFromTransform(CapsuleTransform a_Transform)
 {
     m_Position    = a_Transform.GetPosition();
     m_UpDirection = a_Transform.GetUpDirection();
     m_Length      = a_Transform.GetLength();
 }
Esempio n. 14
0
    //This context uses raycasts to determine if a ledge is present.
    //The raycasts originate from above and to the left/right of the character, and are casted downwards
    public void UpdateWithCollisions()
    {
        RaycastHit rightHit;
        RaycastHit leftHit;
        bool       rightHasHit = false;
        bool       leftHasHit  = false;

        m_HasHitEdge = false;
        Vector3 upCenter       = m_CapsuleCollider.GetUpCenter();
        Vector3 upDirection    = m_CapsuleCollider.GetUpDirection();
        Vector3 transformRight = m_CapsuleCollider.transform.right;
        //Orient against wall to the side, even if not able to wallsliding
        //This allows the character to grab onto ledges on slanted walls
        CSideCastInfo sideInfo = m_CapsuleCollider.GetSideCastInfo();

        if (sideInfo.m_HasHitSide)
        {
            Vector3 sideNormal = sideInfo.GetSideNormal();
            Vector3 sidePoint  = sideInfo.GetSidePoint();
            Vector3 sideUp     = CState.GetDirectionAlongNormal(Vector3.up, sideNormal);

            RaycastHit properSideHit;
            if (Physics.Raycast(sidePoint + sideNormal * 0.2f + sideUp * 0.05f, -sideNormal, out properSideHit, 0.3f, m_CapsuleCollider.GetLayerMask()))
            {
                Vector3 newPoint  = properSideHit.point;
                Vector3 newNormal = properSideHit.normal;
                Vector3 newUp     = CState.GetDirectionAlongNormal(Vector3.up, newNormal);

                Vector3          pivot       = upCenter - newPoint;
                Quaternion       rotation    = Quaternion.FromToRotation(upDirection, newUp);
                Vector3          newUpCenter = newPoint + rotation * pivot;
                CapsuleTransform transform   = m_CapsuleCollider.GetCapsuleTransformCopy();
                transform.SetUpDirection(newUp);
                transform.SetUpCenter(newUpCenter);

                upCenter       = newUpCenter;
                upDirection    = newUp;
                transformRight = transform.GetRightDirection();
            }
        }
        //Determine the starting positions of the raycasts
        Vector3 centerStart = upCenter + upDirection * (m_CapsuleCollider.GetRadius() + m_CapsuleCollider.GetEdgeCastVerticalMargin());
        Vector3 sideOffSet  = transformRight * (m_CapsuleCollider.GetRadius() + m_CapsuleCollider.GetEdgeCastHorizontalDistance());
        Vector3 grabLength  = -upDirection * (m_CapsuleCollider.GetEdgeCastVerticalDistance() + m_CapsuleCollider.GetEdgeCastVerticalMargin());

        //The raycasts originate from above and to the left/right of the character, and are casted downwards
        //The angle of the slope they hit can't be too steep, or the character will slide off.
        if (Physics.Raycast(centerStart + sideOffSet, -upDirection, out rightHit, grabLength.magnitude, m_CapsuleCollider.GetLayerMask()))
        {
            if (Vector3.Angle(rightHit.normal, upDirection) < m_CapsuleCollider.GetMaxGrabAngle())
            {
                rightHasHit = true;
            }
        }
        if (Physics.Raycast(centerStart - sideOffSet, -upDirection, out leftHit, grabLength.magnitude, m_CapsuleCollider.GetLayerMask()))
        {
            if (Vector3.Angle(leftHit.normal, upDirection) < m_CapsuleCollider.GetMaxGrabAngle())
            {
                leftHasHit = true;
            }
        }
        if (rightHasHit || leftHasHit)
        {
            RaycastHit castToUse;
            Vector3    wallProbeDirection;
            if (rightHasHit && leftHasHit)
            {
                if (leftHit.distance < rightHit.distance)
                {
                    castToUse          = leftHit;
                    wallProbeDirection = -transformRight;
                }
                else
                {
                    castToUse          = rightHit;
                    wallProbeDirection = transformRight;
                }
            }
            else if (rightHasHit)
            {
                castToUse          = rightHit;
                wallProbeDirection = transformRight;
            }
            else
            {
                castToUse          = leftHit;
                wallProbeDirection = -transformRight;
            }

            //Check if the character can even hold on. The distance between the character and the start of the raycastpoint should not be blocked by a collider (no grabbing on ledges on the other side of walls
            if (Physics.Raycast(centerStart, wallProbeDirection, m_CapsuleCollider.GetRadius() + m_CapsuleCollider.GetEdgeCastHorizontalDistance(), m_CapsuleCollider.GetLayerMask()))
            {
                return;
            }

            wallProbeDirection = CState.GetDirectionAlongNormal(wallProbeDirection, castToUse.normal);
            //After detecting that collider can hang onto edge, orient properly against surface
            RaycastHit probeHit;
            Vector3    probedNormal = CState.GetDirectionAlongNormal(-wallProbeDirection, Vector3.up);
            if (Physics.Raycast(upCenter, wallProbeDirection, out probeHit, m_CapsuleCollider.GetRadius() + m_CapsuleCollider.GetEdgeAlignProbeDistance(), m_CapsuleCollider.GetLayerMask()))
            {
                float angle = Vector3.Angle(probeHit.normal, Vector3.up);
                if (angle < m_CapsuleCollider.GetMaxEdgeAlignAngle())
                {
                    probedNormal = probeHit.normal;
                }
            }
            Vector3 newUpDirection = CState.GetDirectionAlongNormal(Vector3.up, probedNormal);
            Vector3 headPoint      = castToUse.point + probedNormal * (m_CapsuleCollider.GetRadius() + m_CapsuleCollider.GetEdgeCastHorizontalDistance()) - newUpDirection * m_CapsuleCollider.GetRadius();
            //Block check
            //Check if something is obstructing the proposed headposition (and fix if so)
            RaycastHit blockHit;
            if (Physics.Raycast(headPoint, -probedNormal, out blockHit, m_CapsuleCollider.GetRadius(), m_CapsuleCollider.GetLayerMask()))
            {
                if (blockHit.distance < m_CapsuleCollider.GetRadius())
                {
                    Vector3 alongNormal = -CState.GetDirectionAlongNormal(wallProbeDirection, castToUse.normal);
                    castToUse.point += alongNormal * (m_CapsuleCollider.GetRadius() - blockHit.distance) / Vector3.Dot(alongNormal, blockHit.normal);

                    headPoint = castToUse.point + probedNormal * (m_CapsuleCollider.GetRadius() + m_CapsuleCollider.GetEdgeCastHorizontalDistance()) - newUpDirection * m_CapsuleCollider.GetRadius();
                }
            }

            //Rotation check, check if character is aligned to wall or dangling
            //then check if that rotation can be achieved
            CapsuleTransform copy = m_CapsuleCollider.GetCapsuleTransformCopy();
            copy.SetUpCenter(headPoint);
            if (Vector3.Angle(Vector3.up, probedNormal) > m_CapsuleCollider.GetMaxWallAngle() || Vector3.Angle(Vector3.up, probedNormal) < m_CapsuleCollider.GetMaxGroundedAngle())
            {
                return;
            }

            if (copy.CanRotate(newUpDirection, RotateMethod.FromTop))
            {
                m_EdgePoint            = castToUse.point;
                m_EdgeNormal           = castToUse.normal;
                m_EdgeTransform        = castToUse.transform;
                m_WallNormal           = probedNormal;
                m_UpDirection          = newUpDirection;
                m_ProposedHeadPosition = headPoint;
                m_HasHitEdge           = true;
            }
        }
    }