Beispiel #1
0
    public bool FindPlatformInfront(Vector3 start, Vector3 dir, float maxHeight, out LedgeInfo ledgeInfo, float depth = 0.25f)
    {
        RaycastHit vHit;
        Vector3    vStart = start + (Vector3.up * 2f) + (dir * depth);

        if (Physics.Raycast(vStart, Vector3.down, out vHit, (maxHeight - 0.01f), ~(1 << 8)))
        {
            RaycastHit hHit;
            Vector3    hStart = new Vector3(start.x, vHit.point.y - 0.01f, start.z);

            if (Physics.Raycast(start, dir, out hHit, depth, ~(1 << 8)))
            {
                Vector3 ledgeRight = Vector3.Cross(Vector3.up, hHit.normal);

                float sideAngle    = Vector3.SignedAngle(Vector3.up, vHit.normal, -hHit.normal);
                float forwardAngle = Vector3.SignedAngle(Vector3.up, vHit.normal, ledgeRight);

                // Check that the ledge doesnt slope too much in either direction
                if (Mathf.Abs(sideAngle) < maxRightAngle && Mathf.Abs(forwardAngle) < maxForwardAngle)
                {
                    Vector3 ledgePoint = new Vector3(hHit.point.x, vHit.point.y, hHit.point.z);

                    hStart = ledgePoint - dir * 0.1f + Vector3.up * 1.75f;
                    if (!Physics.Raycast(hStart, dir, 1f))
                    {
                        ledgeInfo = new LedgeInfo(LedgeType.Normal, ledgePoint, -hHit.normal, hHit.collider);
                        return(true);
                    }
                }
            }
        }

        ledgeInfo = new LedgeInfo();
        return(false);
    }
    public static LedgeInfo DetectLedgeOnWall(Direction.Horizontal _direction, Direction.Vertical _verticalDirection, BoxCollider2D _collider, float velocityToCheck, float offset = 0.25f)
    {
        RaycastHit2D raycastHits        = new RaycastHit2D();
        int          collisionLayerMask = 1 << LayerMask.NameToLayer("Terrain");

        float   rayLength    = _collider.size.y + Mathf.Abs(velocityToCheck) + offset;
        Vector2 rayDirection = (_verticalDirection == Direction.Vertical.Up) ? Vector2.up : Vector2.down;
        bool    isConnected  = false;

        Vector2 rayOrigin = new Vector2(_collider.transform.position.x + (_collider.size.x * 0.5f) * (int)_direction, _collider.transform.position.y - (_collider.size.y * 0.5f * (int)_verticalDirection));

        rayOrigin.y = (rayDirection == Vector2.up) ? _collider.bounds.min.y - offset : _collider.bounds.max.y + offset;

        float raycastSpacing = _collider.size.x * 0.5f;

        rayOrigin.x = (_direction == Direction.Horizontal.Left) ? rayOrigin.x - raycastSpacing : rayOrigin.x + raycastSpacing;

        raycastHits = Physics2D.Raycast(rayOrigin, rayDirection, rayLength, collisionLayerMask);
        if (raycastHits.fraction > 0)
        {
            isConnected = true;
        }

                #if UNITY_EDITOR
        //Debug.DrawRay(rayOrigin, new Vector2(0.25f * (int)_direction, (int)rayDirection.y * rayLength), Color.red);
                #endif

        float     hitY      = (isConnected) ? raycastHits.point.y : 0.0f;
        LedgeInfo ledgeInfo = new LedgeInfo();
        ledgeInfo.didHit = isConnected;
        ledgeInfo.hitY   = hitY;

        return(ledgeInfo);
    }
Beispiel #3
0
    public override void ReceiveContext(object context)
    {
        if (!(context is LedgeInfo))
        {
            return;
        }

        ledgeInfo = (LedgeInfo)context;
    }
Beispiel #4
0
    public override void OnExit(PlayerController player)
    {
        player.MaximizeCollider();

        player.Anim.SetBool("isAutoGrabbing", false);
        player.ForceHeadLook = false;

        ledgeInfo = null;
    }
Beispiel #5
0
    private bool FindInnerCorner(PlayerController player, Vector3 dir, out LedgeInfo ledgeInfo)
    {
        Vector3 castFrom = player.transform.position
                           + Vector3.up * (player.HangUpOffset - ledgeDetector.MinDepth)
                           - player.transform.forward * 0.2f;

        if (ledgeDetector.FindLedgeAtPoint(castFrom, dir, 1f, 0.2f, out ledgeInfo))
        {
            return(true);
        }

        return(false);
    }
Beispiel #6
0
    public bool FindLedgeJump(Vector3 start, Vector3 dir, float maxDistance, float maxHeight, out LedgeInfo ledgeInfo, PlayerController player)
    {
        for (float offset = maxHeight - minHeight; offset >= 0f; offset -= minHeight)
        {
            Vector3 rayStart = start + Vector3.up * offset;

            LedgeInfo info;
            if (FindHangableLedge(rayStart, dir, maxDistance, minHeight, out info, player))
            {
                ledgeInfo = info;
                return(true);
            }
        }

        ledgeInfo = new LedgeInfo();
        return(false);
    }
Beispiel #7
0
    public bool FindAboveHead(Vector3 start, Vector3 dir, float maxHeight, out LedgeInfo ledgeInfo)
    {
        RaycastHit hit;

        if (Physics.Raycast(start, dir, out hit, maxHeight, ~(1 << 8), QueryTriggerInteraction.Ignore))
        {
            if (hit.collider.CompareTag("MonkeySwing"))
            {
                ledgeInfo = new LedgeInfo(LedgeType.Monkey, hit.point, Vector3.up, hit.collider);
                return(true);
            }
            else if (hit.collider.CompareTag("HorPole"))
            {
                ledgeInfo = new LedgeInfo(LedgeType.HorPole, hit.point, Vector3.up, hit.collider);
                return(true);
            }
        }

        ledgeInfo = new LedgeInfo();
        return(false);
    }
Beispiel #8
0
    public bool FindLedgeAtPoint(Vector3 start, Vector3 dir, float maxDistance, float deltaHeight, out LedgeInfo ledgeInfo)
    {
        int notPlayerLayer = ~(1 << 8);

        // Horizontal check
        RaycastHit hHit;

        if (!Physics.Raycast(start, dir, out hHit, maxDistance, notPlayerLayer, QueryTriggerInteraction.Ignore))
        {
            goto NoLedge;
        }

        bool isMoving = hHit.collider.CompareTag("MovingPlatform");

        if (hHit.collider.CompareTag("Freeclimb"))
        {
            ledgeInfo = new LedgeInfo(LedgeType.Free, new Vector3(hHit.point.x, start.y, hHit.point.z), -hHit.normal, hHit.collider);
            return(true);
        }

        // Vertical check
        RaycastHit vHit;

        start    = hHit.point + (dir * minDepth);
        start.y += deltaHeight;

        if (!Physics.Raycast(start, Vector3.down, out vHit, deltaHeight, notPlayerLayer, QueryTriggerInteraction.Ignore))
        {
            goto NoLedge;
        }

        // Check angle is shallow enough sideways (think shimmying up when going sideways)
        float angleRight = Vector3.SignedAngle(Vector3.up, vHit.normal, -hHit.normal);

        if (Mathf.Abs(angleRight) > maxRightAngle)
        {
            goto NoLedge;
        }

        // Check angle is shallow enough straight in front (think grabbing bottom of slope)
        Vector3 ledgeRight = Vector3.Cross(Vector3.up, hHit.normal).normalized;

        float angleForward = Vector3.SignedAngle(Vector3.up, vHit.normal, ledgeRight);

        if (angleForward > maxForwardAngle)
        {
            goto NoLedge;
        }

        // Resolve so Lara grabs correct point on a slope
        float offset = minDepth * Mathf.Tan(angleForward * Mathf.Deg2Rad);

        Vector3 ledgePoint = new Vector3(hHit.point.x, vHit.point.y - offset, hHit.point.z);

        // Check minimum depth
        start = ledgePoint + Vector3.up * 0.1f + hHit.normal * 0.2f;
        if (Physics.Raycast(start, -hHit.normal, minDepth + 0.2f, notPlayerLayer, QueryTriggerInteraction.Ignore))
        {
            goto NoLedge;
        }

        ledgeInfo = new LedgeInfo(LedgeType.Normal, ledgePoint, -hHit.normal, hHit.collider);
        return(true);

NoLedge:
        ledgeInfo = new LedgeInfo();
        return(false);
    }
Beispiel #9
0
    public bool FindHangableLedge(Vector3 start, Vector3 dir, float maxDistance, float deltaHeight, out LedgeInfo ledgeInfo, PlayerController player)
    {
        if (FindLedgeAtPoint(start, dir, maxDistance, deltaHeight, out ledgeInfo))
        {
            Vector3 heightCheckStart = ledgeInfo.Point - dir * player.HangForwardOffset;

            // If we hit something that isn't a trigger thats not water then something is blocking

            RaycastHit hit;
            if (Physics.Raycast(heightCheckStart, Vector3.down, out hit, player.HangUpOffset, ~(1 << 8), QueryTriggerInteraction.Collide))
            {
                if (!hit.collider.isTrigger || hit.collider.CompareTag("Water"))
                {
                    return(false);
                }
            }

            // Now check that there is room for Lara's hands on either side (stops her hanging inside a wall)

            Vector3 handCheckStart = ledgeInfo.Point - ledgeInfo.Direction * 0.1f + Vector3.down * (minHeight / 2f);
            Vector3 ledgeRight     = Vector3.Cross(ledgeInfo.Direction, Vector3.up);

            if (!FindLedgeAtPoint(handCheckStart - ledgeRight * player.CharControl.radius, ledgeInfo.Direction, 0.2f, minHeight))
            {
                return(false);
            }

            if (!FindLedgeAtPoint(handCheckStart + ledgeRight * player.CharControl.radius, ledgeInfo.Direction, 0.2f, minHeight))
            {
                return(false);
            }

            return(true);
        }

        return(false);  // No possible ledge even found
    }