Esempio n. 1
0
        // determing the full size of a series of hit colliders
        static float DetermineHitPointsSize(PhysicsHit hitGroup, Vector3 direction, LayerMask mask)
        {
            int hitGroupHitsCount = hitGroup.hitElements.Count;

            if (!hitGroup.isRagdoll || hitGroupHitsCount == 1)
            {
                PhysicsHitElement h = hitGroup.hitElements[0];

                if (h.box != null)
                {
                    return(DetermineBoxSize(h.box));
                }
                if (h.sphere != null)
                {
                    return(DetermindSphereSize(h.sphere));
                }
                if (h.capsule != null)
                {
                    return(DetermineCapsuleSize(h.capsule));
                }
            }

            // determine size for multiple grabbed ragdolls / mesh colliders

            // start ray from the last hit (furthest from origin)
            Vector3   startRayPoint = hitGroup.hitElements[hitGroupHitsCount - 1].hitPoint;
            Rigidbody furthestHitRB = hitGroup.hitElements[hitGroupHitsCount - 1].rigidbody;

            // keep trying until we've searched too far
            float trySize = determineSizeTrySize;

            while (trySize < maxTrySize)
            {
                RaycastHit hit;

                // go forward and then raycast back towards our last hit point, to find the "other" side of the collider
                if (Physics.Raycast(new Ray(startRayPoint + direction * trySize, -direction), out hit, determineSizeTrySize, mask, QueryTriggerInteraction.Ignore))
                {
                    // if it's our collider we hit, then we found the other side
                    if (hit.rigidbody == furthestHitRB)
                    {
                        Vector3 lastCollidersOtherSide = hit.point;

                        // distance start calculated from the first hit point (nearest to ray origin)
                        return(Vector3.Distance(hitGroup.hitElements[0].hitPoint, lastCollidersOtherSide));
                    }
                }
                // didnt find end
                trySize += determineSizeTrySize;
            }

            // Debug.LogError("Couldnt find end " + hitGroup.hitElements[0].rigidbody.name);
            return(1);
        }
Esempio n. 2
0
        public static List <PhysicsHit> SphereCastAll(Ray ray, float radius, LayerMask shootMask, float maxDist)
        {
            // shoot ray
            grabRayHits = Physics.SphereCastAll(ray, radius, maxDist, shootMask, QueryTriggerInteraction.Ignore);
            // sort from nearest to farthest
            System.Array.Sort(grabRayHits, (x, y) => x.distance.CompareTo(y.distance));

            List <PhysicsHit> allHits = new List <PhysicsHit>();

            // each ragdoll has it's own hit group, to avoid having multiple moving joints attached to
            // ragdolls (this improves stability)
            Dictionary <Ragdoll, PhysicsHit> ragdoll2HitGroup = new Dictionary <Ragdoll, PhysicsHit>();

            for (int i = 0; i < grabRayHits.Length; i++)
            {
                RaycastHit        hit        = grabRayHits[i];
                PhysicsHitElement hitElement = new PhysicsHitElement(hit);

                if (hitElement.ragdollBone != null)
                {
                    if (ragdoll2HitGroup.ContainsKey(hitElement.ragdollBone.ragdoll))
                    {
                        ragdoll2HitGroup[hitElement.ragdollBone.ragdoll].hitElements.Add(hitElement);
                    }
                    else
                    {
                        PhysicsHit newGroup = new PhysicsHit(new List <PhysicsHitElement>()
                        {
                            hitElement
                        });
                        allHits.Add(newGroup);
                        ragdoll2HitGroup[hitElement.ragdollBone.ragdoll] = newGroup;
                    }
                }
                else
                {
                    allHits.Add(new PhysicsHit(new List <PhysicsHitElement>()
                    {
                        hitElement
                    }));
                }
            }

            // initialize the groups, (must be done after loop, so ragdoll groups are complete)
            for (int i = 0; i < allHits.Count; i++)
            {
                allHits[i].InitializeHit(ray.origin);
            }

            return(allHits);
        }
Esempio n. 3
0
        protected override void UpdateProjectile(float deltaTime)
        {
            if (reachedDestination)
            {
                return;
            }

            UpdateTravelZ(deltaTime, 0);

            for (int i = physicsHits.Count - 1; i >= 0; i--)
            {
                PhysicsHit hit = physicsHits[i];

                // if we've reached the hitgroup average position
                if (travelZ >= hit.hitDistance)
                {
                    // make sure this only happens for a frame
                    if (!reachedIndicies.Contains(i))
                    {
                        if (onReachHitObject != null)
                        {
                            onReachHitObject(hit);
                        }
                        // foreach rigidbody in the hit group
                        // simulate as if the impaler passed through it
                        // add force to the rigidbodies
                        for (int x = 0; x < hit.hitElements.Count; x++)
                        {
                            PhysicsHitElement hitElement = hit.hitElements[x];
                            hitElement.rigidbody.velocity = impaleDirection * velocity * hitObjectVelocityMultiplier;
                            // hitElement.rigidbody.AddForceAtPosition( impaleDirection * velocity * hitObjectVelocityMultiplier, hitElement.hitPoint, ForceMode.VelocityChange);
                        }

                        reachedIndicies.Add(i);
                    }
                }
            }

            if (reachedDestination)
            {
                SetKinematic(kinematicOnReach);
                EnableCollider(!kinematicOnReach || useColliderOnReach);
            }
        }
Esempio n. 4
0
        protected override void UpdateProjectile(float deltaTime)
        {
            UpdateArcSimulation();

            if (reachedDestination)
            {
                return;
            }

            UpdateTravelZ(deltaTime, randomOffset);

            /*
             *  update backwards for stability, so we set our furthest rigidbody first
             *  this way A doesnt bump into B accidentally
             *  -Spear-->>>>  A       B
             */
            for (int i = physicsHits.Count - 1; i >= 0; i--)
            {
                bool isSkewered = i >= startIndexForSkewered;

                PhysicsHit hit = physicsHits[i];

                // out offset with regard to all the other impaled entities (local position on spear)
                // 0 if we're not skewering
                float skewerOffset = isSkewered ? skewerOffsets[i] : 0;

                // where out imalement "slot" is on the spear thats travelling
                float z = travelZ - skewerOffset;

                // our target z (where we'll wind up)
                float end = endPointDistance - skewerOffset;

                // stay at 0 until the "spear" reaches our destination
                float t = Mathf.Clamp01((z - hit.hitDistance) / (end - hit.hitDistance));

                // if we've reached the hitgroup average position
                if (t > 0)
                {
                    // make sure this only happens for a frame
                    if (!reachedIndicies.Contains(i))
                    {
                        if (onReachHitObject != null)
                        {
                            onReachHitObject(hit, isSkewered);
                        }

                        // if we're not skewering this hit group
                        // simulate as if the spear passed through it
                        if (!isSkewered)
                        {
                            // ungrab the group (disables created joints)
                            grabbedBodies[i].Detach();

                            // foreach rigidbody in the hit group
                            for (int x = 0; x < hit.hitElements.Count; x++)
                            {
                                PhysicsHitElement physicsHitElement = hit.hitElements[x];

                                // add force to the rigidbodies
                                // physicsHitElement.rigidbody.velocity = launchRay.direction * velocity;
                                physicsHitElement.rigidbody.AddForceAtPosition(launchRay.direction * velocity, physicsHitElement.hitPoint, ForceMode.VelocityChange);

                                // if its a ragdoll, attempt to dismember the bone
                                if (physicsHitElement.ragdoll != null)
                                {
                                    physicsHitElement.ragdoll.DismemberBone("Spear", physicsHitElement.ragdollBone.bone);
                                }
                            }
                        }
                        reachedIndicies.Add(i);
                    }
                }

                if (isSkewered)
                {
                    /*
                     *  update each attachment point so that it starts moving when
                     *  the point on the spear it's going to wind up impaled on reaches the point itself
                     *
                     *  set the target position as the spot it's going to wind up at the end of the
                     *  movement
                     */
                    grabbedBodies[i].grabPoint.baseRigidbody.MovePosition(Vector3.Lerp(hit.averagePosition, skewerTargets[i], t));

                    // if we're pinned up against a wall, allow joint movement along teh z axis,
                    // so rigidbodies can slide along the spear (helps stability)
                    if (reachedDestination && stickToEnd)
                    {
                        ConfigurableJoint j = grabbedBodies[i].grabPoint.baseJoint;

                        j.zMotion = ConfigurableJointMotion.Limited;
                        var l = j.linearLimit;
                        l.limit       = spearLength - skewerOffset;
                        j.linearLimit = l;
                    }
                }
            }

            // move model
            transform.position = Vector3.Lerp(launchRay.origin, modelEndTarget, Mathf.Clamp01(travelZ / endPointDistance));

            if (reachedDestination)
            {
                ReachDestination(skeweredCount > 0 ? hitObjectVelocityMultiplier : 1);
            }
        }