Ejemplo n.º 1
0
    private bool FootStrike(out GameObject struckObject)
    {
        struckObject = null;

        float radius = controller.radius;

        Vector3 o = controller.OffsetPosition(controller.feet.Offset);

        Collider[] colliders = Physics.OverlapSphere(o, radius, EnemyLayerMask);

        foreach (var col in colliders)
        {
            var machine = col.gameObject.GetComponent <GoombaMachine>();

            if (machine != null)
            {
                if (!machine.Alive)
                {
                    continue;
                }
            }

            Vector3 closestPoint = SuperCollider.ClosestPointOnSurface(col, o, radius);

            if (SuperMath.PointAbovePlane(controller.down, o, closestPoint))
            {
                struckObject = col.gameObject;
                return(true);
            }
        }

        return(false);
    }
Ejemplo n.º 2
0
    bool PushBack()
    {
        bool isPushedBack = false;

        for (int i = collisionSpheres.Count - 1; i >= 0; i--)
        {
            overlappingColliders = Physics.OverlapSphere(SpherePosition(collisionSpheres[i]), radius, LayersManager.colLayers);

            for (int j = 0; j < overlappingColliders.Length; j++)
            {
                if (overlappingColliders[j] != myCollider)
                {
                    isPushedBack = true;
                    Vector3 position     = SpherePosition(collisionSpheres[i]);                                            // The position of the sphere in world coordinates
                    Vector3 contactPoint = SuperCollider.ClosestPointOnSurface(overlappingColliders[j], position, radius); // The closest point on the collider, named contact point
                    if (contactPoint != Vector3.zero)                                                                      // Contact point was found
                    {
                        Vector3 v = contactPoint - position;                                                               //The direction from the position of the sphere to the contact point

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

                            overlappingColliders[j].gameObject.layer = _temporaryLayerIndex;

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

                            //Set col layer back to its previous layer
                            overlappingColliders[j].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;                                     //The distance needed to move the controller in order to push it out of the collider
                                }
                                else
                                {
                                    // A previously resolved collision has had a side effect that moved us outside this collider
                                    continue;
                                }
                            }
                            else
                            {
                                v = v.normalized * (radius + v.magnitude);       //The distance needed to move the controller in order to push it out of the collider
                            }
                            transform.position += v;                             //Push back controller

                            overlappingColliders[j].gameObject.layer = layer;
                        }
                    }
                }
            }
        }

        return(isPushedBack);
    }
Ejemplo n.º 3
0
    public static Vector3 ClosestPointOnSurface(Collider collider, Vector3 to, float radius)
    {
        if (collider is BoxCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((BoxCollider)collider, to));
        }
        else if (collider is SphereCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((SphereCollider)collider, to));
        }
        else if (collider is CapsuleCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((CapsuleCollider)collider, to));
        }
        else if (collider is MeshCollider)
        {
            BSPTree bsp = collider.GetComponent <BSPTree>();

            if (bsp != null)
            {
                return(bsp.ClosestPointOn(to, radius));
            }

            BruteForceMesh bfm = collider.GetComponent <BruteForceMesh>();

            if (bfm != null)
            {
                return(bfm.ClosestPointOn(to));
            }
        }

        return(Vector3.zero);
    }
Ejemplo n.º 4
0
 // Main collision check
 public GameObject collides(SuperCollider collider, float x, float y, float width, float height)
 {
     if (x + width / 2 > collider.transform.position.x - collider.width / 2 &&
         y + height / 2 > collider.transform.position.y - collider.height / 2 &&
         x - width / 2 <= collider.transform.position.x + collider.width / 2 &&
         y - height / 2 <= collider.transform.position.y + collider.height / 2)
     {
         return(collider.gameObject);
     }
     return(null);
 }
Ejemplo n.º 5
0
    public static bool ClosestPointOnSurface(Collider collider, Vector3 to, float radius, out Vector3 closestPointOnSurface)
    {
        if (collider is BoxCollider)
        {
            closestPointOnSurface = SuperCollider.ClosestPointOnSurface((BoxCollider)collider, to);
            return(true);
        }
        else if (collider is SphereCollider)
        {
            closestPointOnSurface = SuperCollider.ClosestPointOnSurface((SphereCollider)collider, to);
            return(true);
        }
        else if (collider is CapsuleCollider)
        {
            closestPointOnSurface = SuperCollider.ClosestPointOnSurface((CapsuleCollider)collider, to);
            return(true);
        }
        else if (collider is MeshCollider)
        {
            BSPTree bspTree = collider.GetComponent <BSPTree>();

            if (bspTree != null)
            {
                closestPointOnSurface = bspTree.ClosestPointOn(to, radius);
                return(true);
            }

            BSPTree bsp = collider.GetComponent <BSPTree>();

            if (bsp != null)
            {
                closestPointOnSurface = bsp.ClosestPointOn(to, radius);
                return(true);
            }

            BruteForceMesh bfm = collider.GetComponent <BruteForceMesh>();

            if (bfm != null)
            {
                closestPointOnSurface = bfm.ClosestPointOn(to);
                return(true);
            }
        }
        else if (collider is TerrainCollider)
        {
            closestPointOnSurface = SuperCollider.ClosestPointOnSurface((TerrainCollider)collider, to, radius, false);
            return(true);
        }

        Debug.LogError(string.Format("{0} does not have an implementation for ClosestPointOnSurface; GameObject.Name='{1}'", collider.GetType(), collider.gameObject.name));
        closestPointOnSurface = Vector3.zero;
        return(false);
    }
Ejemplo n.º 6
0
    /// <summary>
    /// Checks if there exists a wall in front of us as well as a flat surface to finish the climb on
    /// </summary>
    private bool CanGrabLedge(out Vector3 hitPosition, out GameObject grabbedObject)
    {
        hitPosition = Vector3.zero;

        grabbedObject = null;

        Vector3 o = controller.OffsetPosition(controller.head.Offset);

        Collider[] colliders = Physics.OverlapSphere(o, controller.radius + 0.2f, controller.Walkable);

        if (colliders.Length > 0)
        {
            foreach (var col in colliders)
            {
                SuperCollisionType type = col.GetComponent <SuperCollisionType>();

                Vector3 closestPoint = SuperCollider.ClosestPointOnSurface(col, o, controller.radius);

                RaycastHit hit;

                col.Raycast(new Ray(o, closestPoint - o), out hit, Mathf.Infinity);

                if (Vector3.Angle(hit.normal, controller.up) < type.StandAngle)
                {
                    continue;
                }

                if (Vector3.Angle(-hit.normal, lookDirection) < 60.0f)
                {
                    Vector3 topOfHead = o + controller.up * controller.radius;
                    Vector3 direction = Math3d.ProjectVectorOnPlane(controller.up, closestPoint - o);
                    Vector3 rayOrigin = topOfHead + Math3d.AddVectorLength(direction, 0.02f);

                    col.Raycast(new Ray(rayOrigin, controller.down), out hit, 0.5f);

                    if (Vector3.Angle(hit.normal, controller.up) < 20.0f)
                    {
                        hitPosition   = Math3d.ProjectPointOnPlane(controller.up, hit.point, topOfHead + direction);
                        grabbedObject = col.gameObject;

                        return(true);
                    }
                }
            }
        }

        return(false);
    }
Ejemplo n.º 7
0
    public static Vector3 ClosestPointOnSurface(Collider collider, Vector3 to, float radius)
    {
        if (collider is BoxCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((BoxCollider)collider, to));
        }
        else if (collider is SphereCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((SphereCollider)collider, to));
        }
        else if (collider is CapsuleCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((CapsuleCollider)collider, to));
        }
        else if (collider is MeshCollider)
        {
            RPGMesh rpgMesh = collider.GetComponent <RPGMesh>();

            if (rpgMesh != null)
            {
                return(rpgMesh.ClosestPointOn(to, radius, false, false));
            }

            BSPTree bsp = collider.GetComponent <BSPTree>();

            if (bsp != null)
            {
                return(bsp.ClosestPointOn(to, radius));
            }

            BruteForceMesh bfm = collider.GetComponent <BruteForceMesh>();

            if (bfm != null)
            {
                return(bfm.ClosestPointOn(to));
            }
        }
        else if (collider is TerrainCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((TerrainCollider)collider, to, radius, false));
        }

        Debug.LogError(string.Format("{0} does not have an implementation for ClosestPointOnSurface", collider.GetType()));

        return(Vector3.zero);
    }
Ejemplo n.º 8
0
    public static Vector3 ClosestPointOnSurface(Collider collider, Vector3 to, float radius)
    {
        if (collider is BoxCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((BoxCollider)collider, to));
        }
        else if (collider is SphereCollider)
        {
            return(SuperCollider.ClosestPointOnSurface((SphereCollider)collider, to));
        }
        else if (collider is MeshCollider)
        {
            RPGMesh rpgMesh = collider.GetComponent <RPGMesh>();

            if (rpgMesh != null)
            {
                return(rpgMesh.ClosestPointOn(to, radius, false, false));
            }
        }

        return(Vector3.zero);
    }
Ejemplo n.º 9
0
    private bool Strike(out GameObject struckObject, Vector3 origin, Vector3 offset, float radius = 0)
    {
        struckObject = null;

        if (radius == 0)
        {
            radius = controller.radius;
        }

        // Vector3 o = transform.position + (controller.Up * controller.Height * 0.5f);
        Vector3 center = origin + offset;

        Collider[] colliders = Physics.OverlapSphere(center, radius, controller.Walkable | EnemyLayerMask);

        foreach (var col in colliders)
        {
            SuperCollisionType type = col.GetComponent <SuperCollisionType>();

            Vector3 closestPoint = SuperCollider.ClosestPointOnSurface(col, center, radius);

            RaycastHit hit;

            col.Raycast(new Ray(origin, closestPoint - origin), out hit, Mathf.Infinity);

            if (type != null && Vector3.Angle(hit.normal, controller.up) < type.StandAngle)
            {
                continue;
            }

            if (Vector3.Angle(-hit.normal, lookDirection) < 60.0f)
            {
                struckObject = col.gameObject;
                return(true);
            }
        }

        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, 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);
        }
    }
Ejemplo n.º 11
0
        private void RecursivePushback(int depth)
        {
            PushIgnoredColliders();

            bool hasContact = false;

            foreach (CollisionSphere collisionSphere in collisionSpheres)
            {
                Collider[] colliders = Physics.OverlapSphere(
                    collisionSphere.Position,
                    collisionSphere.Radius,
                    settings.walkableLayerMask
                    );

                foreach (Collider collider in colliders)
                {
                    if (collider.isTrigger)
                    {
                        continue;
                    }

                    Vector3 contactPoint = SuperCollider.ClosestPointOnSurface(
                        collider,
                        collisionSphere.Position,
                        collisionSphere.Radius
                        );

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

                        Vector3 contactDirection = contactPoint - collisionSphere.Position;

                        if (contactDirection != Vector3.zero)
                        {
                            int cachedLayer = collider.gameObject.layer;

                            collider.gameObject.layer = ignoreCollisionLayer;

                            Ray  ray          = new Ray(collisionSphere.Position, contactDirection.normalized);
                            bool facingNormal = Physics.SphereCast(
                                ray,
                                settings.epsilon,
                                contactDirection.magnitude + settings.epsilon,
                                1 << ignoreCollisionLayer
                                );

                            collider.gameObject.layer = cachedLayer;

                            if (facingNormal)
                            {
                                if (Vector3.Distance(collisionSphere.Position, contactPoint) < collisionSphere.Radius)
                                {
                                    contactDirection = -contactDirection.normalized * (collisionSphere.Radius - contactDirection.magnitude);
                                }
                                else
                                {
                                    // A previously resolved collision has had a
                                    // side effect that moved us outside the
                                    // collider
                                    continue;
                                }
                            }
                            else
                            {
                                contactDirection = contactDirection.normalized * (collisionSphere.Radius + contactDirection.magnitude);
                            }

                            hasContact = true;

                            playerView.Position += contactDirection;

                            collider.gameObject.layer = ignoreCollisionLayer;

                            RaycastHit normalHit;

                            Ray normalRay = new Ray(
                                collisionSphere.Position + contactDirection,
                                contactPoint - collisionSphere.Position - contactDirection
                                );

                            Physics.SphereCast(
                                normalRay,
                                settings.epsilon,
                                out normalHit,
                                1 << ignoreCollisionLayer
                                );

                            collider.gameObject.layer = cachedLayer;

                            Collidable collidable = collider.gameObject.GetComponent <Collidable>();

                            if (collidable == null)
                            {
                                collidable = defaultCollidable;
                            }

                            Collision collision = new Collision()
                            {
                                collisionSphere = collisionSphere,
                                collidable      = collidable,
                                gameObject      = collider.gameObject,
                                point           = contactPoint,
                                normal          = normalHit.normal
                            };

                            collisions.Add(collision);
                        }
                    }
                }
            }

            PopIgnoredColliders();

            if (depth < settings.maxPushbackIterations && hasContact)
            {
                RecursivePushback(depth + 1);
            }
        }
Ejemplo n.º 12
0
    // This function makes sure we don't phase through other colliders. (Since character controller doesn't provide this functionality lmao).
    // I copied it from https://github.com/IronWarrior/SuperCharacterController
    // I changed it a bit, but SuperCharacterController is under the MIT license, meaning we can't use it without making our game also under the MIT license.
    // so TODO: Change this enough that we don't have to use the MIT license if we don't want to.
    private void RecursivePushback(int depth, int maxDepth)
    {
        bool contact = false;

        foreach (var sphere in spheres)
        {
            foreach (Collider col in Physics.OverlapSphere(SpherePosition(sphere), sphere.radius, layerMask, QueryTriggerInteraction.Ignore))
            {
                if (col.isTrigger)
                {
                    continue;
                }
                Vector3 position = SpherePosition(sphere);
                Vector3 contactPoint;
                bool    contactPointSuccess = SuperCollider.ClosestPointOnSurface(col, position, radius, out contactPoint);

                if (!contactPointSuccess)
                {
                    return;
                }

                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, QueryTriggerInteraction.Ignore);
                    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;
                    HandleCollision(col.gameObject, normalHit.normal, normalHit.point);
                }
            }
        }
        if (depth < maxDepth && contact)
        {
            RecursivePushback(depth + 1, maxDepth);
        }
    }