Пример #1
0
    private bool HasWallCollided(out SuperCollision superCollision)
    {
        foreach (var col in controller.collisionData)
        {
            if (Vector3.Angle(col.normal, controller.up) > 80.0f)
            {
                superCollision = col;
                return(true);
            }
        }

        superCollision = new SuperCollision();
        return(false);
    }
Пример #2
0
    private bool HasFeetCollided(out SuperCollision superCollision)
    {
        foreach (var col in controller.collisionData)
        {
            Vector3 direction = col.point - controller.OffsetPosition(controller.feet.Offset);

            if (Vector3.Angle(direction, controller.down) < 88.0f)
            {
                superCollision = col;
                return(true);
            }
        }

        superCollision = new SuperCollision();
        return(false);
    }
    /// <summary>
    /// Check if any of the CollisionSpheres are colliding with any walkable objects in the world.
    /// If they are, apply a proper pushback and retrieve the collision data
    /// </summary>
    void RecursivePushback(int depth, int maxDepth)
    {
        PushIgnoredColliders();

        bool contact = false;

        foreach (var sphere in spheres)
        {
            foreach (Collider col in Physics.OverlapSphere((SpherePosition(sphere)), radius, Walkable))
            {
                if (col.isTrigger)
                    continue;

                Vector3 position = SpherePosition(sphere);
                Vector3 contactPoint = SuperCollider.ClosestPointOnSurface(col, position, radius);

                if (contactPoint != Vector3.zero)
                {
                    if (debugPushbackMesssages)
                        DebugDraw.DrawMarker(contactPoint, 2.0f, Color.cyan, 0.0f, false);

                    Vector3 v = contactPoint - position;

                    if (v != Vector3.zero)
                    {
                        // Cache the collider's layer so that we can cast against it
                        int layer = col.gameObject.layer;

                        col.gameObject.layer = TemporaryLayerIndex;

                        // Check which side of the normal we are on
                        bool facingNormal = Physics.SphereCast(new Ray(position, v.normalized), TinyTolerance, v.magnitude + TinyTolerance, 1 << TemporaryLayerIndex);

                        col.gameObject.layer = layer;

                        // Orient and scale our vector based on which side of the normal we are situated
                        if (facingNormal)
                        {
                            if (Vector3.Distance(position, contactPoint) < radius)
                            {
                                v = v.normalized * (radius - v.magnitude) * -1;
                            }
                            else
                            {
                                // A previously resolved collision has had a side effect that moved us outside this collider
                                continue;
                            }
                        }
                        else
                        {
                            v = v.normalized * (radius + v.magnitude);
                        }

                        contact = true;

                        transform.position += v;

                        col.gameObject.layer = TemporaryLayerIndex;

                        // Retrieve the surface normal of the collided point
                        RaycastHit normalHit;

                        Physics.SphereCast(new Ray(position + v, contactPoint - (position + v)), TinyTolerance, out normalHit, 1 << TemporaryLayerIndex);

                        col.gameObject.layer = layer;

                        SuperCollisionType superColType = col.gameObject.GetComponent<SuperCollisionType>();

                        if (superColType == null)
                            superColType = defaultCollisionType;

                        // Our collision affected the collider; add it to the collision data
                        var collision = new SuperCollision()
                        {
                            collisionSphere = sphere,
                            superCollisionType = superColType,
                            gameObject = col.gameObject,
                            point = contactPoint,
                            normal = normalHit.normal
                        };

                        collisionData.Add(collision);
                    }
                }
            }
        }

        PopIgnoredColliders();

        if (depth < maxDepth && contact)
        {
            RecursivePushback(depth + 1, maxDepth);
        }
    }
    /// <summary>
    /// Check if any of the CollisionSpheres are colliding with any walkable objects in the world.
    /// If they are, apply a proper pushback and retrieve the collision data
    /// </summary>
    void RecursivePushback(int depth, int maxDepth)
    {
        PushIgnoredColliders();

        bool contact = false;

        foreach (var sphere in spheres)
        {
            foreach (Collider col in Physics.OverlapSphere((SpherePosition(sphere)), radius, Walkable, triggerInteraction))
            {
                Vector3 position = SpherePosition(sphere);
                Vector3 contactPoint;
                bool    contactPointSuccess = SuperCollider.ClosestPointOnSurface(col, position, radius, out contactPoint);

                if (!contactPointSuccess)
                {
                    return;
                }

                if (debugPushbackMesssages)
                {
                    DebugDraw.DrawMarker(contactPoint, 2.0f, Color.cyan, 0.0f, false);
                }

                Vector3 v = contactPoint - position;
                if (v != Vector3.zero)
                {
                    // Cache the collider's layer so that we can cast against it
                    int layer = col.gameObject.layer;

                    col.gameObject.layer = TemporaryLayerIndex;

                    // Check which side of the normal we are on
                    bool facingNormal = Physics.SphereCast(new Ray(position, v.normalized), TinyTolerance, v.magnitude + TinyTolerance, 1 << TemporaryLayerIndex);

                    col.gameObject.layer = layer;

                    // Orient and scale our vector based on which side of the normal we are situated
                    if (facingNormal)
                    {
                        if (Vector3.Distance(position, contactPoint) < radius)
                        {
                            v = v.normalized * (radius - v.magnitude) * -1;
                        }
                        else
                        {
                            // A previously resolved collision has had a side effect that moved us outside this collider
                            continue;
                        }
                    }
                    else
                    {
                        v = v.normalized * (radius + v.magnitude);
                    }

                    contact = true;

                    transform.position += v;

                    col.gameObject.layer = TemporaryLayerIndex;

                    // Retrieve the surface normal of the collided point
                    RaycastHit normalHit;

                    Physics.SphereCast(new Ray(position + v, contactPoint - (position + v)), TinyTolerance, out normalHit, 1 << TemporaryLayerIndex);

                    col.gameObject.layer = layer;

                    SuperCollisionType superColType = col.gameObject.GetComponent <SuperCollisionType>();

                    if (superColType == null)
                    {
                        superColType = defaultCollisionType;
                    }

                    // Our collision affected the collider; add it to the collision data
                    var collision = new SuperCollision()
                    {
                        collisionSphere    = sphere,
                        superCollisionType = superColType,
                        gameObject         = col.gameObject,
                        point  = contactPoint,
                        normal = normalHit.normal
                    };

                    collisionData.Add(collision);
                }
            }
        }

        PopIgnoredColliders();

        if (depth < maxDepth && contact)
        {
            RecursivePushback(depth + 1, maxDepth);
        }
    }
    void Fall_SuperUpdate()
    {
        //TODO:
        //Input interpreting
        //Take camera position into account when determining if wall run shoud start?
        //Bumbing off the ceiling
        //Is the extra frame/s for wallrunning needed?

        //Rope
        CreateAndDeleteRope();

        //For reducing falsely interpreted input
        lastMoveInputs.Add(input.Current.MoveInput);
        //Seems to be always the last two frames

        if (lastMoveInputs.Count > 10)
        {
            lastMoveInputs.RemoveAt(0);
        }

        Vector3 sum     = Vector3.zero;
        Vector3 average = Vector3.zero;

        foreach (Vector3 v in lastMoveInputs)
        {
            sum += v;
        }

        average = sum / lastMoveInputs.Count;

        if (lastMoveInputs[lastMoveInputs.Count - 1].magnitude == 0)//Edit this to check final inputs to see if they differ from intended
        {
            average = Vector3.zero;
        }

        lastLocalMoves.Add(LocalMovement());

        if (lastLocalMoves.Count > 10)
        {
            lastLocalMoves.RemoveAt(0);
        }

        Vector3 sum2     = Vector3.zero;
        Vector3 average2 = Vector3.zero;

        foreach (Vector3 v in lastLocalMoves)
        {
            sum2 += v;
        }

        average2 = sum / lastLocalMoves.Count;

        if (lastLocalMoves[lastLocalMoves.Count - 1].magnitude == 0)//Edit this to check final inputs to see if they differ from intended
        {
            average2 = Vector3.zero;
        }

        //Horizontal and vertical components
        Vector3 planarMoveDirection   = Math3d.ProjectVectorOnPlane(controller.up, moveDirection);
        Vector3 verticalMoveDirection = moveDirection - planarMoveDirection;

        //Are we touching anything?
        if (controller.collisionData.Count > 0 || previousFirstCollision.gameObject != null)
        {
            if (controller.collisionData.Count > 0)
            {
                collisionNormal = controller.collisionData[0].normal;
                collisionPoint  = controller.collisionData[0].point;
            }
            else
            {
                collisionNormal = previousFirstCollision.normal;
                collisionPoint  = previousFirstCollision.point;
            }

            if (previousFirstCollision.gameObject)
            {
                print(controller.collisionData.Count + "and" + previousFirstCollision.gameObject.name);
            }

            if (controller.collisionData.Count > 1)
            {
                //print("how many colliders? " + controller.collisionData.Count);

                //foreach (SuperCollision col in controller.collisionData)
                //{
                //    print("type: "+col.superCollisionType+ "object: "+ col.gameObject + "normal: "+ col.normal);
                //}
            }

            //Walljump
            if (input.Current.JumpInput && jumpCount <= maxJumpCount && canWallJump)
            {
                isWallJumping = true;
                Gravity       = originalGravity;
                WalkSpeed     = originalWalkspeed;

                if (walkSpeedAtJump > originalWalkspeed)
                {
                    WalkSpeed = walkSpeedAtJump;
                }

                if (reducedTime > 0)
                {
                    print("does this even");
                    JumpAcceleration = reducedJumpAcceleration;
                }
                else
                {
                    JumpAcceleration = originalJumpAcceleration;
                }

                currentState = PlayerStates.Jump;
                return;
            }

            float steepAngle = Vector3.Angle(Vector3.up, collisionNormal);
            float jumpAngle  = Vector3.Angle(planarMoveDirection, collisionNormal);

            print("steepangle: " + steepAngle);

            //Wallrun
            if (110f >= steepAngle && steepAngle >= 55.1f && jumpAngle <= 155f && canWallRun)
            {
                if (isWallRunning == false)
                {
                    print("wallrun started at" + Time.timeSinceLevelLoad);
                    if (verticalMoveDirection.y < 0)
                    {
                        verticalMoveDirection.y = 4;
                    }

                    jumpCount            = 1;
                    planarMoveDirection *= 2f;
                }

                isWallRunning = true;
                Gravity       = 0;
            }

            if (steepAngle < 15f)
            {
                print("steepangle < 15f");
                WalkSpeed     = 0;
                moveDirection = planarMoveDirection;
                previousPlanarMovedirection = Vector3.zero;
                currentState = PlayerStates.Idle;
                return;
            }

            if (steepAngle > 160f)
            {
                print("steepangle > 160f");
                WalkSpeed     = 0;
                moveDirection = planarMoveDirection;
                previousPlanarMovedirection = Vector3.zero;
                currentState = PlayerStates.Fall;
                return;
            }
        }
        else
        {
            if (isWallRunning)
            {
                print("stopped wallrun");
                planarMoveDirection *= 0.5f;
            }

            isWallRunning = false;
            Gravity       = originalGravity;
            WalkSpeed     = originalWalkspeed + momentum;

            if (walkSpeedAtJump > originalWalkspeed)
            {
                WalkSpeed = walkSpeedAtJump + momentum;
            }

            if (reducedTime > 0)
            {
                JumpAcceleration = reducedJumpAcceleration;
            }
            else
            {
                JumpAcceleration = originalJumpAcceleration;
            }

            //Double jump and beyond
            if (input.Current.JumpInput && jumpCount < maxJumpCount)
            {
                if (moveDirection.y < 0)
                {
                    moveDirection.y = 0;
                }

                currentState = PlayerStates.Jump;
                return;
            }
        }

        if (Vector3.Angle(verticalMoveDirection, controller.up) > 90 && AcquiringGround())
        {
            moveDirection = planarMoveDirection;
            previousPlanarMovedirection = Vector3.zero;
            currentState = PlayerStates.Idle;
            return;
        }

        //Wallrun speed
        if (isWallRunning)
        {
            WalkSpeed        = originalWalkspeed + extraWallRunSpeed + momentum;
            JumpAcceleration = originalJumpAcceleration + extraWallRunJumpAcceleration;
        }
        else
        {
            WalkSpeed = originalWalkspeed + momentum;

            if (walkSpeedAtJump > originalWalkspeed || (walkSpeedAtJump > 0 && walkSpeedAtJump < originalWalkspeed))
            {
                WalkSpeed = walkSpeedAtJump + momentum;
            }

            JumpAcceleration = originalJumpAcceleration;

            //IF WE WANT TO STOP FAST IN THE AIR
            //if (LocalMovement().magnitude == 0)
            //{
            //    WalkSpeed = walkSpeedAtJump + momentum;
            //}
        }

        //Do we have LocalMovement caused by input etc
        if (LocalMovement().magnitude > 0)
        {
            //WalkSpeed = originalWalkspeed;
            if (isWallRunning)
            {
                //WalkSpeed = originalWalkspeed + extraWallRunSpeed * 2;
                //JumpAcceleration = originalJumpAcceleration * 3;
            }
            else
            {
                WalkSpeed = originalWalkspeed + momentum;

                if (walkSpeedAtJump > originalWalkspeed || (walkSpeedAtJump > 0 && walkSpeedAtJump < originalWalkspeed))
                {
                    WalkSpeed = walkSpeedAtJump;
                }

                if (reducedTime > 0)
                {
                    JumpAcceleration = reducedJumpAcceleration;
                }
                else
                {
                    JumpAcceleration = originalJumpAcceleration;
                }
            }

            if (walkSpeedAtJump > originalWalkspeed)
            {
                WalkSpeed = walkSpeedAtJump + momentum;
            }

            if (isWallRunning == false)
            {
                planarMoveDirection = Vector3.MoveTowards(planarMoveDirection, LocalMovement() * WalkSpeed, JumpAcceleration * controller.deltaTime);
            }
        }
        else
        {
            if (isWallRunning == false)
            {
                planarMoveDirection = Vector3.MoveTowards(planarMoveDirection, planarMoveDirection.normalized * WalkSpeed, JumpAcceleration * controller.deltaTime);
            }

            if (controller.collisionData.Count == 0)
            {
                if (WalkSpeed - WalkSpeed * 0.01f > 0)
                {
                    WalkSpeed -= WalkSpeed * 0.01f;
                }
            }
        }

        if (isWallRunning)
        {
            WalkSpeed        = originalWalkspeed + extraWallRunSpeed + momentum;
            JumpAcceleration = originalJumpAcceleration * 2;

            float angle = Vector3.Angle(planarMoveDirection, collisionNormal);
            print("angle: " + angle);

            //Wallrun direction
            if (angle >= 90f)
            {
                Vector3 tempPlanarMoveDirection = Math3d.ProjectVectorOnPlane(controller.up, collisionPoint) + (planarMoveDirection * WalkSpeed - Math3d.ProjectVectorOnPlane(controller.up, collisionPoint)) - Math3d.ProjectVectorOnPlane(controller.up, collisionNormal) * Vector3.Dot((planarMoveDirection * WalkSpeed - Math3d.ProjectVectorOnPlane(controller.up, collisionPoint)), Math3d.ProjectVectorOnPlane(controller.up, collisionNormal));
                angle = Vector3.Angle(tempPlanarMoveDirection, collisionNormal);

                print("temp planar dir: " + tempPlanarMoveDirection + " normal: " + collisionNormal + " angle after: " + angle);

                if (angle >= 90f)
                {
                    tempPlanarMoveDirection = Quaternion.AngleAxis(-(angle - 90f - 1f), Vector3.up) * tempPlanarMoveDirection;

                    float angle2 = angle;

                    angle = Vector3.Angle(tempPlanarMoveDirection, collisionNormal);

                    print("angle if over or equal 90: " + angle);

                    if (angle >= 91.9f)
                    {
                        tempPlanarMoveDirection = Quaternion.AngleAxis(((angle2 - 90f) * 2f - 2f), Vector3.up) * tempPlanarMoveDirection;
                        angle = Vector3.Angle(tempPlanarMoveDirection, collisionNormal);
                    }
                }
                else
                {
                    tempPlanarMoveDirection = Quaternion.AngleAxis((90f - angle + 1f), Vector3.up) * tempPlanarMoveDirection;

                    float angle2 = angle;

                    angle = Vector3.Angle(tempPlanarMoveDirection, collisionNormal);

                    print("angle if under 90: " + angle);

                    if (angle <= 90f)
                    {
                        tempPlanarMoveDirection = Quaternion.AngleAxis(-((90f - angle2) * 2f + 2f), Vector3.up) * tempPlanarMoveDirection;
                        angle = Vector3.Angle(tempPlanarMoveDirection, collisionNormal);
                    }
                }

                planarMoveDirection = Vector3.MoveTowards(planarMoveDirection, tempPlanarMoveDirection.normalized * WalkSpeed, JumpAcceleration * controller.deltaTime);
            }
            else
            {
                planarMoveDirection = Vector3.MoveTowards(planarMoveDirection, planarMoveDirection.normalized * WalkSpeed, JumpAcceleration * controller.deltaTime);
            }

            verticalMoveDirection -= controller.up * wallRunGravity * controller.deltaTime;
        }
        else
        {
            verticalMoveDirection -= controller.up * Gravity * controller.deltaTime;
        }

        moveDirection = planarMoveDirection + verticalMoveDirection;

        if (LocalMovement().magnitude > 0)
        {
            previousNonZeroLocalMovement = LocalMovement();
        }

        previousNonZeroAverageLocalMovement = average2;

        previousPlanarMovedirection = planarMoveDirection;

        if (controller.collisionData.Count > 0)
        {
            previousFirstCollision = controller.collisionData[0];
        }
        else
        {
            if (previousFirstCollision.gameObject)
            {
                previousFirstCollision.gameObject = null;
            }
        }
    }