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); }
public override void ReceiveContext(object context) { if (!(context is LedgeInfo)) { return; } ledgeInfo = (LedgeInfo)context; }
public override void OnExit(PlayerController player) { player.MaximizeCollider(); player.Anim.SetBool("isAutoGrabbing", false); player.ForceHeadLook = false; ledgeInfo = null; }
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); }
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); }
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); }
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); }
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 }