예제 #1
0
 /// <summary>
 /// Called when this object is fractured or spawned as a result of a fracture
 /// </summary>
 /// <param name="args"></param>
 internal virtual void OnFracture(OnFractureEventArgs args)
 {
     if (args.OriginalObject == this)
     {
         _processingFracture = false;
     }
 }
예제 #2
0
 private void OnFracture(OnFractureEventArgs args)
 {
     if (args.OriginalObject.gameObject == gameObject)
     {
         TransferOurJoint(args);
         RewriteOtherJoints(args);
     }
 }
예제 #3
0
        internal override void OnFracture(OnFractureEventArgs args)
        {
            if (!_ignoreOnFractured)
            {
                base.OnFracture(args);

                GeneratedPieces = args.FracturePiecesRootObject;
                GeneratedPieces.SetActive(false);
            }
        }
예제 #4
0
 private void OnFracture(OnFractureEventArgs e)
 {
     for (int i = 0; i < ObjectsToDisable.Length; i++)
     {
         if (ObjectsToDisable[i] != null)
         {
             ObjectsToDisable[i].SetActive(false);
         }
     }
 }
예제 #5
0
 private void OnFracture(OnFractureEventArgs args)
 {
     if (args.OriginalObject.gameObject == gameObject)
     {
         for (int i = 0; i < GameObjects.Length; i++)
         {
             if (GameObjects[i] != null)
             {
                 GameObjects[i].SendMessage("OnFracture", args, SendMessageOptions.DontRequireReceiver);
             }
         }
     }
 }
예제 #6
0
        protected override AsyncFractureResult FractureInternal(Vector3 localPos)
        {
            if (gameObject.activeSelf)
            {
                if (GeneratedPieces == null)
                {
                    GenerateFractureMeshes(localPos, null);

                    EnableFracturePieces();
                }
                else
                {
                    EnableFracturePieces();

                    OnFractureEventArgs args = new OnFractureEventArgs(this, GeneratedPieces);

                    // Notify scripts on this object
                    _ignoreOnFractured = true;
                    gameObject.SendMessage("OnFracture", args,
                                           SendMessageOptions.DontRequireReceiver);
                    _ignoreOnFractured = false;

                    // Notify each fracture piece
                    Transform trans = GeneratedPieces.transform;
                    for (int i = 0; i < trans.childCount; i++)
                    {
                        trans.GetChild(i).gameObject.SendMessage("OnFracture", args, SendMessageOptions.DontRequireReceiver);
                    }
                }

                gameObject.SetActive(false);

                AsyncFractureResult result = new AsyncFractureResult();
                result.SetResult(GeneratedPieces, EntireMeshBounds);
                return(result);
            }
            else
            {
                AsyncFractureResult result = new AsyncFractureResult();
                result.SetResult(null, new Bounds());
                return(result);
            }
        }
예제 #7
0
        private void OnFracture(OnFractureEventArgs args)
        {
            if (args.OriginalObject.gameObject == gameObject)
            {
                // We most likely will be disabled next frame.  When that
                // happens, the audio source on this object will not play.
                // To work around this, we create a temporary object and
                // copy all the sound properties to it.

                GameObject go = new GameObject("FractureTempAudioSource");

                AudioSource ourSrc = GetComponent <AudioSource>();
                AudioSource newSrc = go.AddComponent <AudioSource>();
                newSrc.bypassEffects         = ourSrc.bypassEffects;
                newSrc.bypassListenerEffects = ourSrc.bypassListenerEffects;
                newSrc.bypassReverbZones     = ourSrc.bypassReverbZones;
                newSrc.clip                 = ourSrc.clip;
                newSrc.dopplerLevel         = ourSrc.dopplerLevel;
                newSrc.ignoreListenerPause  = ourSrc.ignoreListenerPause;
                newSrc.ignoreListenerVolume = ourSrc.ignoreListenerVolume;
                newSrc.loop                 = ourSrc.loop;
                newSrc.maxDistance          = ourSrc.maxDistance;
                newSrc.mute                 = ourSrc.mute;
                newSrc.mute                 = ourSrc.mute;
                newSrc.minDistance          = ourSrc.minDistance;
                newSrc.mute                 = ourSrc.mute;
                newSrc.panStereo            = ourSrc.panStereo;
                newSrc.spatialBlend         = ourSrc.spatialBlend;
                newSrc.pitch                = ourSrc.pitch;
                newSrc.playOnAwake          = ourSrc.playOnAwake;
                newSrc.priority             = ourSrc.priority;
                newSrc.rolloffMode          = ourSrc.rolloffMode;
                newSrc.spread               = ourSrc.spread;
                newSrc.time                 = ourSrc.time;
                newSrc.timeSamples          = ourSrc.timeSamples;
                newSrc.velocityUpdateMode   = ourSrc.velocityUpdateMode;
                newSrc.volume               = ourSrc.volume;

                go.AddComponent <Internal.DestroyOnAudioFinish>();
            }
        }
예제 #8
0
        private void RewriteOtherJoints(OnFractureEventArgs args)
        {
            Joint[] joints;
            if (IncomingJointsSearchRoot != null)
            {
                joints = IncomingJointsSearchRoot.GetComponentsInChildren <Joint>();
            }
            else
            {
                joints = FindObjectsOfType <Joint>();
            }

            if (joints != null)
            {
                for (int i = 0; i < joints.Length; i++)
                {
                    if (joints[i] != null && joints[i].connectedBody == args.OriginalObject.GetComponent <Rigidbody>())
                    {
                        Transform rootTrans = args.FracturePiecesRootObject.transform;
                        for (int j = 0; j < rootTrans.childCount; j++)
                        {
                            Transform pieceTrans = rootTrans.GetChild(j);

                            Vector3 worldPoint =
                                joints[i].transform.localToWorldMatrix.MultiplyPoint(joints[i].anchor);

                            Collider ourCollider = pieceTrans.GetComponent <Collider>();
                            Vector3  closestOnUs = (ourCollider != null)
                                ? ourCollider.ClosestPointOnBounds(worldPoint)
                                : transform.position;

                            if ((worldPoint - pieceTrans.position).sqrMagnitude <
                                (closestOnUs - pieceTrans.position).sqrMagnitude + DistanceTolerance * DistanceTolerance)
                            {
                                joints[i].connectedBody = pieceTrans.GetComponent <Rigidbody>();
                            }
                        }
                    }
                }
            }
        }
예제 #9
0
        private void OnFracture(OnFractureEventArgs fractureRoot)
        {
            Rigidbody body = GetComponent <Rigidbody>();

            if (body != null)
            {
                body.isKinematic = false;   // Need to turn off kinematic to get collision events

                _rigidBodyVelocity        = body.velocity;
                _rigidBodyAngularVelocity = body.angularVelocity;
                _rigidBodyConstraints     = body.constraints;
                body.constraints          = RigidbodyConstraints.FreezeAll;

                _impactPoint    = Vector3.zero;
                _impactVelocity = Vector3.zero;
                _impactMass     = 0.0f;

                _fractureFrame = Time.frameCount;
                this.enabled   = true;
            }
        }
예제 #10
0
        private void OnFracture(OnFractureEventArgs args)
        {
            if (args.OriginalObject.gameObject == gameObject)
            {
                float radiusSq = ForceFalloffRadius * ForceFalloffRadius;

                for (int i = 0; i < args.FracturePiecesRootObject.transform.childCount; i++)
                {
                    Transform piece = args.FracturePiecesRootObject.transform.GetChild(i);

                    Rigidbody rb = piece.GetComponent <Rigidbody>();
                    if (rb != null)
                    {
                        Vector3 force = _impactMass * _impactVelocity / (rb.mass + _impactMass);

                        if (ForceFalloffRadius > 0.0f)
                        {
                            float distSq = (piece.position - _impactPoint).sqrMagnitude;
                            force *= Mathf.Clamp01(1.0f - distSq / (radiusSq));
                        }

                        rb.AddForceAtPosition(force * rb.mass, _impactPoint, ForceMode.Impulse);
                    }
                }

                if (AdjustForKinematic)
                {
                    // If the fractured body is kinematic, the collision for the colliding body will
                    // be as if it hit an unmovable wall.  Try to correct for that by adding the same
                    // force to colliding body.
                    Rigidbody thisBody = GetComponent <Rigidbody>();
                    if (thisBody != null && thisBody.isKinematic && _impactBody != null)
                    {
                        Vector3 force = thisBody.mass * _impactVelocity / (thisBody.mass + _impactMass);
                        _impactBody.AddForceAtPosition(force * _impactMass, _impactPoint, ForceMode.Impulse);
                    }
                }
            }
        }
예제 #11
0
        private void TransferOurJoint(OnFractureEventArgs args)
        {
            Joint origJoint = args.OriginalObject.GetComponent <Joint>();

            if (origJoint != null)
            {
                Vector3 worldPoint =
                    args.OriginalObject.transform.localToWorldMatrix.MultiplyPoint(origJoint.anchor);

                Transform rootTrans = args.FracturePiecesRootObject.transform;
                for (int i = 0; i < rootTrans.childCount; i++)
                {
                    Transform pieceTrans  = rootTrans.GetChild(i);
                    Collider  ourCollider = pieceTrans.GetComponent <Collider>();
                    Vector3   closestOnUs = (ourCollider != null)
                        ? ourCollider.ClosestPointOnBounds(worldPoint)
                        : transform.position;

                    if ((worldPoint - pieceTrans.position).sqrMagnitude <
                        (closestOnUs - pieceTrans.position).sqrMagnitude + DistanceTolerance * DistanceTolerance)
                    {
                        Joint  ourJoint = (Joint)pieceTrans.gameObject.AddComponent(origJoint.GetType());
                        string ourName  = ourJoint.name;

                        // Copy the properties
#if UNITY_METRO && !UNITY_EDITOR
                        foreach (
                            PropertyInfo info in
                            origJoint.GetType().GetRuntimeProperties())
                        {
                            if (info.CanWrite && info.CanRead)
                            {
                                info.SetValue(ourJoint, info.GetValue(origJoint, null), null);
                            }
                        }
#else
                        foreach (
                            PropertyInfo info in
                            origJoint.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
                        {
                            if (info.CanWrite && info.CanRead)
                            {
                                info.SetValue(ourJoint, info.GetValue(origJoint, null), null);
                            }
                        }
                        foreach (
                            PropertyInfo info in
                            origJoint.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic))
                        {
                            if (info.CanWrite && info.CanRead &&
                                info.GetCustomAttributes(typeof(SerializeField), true).Length != 0)
                            {
                                info.SetValue(ourJoint, info.GetValue(origJoint, null), null);
                            }
                        }
#endif

                        ourJoint.name = ourName;

                        // Reanchor
                        ourJoint.anchor = pieceTrans.worldToLocalMatrix.MultiplyPoint(worldPoint);

                        Vector3 connectedAnchorWorldPoint =
                            args.OriginalObject.transform.localToWorldMatrix.MultiplyPoint(origJoint.connectedAnchor);
                        ourJoint.connectedAnchor = pieceTrans.worldToLocalMatrix.MultiplyPoint(connectedAnchorWorldPoint);

                        Vector3 worldAxis =
                            args.OriginalObject.transform.localToWorldMatrix.MultiplyVector(origJoint.axis);
                        ourJoint.axis = pieceTrans.worldToLocalMatrix.MultiplyVector(worldAxis).normalized;
                    }

                    // Make sure each piece has one of these scripts attached
                    if (pieceTrans.GetComponent <TransferJointsOnFracture>() == null)
                    {
                        TransferJointsOnFracture tjof = pieceTrans.gameObject.AddComponent <TransferJointsOnFracture>();
                        tjof.IncomingJointsSearchRoot = IncomingJointsSearchRoot;
                        tjof.DistanceTolerance        = DistanceTolerance;
                    }
                }
            }
        }
예제 #12
0
        private IEnumerator WaitForResults(AsyncFractureOperation operation, FractureGeometry callback, Transform piecesParent, bool transferMass, bool hideAfterFracture, AsyncFractureResult result)
        {
            while (!operation.IsComplete)
            {
                // Async fractures should not happen while in edit mode because game objects don't update too often
                // and the coroutine is not pumped. Sync fractures should not reach this point.
                System.Diagnostics.Debug.Assert(Application.isPlaying && operation.Details.Asynchronous);
                yield return(null);
            }

            Rigidbody origBody = null;

            if (transferMass)
            {
                origBody = callback.GetComponent <Rigidbody>();
            }
            float density = 0.0f;

            if (origBody != null)
            {
                // Calculate the density by setting the density to
                // a known value and see what the mass comes out to.
                float mass = origBody.mass;
                origBody.SetDensity(1.0f);
                float volume = origBody.mass;
                density = mass / volume;

                // Reset the mass
                origBody.mass = mass;
            }

            List <FracturedMesh> meshes = operation.Result.GetMeshes();

            GameObject rootGO = new GameObject(callback.gameObject.name + " - Fracture Root");

            rootGO.transform.parent     = (piecesParent ?? callback.transform.parent);
            rootGO.transform.position   = callback.transform.position;
            rootGO.transform.rotation   = callback.transform.rotation;
            rootGO.transform.localScale = Vector3.one;  // Scale is controlled by the value in operation.Details

            Material[] sharedMaterials = callback.GetComponent <Renderer>().sharedMaterials;

            for (int i = 0; i < meshes.Count; i++)
            {
                GameObject go = (GameObject)Instantiate(callback.FractureTemplate);
                go.name                    = "Fracture Object " + i;
                go.transform.parent        = rootGO.transform;
                go.transform.localPosition = meshes[i].Offset;
                go.transform.localRotation = Quaternion.identity;
                go.transform.localScale    = Vector3.one;
                go.SetActive(true);

                MeshFilter mf = go.GetComponent <MeshFilter>();
                mf.mesh = meshes[i].Mesh;

                MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>();
                if (meshRenderer != null)
                {
                    Material[] materials = new Material[sharedMaterials.Length - meshes[i].EmptyTriangleCount + 1];
                    int        matIdx    = 0;
                    for (int m = 0; m < sharedMaterials.Length; m++)
                    {
                        if (!meshes[i].EmptyTriangles[m])
                        {
                            materials[matIdx++] = sharedMaterials[m];
                        }
                    }
                    if (!meshes[i].EmptyTriangles[sharedMaterials.Length])
                    {
                        materials[matIdx] = callback.InsideMaterial;
                    }

                    meshRenderer.sharedMaterials = materials;
                }

                MeshCollider meshCol = go.GetComponent <MeshCollider>();
                if (meshCol != null)
                {
                    meshCol.sharedMesh = mf.sharedMesh;
                }

                if (transferMass && origBody != null)
                {
                    Rigidbody rb = go.GetComponent <Rigidbody>();
                    if (rb != null)
                    {
                        rb.SetDensity(density);
                        rb.mass = rb.mass;  // Need to explicity set it for the editor to reflect the changes
                    }
                }

                FractureGeometry fg = go.GetComponent <FractureGeometry>();
                if (fg != null)
                {
                    fg.InsideMaterial   = callback.InsideMaterial;
                    fg.FractureTemplate = callback.FractureTemplate;
                    fg.PiecesParent     = callback.PiecesParent;
                    fg.NumGenerations   = callback.NumGenerations - 1;
                    fg.DistributeMass   = callback.DistributeMass;
                }
            }

            OnFractureEventArgs args = new OnFractureEventArgs(callback, rootGO);

            if (Application.isPlaying)
            {
                callback.gameObject.SendMessage("OnFracture", args, SendMessageOptions.DontRequireReceiver);
            }
            else
            {
                callback.OnFracture(args);
            }

            if (hideAfterFracture)
            {
                callback.gameObject.SetActive(false);
            }

            if (Application.isPlaying)
            {
                Transform trans = rootGO.transform;
                for (int i = 0; i < trans.childCount; i++)
                {
                    trans.GetChild(i).gameObject.SendMessage("OnFracture", args, SendMessageOptions.DontRequireReceiver);
                }
            }

            result.SetResult(rootGO, operation.Result.EntireMeshBounds);
        }