示例#1
0
        /// <summary>
        ///
        /// </summary>
        public void ProcessMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            if (!_surfer.moveData.underwater)
            {
                if (_surfer.moveData.velocity.y <= 0f)
                {
                    jumping = false;
                }

                // apply gravity
                if (_surfer.groundObject == null)
                {
                    _surfer.moveData.velocity.y -= (_surfer.moveData.gravityFactor * _config.gravity * _deltaTime);
                    _surfer.moveData.velocity.y += _surfer.baseVelocity.y * _deltaTime;
                }

                // input velocity, check for ground
                CheckGrounded();
                CalculateMovementVelocity();
            }
            else
            {
                // Do underwater logic
                UnderwaterPhysics();
            }

            float yVel = _surfer.moveData.velocity.y;

            _surfer.moveData.velocity.y = 0f;
            _surfer.moveData.velocity   = Vector3.ClampMagnitude(_surfer.moveData.velocity, _config.maxVelocity);
            speed = _surfer.moveData.velocity.magnitude;
            _surfer.moveData.velocity.y = yVel;

            float   maxDistPerFrame   = 1f;
            Vector3 velocityThisFrame = _surfer.moveData.velocity * _deltaTime;
            float   velocityDistLeft  = velocityThisFrame.magnitude;
            float   initialVel        = velocityDistLeft;

            while (velocityDistLeft > 0f)
            {
                float amountThisLoop = Mathf.Min(maxDistPerFrame, velocityDistLeft);
                velocityDistLeft -= amountThisLoop;

                // increment origin
                Vector3 velThisLoop = velocityThisFrame * (amountThisLoop / initialVel);
                _surfer.moveData.origin += velThisLoop;

                // don't penetrate walls
                SurfPhysics.ResolveCollisions(_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce);
            }

            _surfer.moveData.groundedTemp = _surfer.moveData.grounded;

            _surfer = null;
        }
示例#2
0
        ///// Methods /////

        /// <summary>
        ///
        /// </summary>
        public void ProcessMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            // apply gravity
            if (_surfer.GroundObject == null)
            {
                _surfer.MoveData.Velocity.y -= (_surfer.MoveData.GravityFactor * _config.Gravity * _deltaTime);
                _surfer.MoveData.Velocity.y += _surfer.BaseVelocity.y * _deltaTime;
            }

            // input velocity, check for ground
            CheckGrounded();
            CalculateMovementVelocity();

            // increment origin
            _surfer.MoveData.Origin += _surfer.MoveData.Velocity * _deltaTime;

            // don't penetrate walls
            SurfPhysics.ResolveCollisions(_surfer.Collider, ref _surfer.MoveData.Origin, ref _surfer.MoveData.Velocity);

            _surfer = null;
        }
示例#3
0
        ///// Methods /////

        public static void ResolveCollisions(ISurfControllable controller, StrictCollisionAxis axis = StrictCollisionAxis.None)
        {
            var staticOrigin = controller.MoveData.Origin + new Vector3(0, controller.Collider.bounds.extents.y, 0);
            var numOverlaps  = Physics.OverlapBoxNonAlloc(staticOrigin, controller.Collider.bounds.extents, _colliders,
                                                          controller.Orientation, GroundLayerMask, QueryTriggerInteraction.Ignore);

            for (int i = 0; i < numOverlaps; i++)
            {
                if (Physics.ComputePenetration(controller.Collider, controller.MoveData.Origin,
                                               controller.Orientation, _colliders[i], _colliders[i].transform.position,
                                               _colliders[i].transform.rotation, out Vector3 direction, out float distance))
                {
                    // don't resolve if moving away from it
                    if (Vector3.Dot(direction, controller.MoveData.Velocity.normalized) > 0)
                    {
                        continue;
                    }

                    var penetrationVec = direction * distance;
                    var velocityVec    = -Vector3.Project(controller.MoveData.Velocity, -direction);

                    if (axis != StrictCollisionAxis.None)
                    {
                        var horizAdjustment = (Mathf.Abs(penetrationVec.x) + Mathf.Abs(penetrationVec.z)) > Mathf.Abs(penetrationVec.y);
                        if ((axis == StrictCollisionAxis.Horizontal && horizAdjustment) ||
                            (axis == StrictCollisionAxis.Vertical && !horizAdjustment))
                        {
                            controller.MoveData.Origin += penetrationVec;
                            if (controller.MoveData.Surfing)
                            {
                                ClipVelocity(controller.MoveData.Velocity, direction, ref controller.MoveData.Velocity, 1.0f);
                            }
                            else
                            {
                                controller.MoveData.Velocity += velocityVec;
                            }
                        }
                        continue;
                    }

                    controller.MoveData.Origin += penetrationVec;
                    staticOrigin += penetrationVec;
                    if (controller.MoveData.Surfing)
                    {
                        ClipVelocity(controller.MoveData.Velocity, direction, ref controller.MoveData.Velocity, distance);
                    }
                    else
                    {
                        controller.MoveData.Velocity += velocityVec;
                    }
                }
            }
        }
示例#4
0
        public static void Reflect(ISurfControllable surfer, float deltaTime, Vector3 hitNormal)
        {
            var workingVel = surfer.MoveData.JustGrounded
                ? surfer.MoveData.PreGroundedVelocity
                : surfer.MoveData.Velocity;

            workingVel += surfer.MoveData.BaseVelocity;

            if (hitNormal.y <= SurfSlope ||
                hitNormal.y >= 1)
            {
                return;
            }

            ClipVelocity(workingVel, hitNormal, ref workingVel, 1f);

            workingVel -= surfer.MoveData.BaseVelocity;
            surfer.MoveData.Velocity = workingVel;
        }
示例#5
0
        public void CalculateMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            _surfer.MoveData.JustGrounded = false;
            _surfer.MoveData.JustJumped   = false;

            if (surfer.MoveData.LimitedExecution)
            {
                CalculateSyncMovement();
            }
            else
            {
                CheckParameters();
                CalculateFullMovement();
            }

            _surfer = null;
            _config = null;
        }
        public void Crouch(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            if (_surfer == null)
            {
                return;
            }

            if (_surfer.collider == null)
            {
                return;
            }

            bool grounded      = _surfer.groundObject != null;
            bool wantsToCrouch = _surfer.moveData.crouching;

            float crouchingHeight  = Mathf.Clamp(_surfer.moveData.crouchingHeight, 0.01f, 1f);
            float heightDifference = _surfer.moveData.defaultHeight - _surfer.moveData.defaultHeight * crouchingHeight;

            if (grounded)
            {
                uncrouchDown = false;
            }

            // Crouching input
            if (grounded)
            {
                crouchLerp = Mathf.Lerp(crouchLerp, wantsToCrouch ? 1f : 0f,
                                        _deltaTime * _surfer.moveData.crouchingSpeed);
            }
            else if (!grounded && !wantsToCrouch && crouchLerp < 0.95f)
            {
                crouchLerp = 0f;
            }
            else if (!grounded && wantsToCrouch)
            {
                crouchLerp = 1f;
            }

            // Collider and position changing
            if (crouchLerp > 0.9f && !crouching)
            {
                // Begin crouching
                crouching = true;
                if (_surfer.collider.GetType() == typeof(BoxCollider))
                {
                    // Box collider
                    BoxCollider boxCollider = (BoxCollider)_surfer.collider;
                    boxCollider.size = new Vector3(boxCollider.size.x, _surfer.moveData.defaultHeight * crouchingHeight,
                                                   boxCollider.size.z);
                }
                else if (_surfer.collider.GetType() == typeof(CapsuleCollider))
                {
                    // Capsule collider
                    CapsuleCollider capsuleCollider = (CapsuleCollider)_surfer.collider;
                    capsuleCollider.height = _surfer.moveData.defaultHeight * crouchingHeight;
                }

                // Move position and stuff
                _surfer.moveData.origin += heightDifference / 2 * (grounded ? Vector3.down : Vector3.up);
                foreach (Transform child in playerTransform)
                {
                    if (child == _surfer.moveData.viewTransform)
                    {
                        continue;
                    }

                    child.localPosition = new Vector3(child.localPosition.x, child.localPosition.y * crouchingHeight,
                                                      child.localPosition.z);
                }

                uncrouchDown = !grounded;
            }
            else if (crouching)
            {
                // Check if the player can uncrouch
                bool canUncrouch = true;
                if (_surfer.collider.GetType() == typeof(BoxCollider))
                {
                    // Box collider
                    BoxCollider boxCollider = (BoxCollider)_surfer.collider;
                    Vector3     halfExtents = boxCollider.size * 0.5f;
                    Vector3     startPos    = boxCollider.transform.position;
                    Vector3     endPos      = boxCollider.transform.position +
                                              (uncrouchDown ? Vector3.down : Vector3.up) * heightDifference;

                    Trace trace = Tracer.TraceBox(startPos, endPos, halfExtents, boxCollider.contactOffset,
                                                  SurfPhysics.groundLayerMask);

                    if (trace.hitCollider != null)
                    {
                        canUncrouch = false;
                    }
                }
                else if (_surfer.collider.GetType() == typeof(CapsuleCollider))
                {
                    // Capsule collider
                    CapsuleCollider capsuleCollider = (CapsuleCollider)_surfer.collider;
                    Vector3         point1          = capsuleCollider.center + Vector3.up * capsuleCollider.height * 0.5f;
                    Vector3         point2          = capsuleCollider.center + Vector3.down * capsuleCollider.height * 0.5f;
                    Vector3         startPos        = capsuleCollider.transform.position;
                    Vector3         endPos          = capsuleCollider.transform.position +
                                                      (uncrouchDown ? Vector3.down : Vector3.up) * heightDifference;

                    Trace trace = Tracer.TraceCapsule(point1, point2, capsuleCollider.radius, startPos, endPos,
                                                      capsuleCollider.contactOffset, SurfPhysics.groundLayerMask);

                    if (trace.hitCollider != null)
                    {
                        canUncrouch = false;
                    }
                }

                // Uncrouch
                if (canUncrouch && crouchLerp <= 0.9f)
                {
                    crouching = false;
                    if (_surfer.collider.GetType() == typeof(BoxCollider))
                    {
                        // Box collider
                        BoxCollider boxCollider = (BoxCollider)_surfer.collider;
                        boxCollider.size = new Vector3(boxCollider.size.x, _surfer.moveData.defaultHeight,
                                                       boxCollider.size.z);
                    }
                    else if (_surfer.collider.GetType() == typeof(CapsuleCollider))
                    {
                        // Capsule collider
                        CapsuleCollider capsuleCollider = (CapsuleCollider)_surfer.collider;
                        capsuleCollider.height = _surfer.moveData.defaultHeight;
                    }

                    // Move position and stuff
                    _surfer.moveData.origin += heightDifference / 2 * (uncrouchDown ? Vector3.down : Vector3.up);
                    foreach (Transform child in playerTransform)
                    {
                        child.localPosition = new Vector3(child.localPosition.x,
                                                          child.localPosition.y / crouchingHeight, child.localPosition.z);
                    }
                }

                if (!canUncrouch)
                {
                    crouchLerp = 1f;
                }
            }

            // Changing camera position
            if (!crouching)
            {
                _surfer.moveData.viewTransform.localPosition = Vector3.Lerp(
                    _surfer.moveData.viewTransformDefaultLocalPos,
                    _surfer.moveData.viewTransformDefaultLocalPos * crouchingHeight +
                    Vector3.down * heightDifference * 0.5f, crouchLerp);
            }
            else
            {
                _surfer.moveData.viewTransform.localPosition = Vector3.Lerp(
                    _surfer.moveData.viewTransformDefaultLocalPos - Vector3.down * heightDifference * 0.5f,
                    _surfer.moveData.viewTransformDefaultLocalPos * crouchingHeight, crouchLerp);
            }
        }
        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);
            }
        }
        ///// Methods /////

        /// <summary>
        ///
        /// </summary>
        /// <param name="collider"></param>
        /// <param name="origin"></param>
        /// <param name="velocity"></param>
        /// http://www.00jknight.com/blog/unity-character-controller

        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;

            if (collider is CapsuleCollider)
            {
                var capc = collider as CapsuleCollider;

                Vector3 point1, point2;
                GetCapsulePoints(capc, origin, out point1, out point2);

                numOverlaps = Physics.OverlapCapsuleNonAlloc(point1, point2, capc.radius,
                                                             _colliders, groundLayerMask, QueryTriggerInteraction.Ignore);
            }
            else if (collider is BoxCollider)
            {
                numOverlaps = Physics.OverlapBoxNonAlloc(origin, collider.bounds.extents, _colliders,
                                                         Quaternion.identity, groundLayerMask, QueryTriggerInteraction.Ignore);
            }

            Vector3 forwardVelocity = Vector3.Scale(velocity, new Vector3(1f, 0f, 1f));

            for (int i = 0; i < numOverlaps; i++)
            {
                Vector3 direction;
                float   distance;

                if (Physics.ComputePenetration(collider, origin,
                                               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;
                    Vector3 velocityProjected = Vector3.Project(velocity, -direction);
                    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 <Rigidbody> ();
                    if (rb != null && !rb.isKinematic)
                    {
                        rb.AddForceAtPosition(velocityProjected * velocityMultiplier * rigidbodyPushForce, origin, ForceMode.Impulse);
                    }
                }
            }
        }
示例#9
0
        /// <summary>
        ///
        /// </summary>
        public void ProcessMovement(ISurfControllable surfer, MovementConfig config, float deltaTime)
        {
            // cache instead of passing around parameters
            _surfer    = surfer;
            _config    = config;
            _deltaTime = deltaTime;

            if (_surfer.moveData.laddersEnabled && !_surfer.moveData.climbingLadder)
            {
                // Look for ladders
                LadderCheck(new Vector3(1f, 0.95f, 1f), _surfer.moveData.velocity * Mathf.Clamp(Time.deltaTime * 2f, 0.025f, 0.25f));
            }

            if (_surfer.moveData.laddersEnabled && _surfer.moveData.climbingLadder)
            {
                LadderPhysics();
            }
            else if (!_surfer.moveData.underwater)
            {
                if (_surfer.moveData.velocity.y <= 0f)
                {
                    jumping = false;
                }

                // apply gravity
                if (_surfer.groundObject == null)
                {
                    _surfer.moveData.velocity.y -= (_surfer.moveData.gravityFactor * _config.gravity * _deltaTime);
                    _surfer.moveData.velocity.y += _surfer.baseVelocity.y * _deltaTime;
                }

                // input velocity, check for ground
                CheckGrounded();
                CalculateMovementVelocity();
            }
            else
            {
                // Do underwater logic
                UnderwaterPhysics();
            }

            float yVel = _surfer.moveData.velocity.y;

            _surfer.moveData.velocity.y = 0f;
            _surfer.moveData.velocity   = Vector3.ClampMagnitude(_surfer.moveData.velocity, _config.maxVelocity);
            speed = _surfer.moveData.velocity.magnitude;
            _surfer.moveData.velocity.y = yVel;

            if (_surfer.moveData.velocity.sqrMagnitude == 0f)
            {
                // Do collisions while standing still
                SurfPhysics.ResolveCollisions(_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce, _surfer.collider.transform.localPosition, 1f, _surfer.moveData.stepOffset, _surfer);
            }
            else
            {
                float   maxDistPerFrame   = 0.2f;
                Vector3 velocityThisFrame = _surfer.moveData.velocity * _deltaTime;
                float   velocityDistLeft  = velocityThisFrame.magnitude;
                float   initialVel        = velocityDistLeft;
                while (velocityDistLeft > 0f)
                {
                    float amountThisLoop = Mathf.Min(maxDistPerFrame, velocityDistLeft);
                    velocityDistLeft -= amountThisLoop;

                    // increment origin
                    Vector3 velThisLoop = velocityThisFrame * (amountThisLoop / initialVel);
                    _surfer.moveData.origin += velThisLoop;

                    // don't penetrate walls
                    SurfPhysics.ResolveCollisions(_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce, _surfer.collider.transform.localPosition, amountThisLoop / initialVel, _surfer.moveData.stepOffset, _surfer);
                }
            }

            _surfer.moveData.groundedTemp = _surfer.moveData.grounded;

            _surfer = null;
        }
示例#10
0
        public static void Reflect(ISurfControllable surfer, float deltaTime)
        {
            var workingVel = surfer.MoveData.JustGrounded
                ? surfer.MoveData.PreGroundedVelocity
                : surfer.MoveData.Velocity;

            workingVel += surfer.MoveData.BaseVelocity;
            var clipped = false;

            //if (contactOffset != 0)
            //{
            //    var longSide = Mathf.Sqrt(contactOffset * contactOffset + contactOffset * contactOffset);
            //    distance += longSide;
            //    extents *= (1f - contactOffset);
            //}

            //var center = surfer.MoveData.Origin + new Vector3(0, surfer.Collider.bounds.extents.y, 0);
            //var end = center + (Vector3.down * 0.2f) + (workingVel * deltaTime);
            //var dist = Vector3.Distance(center, end);
            //var dir = (end - center).normalized;

            var center = surfer.MoveData.Origin + new Vector3(0, surfer.Collider.bounds.extents.y + 0.1f, 0);
            var dist   = 0.2f;
            var dir    = (Vector3.down + (workingVel * deltaTime)).normalized;
            //var dir = (Vector3.down + (workingVel * deltaTime)).normalized;

            var hitCount = Physics.BoxCastNonAlloc(results: _hits,
                                                   center: center,
                                                   direction: dir,
                                                   orientation: surfer.Orientation,
                                                   maxDistance: dist,
                                                   halfExtents: surfer.Collider.bounds.extents,
                                                   layerMask: GroundLayerMask,
                                                   queryTriggerInteraction: QueryTriggerInteraction.Ignore);

            for (int i = 0; i < hitCount; i++)
            {
                if (Tracer.HitIsShit(_hits[i]) ||
                    _hits[i].collider == null)
                {
                    continue;
                }

                if (_hits[i].normal.y <= SurfSlope ||
                    _hits[i].normal.y >= 1)
                {
                    continue;
                }

                var slopeDir          = Vector3.Cross(Vector3.up, Vector3.Cross(Vector3.up, _hits[i].normal));
                var dot               = Vector3.Dot(workingVel.normalized, slopeDir);
                var goingAgainstSlope = dot > 0;

                if (!goingAgainstSlope)
                {
                    continue;
                }

                ClipVelocity(workingVel, _hits[i].normal, ref workingVel, 1f);
                clipped = true;
            }

            workingVel -= surfer.MoveData.BaseVelocity;

            if (clipped)
            {
                surfer.MoveData.Velocity = workingVel;
            }

            //var oldVelocityMagnitude2d = new Vector2(surfer.MoveData.Velocity.x, surfer.MoveData.Velocity.z).magnitude;

            //

            //var newVelocityMagnitude2d = new Vector2(surfer.MoveData.Velocity.x, surfer.MoveData.Velocity.z).magnitude;
            //float fLateralStoppingAmount = oldVelocityMagnitude2d - newVelocityMagnitude2d;
            //Debug.Log(fLateralStoppingAmount);
        }