diff --git a/Modified fragsurf/Movement/MoveData.cs b/Modified fragsurf/Movement/MoveData.cs index 2cf833c..8677d27 100644 --- a/Modified fragsurf/Movement/MoveData.cs +++ b/Modified fragsurf/Movement/MoveData.cs @@ -32,6 +32,8 @@ namespace Fragsurf.Movement { public bool crouching = false; public bool sprinting = false; + public float slopeLimit = 45f; + public float rigidbodyPushForce = 1f; public float defaultHeight = 2f; @@ -48,5 +50,8 @@ namespace Fragsurf.Movement { public bool groundedTemp = false; public float fallingVelocity = 0f; + public bool useStepOffset = false; + public float stepOffset = 0f; + } } diff --git a/Modified fragsurf/Movement/SurfCharacter.cs b/Modified fragsurf/Movement/SurfCharacter.cs index 8a0afeb..7c47a5a 100644 --- a/Modified fragsurf/Movement/SurfCharacter.cs +++ b/Modified fragsurf/Movement/SurfCharacter.cs @@ -38,7 +38,11 @@ namespace Fragsurf.Movement { [Header ("Features")] public bool crouchingEnabled = true; public bool slidingEnabled = false; - + + [Header ("Step offset (can be buggy, enable at your own risk)")] + public bool useStepOffset = false; + public float stepOffset = 0.35f; + [Header ("Movement Config")] [SerializeField] public MovementConfig movementConfig; @@ -179,6 +183,8 @@ namespace Fragsurf.Movement { } + _moveData.slopeLimit = movementConfig.slopeLimit; + _moveData.rigidbodyPushForce = rigidbodyPushForce; _moveData.slidingEnabled = slidingEnabled; @@ -194,7 +200,10 @@ namespace Fragsurf.Movement { _collider.isTrigger = !solidCollider; _moveData.origin = transform.position; _startPosition = transform.position; - + + _moveData.useStepOffset = useStepOffset; + _moveData.stepOffset = stepOffset; + } private void Update () { diff --git a/Modified fragsurf/Movement/SurfController.cs b/Modified fragsurf/Movement/SurfController.cs index 48cda9b..50027b2 100644 --- a/Modified fragsurf/Movement/SurfController.cs +++ b/Modified fragsurf/Movement/SurfController.cs @@ -76,7 +76,8 @@ namespace Fragsurf.Movement { float maxDistPerFrame = 0.05f; Vector3 velocityThisFrame = _surfer.moveData.velocity * _deltaTime; - float velocityDistLeft = velocityThisFrame.magnitude; + float velocityDist = velocityThisFrame.magnitude; + float velocityDistLeft = velocityDist; float initialVel = velocityDistLeft; while (velocityDistLeft > 0f) { @@ -88,7 +89,7 @@ namespace Fragsurf.Movement { _surfer.moveData.origin += velThisLoop; // don't penetrate walls - SurfPhysics.ResolveCollisions (_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce, amountThisLoop / initialVel); + SurfPhysics.ResolveCollisions (_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce, amountThisLoop / velocityDist, _surfer.moveData.useStepOffset ? _surfer.moveData.stepOffset : 0f, _surfer); } diff --git a/Modified fragsurf/Movement/SurfPhysics.cs b/Modified fragsurf/Movement/SurfPhysics.cs index 7f7dd45..9fd5c89 100644 --- a/Modified fragsurf/Movement/SurfPhysics.cs +++ b/Modified fragsurf/Movement/SurfPhysics.cs @@ -29,12 +29,8 @@ namespace Fragsurf.Movement { /// /// /// http://www.00jknight.com/blog/unity-character-controller - - public static void ResolveCollisions (Collider collider, ref Vector3 origin, ref Vector3 velocity, float rigidbodyPushForce) { - ResolveCollisions (collider, ref origin, ref velocity, rigidbodyPushForce, 1f); - } - - public static void ResolveCollisions (Collider collider, ref Vector3 origin, ref Vector3 velocity, float rigidbodyPushForce, float velocityMultiplier) { + + public static void ResolveCollisions (Collider collider, ref Vector3 origin, ref Vector3 velocity, float rigidbodyPushForce, float velocityMultiplier = 1f, float stepOffset = 0f, ISurfControllable surfer = null) { // manual collision resolving int numOverlaps = 0; @@ -55,6 +51,7 @@ namespace Fragsurf.Movement { } + Vector3 forwardVelocity = Vector3.Scale (velocity, new Vector3 (1f, 0f, 1f)); for (int i = 0; i < numOverlaps; i++) { Vector3 direction; @@ -64,6 +61,11 @@ namespace Fragsurf.Movement { Quaternion.identity, _colliders [i], _colliders [i].transform.position, _colliders [i].transform.rotation, out direction, out distance)) { + // Step offset + if (stepOffset > 0f && surfer != null && surfer.moveData.useStepOffset) + if (StepOffset (collider, _colliders [i], ref origin, ref velocity, rigidbodyPushForce, velocityMultiplier, stepOffset, direction, distance, forwardVelocity, surfer)) + return; + // Handle collision direction.Normalize (); Vector3 penetrationVector = direction * distance; @@ -71,18 +73,91 @@ namespace Fragsurf.Movement { velocityProjected.y = 0; // don't touch y velocity, we need it to calculate fall damage elsewhere origin += penetrationVector; velocity -= velocityProjected * velocityMultiplier; - + Rigidbody rb = _colliders [i].GetComponentInParent (); - if (rb) - if (!rb.isKinematic) - rb.AddForceAtPosition (velocityProjected * velocityMultiplier * rigidbodyPushForce, origin, ForceMode.Impulse); - + if (rb != null && !rb.isKinematic) + rb.AddForceAtPosition (velocityProjected * velocityMultiplier * rigidbodyPushForce, origin, ForceMode.Impulse); + } } } + public static bool StepOffset (Collider collider, Collider otherCollider, ref Vector3 origin, ref Vector3 velocity, float rigidbodyPushForce, float velocityMultiplier, float stepOffset, Vector3 direction, float distance, Vector3 forwardVelocity, ISurfControllable surfer) { + + // Return if step offset is 0 + if (stepOffset <= 0f) + return false; + + // Get forward direction (return if we aren't moving/are only moving vertically) + Vector3 forwardDirection = forwardVelocity.normalized; + if (forwardDirection.sqrMagnitude == 0f) + return false; + + // Trace ground + Trace groundTrace = Tracer.TraceCollider (collider, origin, origin + Vector3.down * 0.1f, groundLayerMask); + if (groundTrace.hitCollider == null || Vector3.Angle (Vector3.up, groundTrace.planeNormal) > surfer.moveData.slopeLimit) + return false; + + // Trace wall + Trace wallTrace = Tracer.TraceCollider (collider, origin, origin + velocity, groundLayerMask, 0.9f); + if (wallTrace.hitCollider == null || Vector3.Angle (Vector3.up, wallTrace.planeNormal) <= surfer.moveData.slopeLimit) + return false; + + // Trace upwards (check for roof etc) + float upDistance = stepOffset; + Trace upTrace = Tracer.TraceCollider (collider, origin, origin + Vector3.up * stepOffset, groundLayerMask); + if (upTrace.hitCollider != null) + upDistance = upTrace.distance; + + // Don't bother doing the rest if we can't move up at all anyway + if (upDistance <= 0f) + return false; + + Vector3 upOrigin = origin + Vector3.up * upDistance; + + // Trace forwards (check for walls etc) + float forwardMagnitude = stepOffset; + float forwardDistance = forwardMagnitude; + Trace forwardTrace = Tracer.TraceCollider (collider, upOrigin, upOrigin + forwardDirection * Mathf.Max (0.2f, forwardMagnitude), groundLayerMask); + if (forwardTrace.hitCollider != null) + forwardDistance = forwardTrace.distance; + + // Don't bother doing the rest if we can't move forward anyway + if (forwardDistance <= 0f) + return false; + + Vector3 upForwardOrigin = upOrigin + forwardDirection * forwardDistance; + + // Trace down (find ground) + float downDistance = upDistance; + Trace downTrace = Tracer.TraceCollider (collider, upForwardOrigin, upForwardOrigin + Vector3.down * upDistance, groundLayerMask); + if (downTrace.hitCollider != null) + downDistance = downTrace.distance; + + // Check step size/angle + float verticalStep = Mathf.Clamp (upDistance - downDistance, 0f, stepOffset); + float horizontalStep = forwardDistance; + float stepAngle = Vector3.Angle (Vector3.forward, new Vector3 (0f, verticalStep, horizontalStep)); + if (stepAngle > surfer.moveData.slopeLimit) + return false; + + // Get new position + Vector3 endOrigin = origin + Vector3.up * verticalStep; + + // Actually move + if (origin != endOrigin && forwardDistance > 0f) { + + Debug.Log ("Moved up step!"); + origin = endOrigin + forwardDirection * forwardDistance * Time.deltaTime; + return true; + + } else + return false; + + } + /// /// /// diff --git a/Modified fragsurf/TraceUtil/Trace.cs b/Modified fragsurf/TraceUtil/Trace.cs index 34ed8e5..a963271 100644 --- a/Modified fragsurf/TraceUtil/Trace.cs +++ b/Modified fragsurf/TraceUtil/Trace.cs @@ -10,6 +10,7 @@ namespace Fragsurf.TraceUtil { public Collider hitCollider; public Vector3 hitPoint; public Vector3 planeNormal; + public float distance; } } diff --git a/Modified fragsurf/TraceUtil/Tracer.cs b/Modified fragsurf/TraceUtil/Tracer.cs index 2bfd9e5..a1eb97a 100644 --- a/Modified fragsurf/TraceUtil/Tracer.cs +++ b/Modified fragsurf/TraceUtil/Tracer.cs @@ -11,12 +11,12 @@ namespace Fragsurf.TraceUtil { /// /// /// - public static Trace TraceCollider (Collider collider, Vector3 origin, Vector3 end, int layerMask) { + public static Trace TraceCollider (Collider collider, Vector3 origin, Vector3 end, int layerMask, float colliderScale = 1f) { if (collider is BoxCollider) { // Box collider trace - return TraceBox (origin, end, collider.bounds.extents, collider.contactOffset, layerMask); + return TraceBox (origin, end, collider.bounds.extents, collider.contactOffset, layerMask, colliderScale); } else if (collider is CapsuleCollider) { @@ -26,7 +26,7 @@ namespace Fragsurf.TraceUtil { Vector3 point1, point2; Movement.SurfPhysics.GetCapsulePoints (capc, origin, out point1, out point2); - return TraceCapsule (point1, point2, capc.radius, origin, end, capc.contactOffset, layerMask); + return TraceCapsule (point1, point2, capc.radius, origin, end, capc.contactOffset, layerMask, colliderScale); } @@ -38,7 +38,7 @@ namespace Fragsurf.TraceUtil { /// /// /// - public static Trace TraceCapsule (Vector3 point1, Vector3 point2, float radius, Vector3 start, Vector3 destination, float contactOffset, int layerMask) { + public static Trace TraceCapsule (Vector3 point1, Vector3 point2, float radius, Vector3 start, Vector3 destination, float contactOffset, int layerMask, float colliderScale = 1f) { var result = new Trace () { startPos = start, @@ -52,9 +52,9 @@ namespace Fragsurf.TraceUtil { RaycastHit hit; if (Physics.CapsuleCast ( - point1: point1, - point2: point2, - radius: radius, + point1: point1 - Vector3.up * colliderScale * 0.5f, + point2: point2 + Vector3.up * colliderScale * 0.5f, + radius: radius * colliderScale, direction: direction, hitInfo: out hit, maxDistance: maxDistance, @@ -65,6 +65,7 @@ namespace Fragsurf.TraceUtil { result.hitCollider = hit.collider; result.hitPoint = hit.point; result.planeNormal = hit.normal; + result.distance = hit.distance; } else result.fraction = 1; @@ -77,7 +78,7 @@ namespace Fragsurf.TraceUtil { /// /// /// - public static Trace TraceBox (Vector3 start, Vector3 destination, Vector3 extents, float contactOffset, int layerMask) { + public static Trace TraceBox (Vector3 start, Vector3 destination, Vector3 extents, float contactOffset, int layerMask, float colliderScale = 1f) { var result = new Trace () { startPos = start, @@ -91,7 +92,7 @@ namespace Fragsurf.TraceUtil { RaycastHit hit; if (Physics.BoxCast (center: start, - halfExtents: extents, + halfExtents: extents * colliderScale, direction: direction, orientation: Quaternion.identity, maxDistance: maxDistance, @@ -103,6 +104,7 @@ namespace Fragsurf.TraceUtil { result.hitCollider = hit.collider; result.hitPoint = hit.point; result.planeNormal = hit.normal; + result.distance = hit.distance; } else result.fraction = 1;