Beispiel #1
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);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Starts a fracture operation
        /// </summary>
        /// <param name="details">Fracture info</param>
        /// <param name="callback">The object to fracture</param>
        /// <param name="piecesParent">The parent of the resulting fractured pieces root object</param>
        /// <param name="transferMass">True to distribute the original object's mass to the fracture pieces; false otherwise</param>
        /// <param name="hideAfterFracture">True to hide the originating object after fracturing</param>
        /// <returns></returns>
        public static AsyncFractureResult StartFracture(FractureDetails details, FractureGeometry callback, Transform piecesParent, bool transferMass, bool hideAfterFracture)
        {
            AsyncFractureResult res = new AsyncFractureResult();

            if (Suspended)
            {
                res.SetResult(null, new Bounds());
            }
            else
            {
                if (details.Asynchronous)
                {
                    IEnumerator it = Instance.WaitForResults(FractureBuilder.Fracture(details), callback, piecesParent, transferMass, hideAfterFracture, res);
                    if (it.MoveNext())
                    {
#if UNITY_EDITOR
                        if (Instance._runningFractures.Count == 0 && !Application.isPlaying)
                        {
                            EditorApplication.update += Instance.OnEditorUpdate;
                        }
#endif

                        Instance._runningFractures.Add(new FractureInstance(res, it));
                    }
                }
                else
                {
                    // There should only be one iteration
                    IEnumerator it = Instance.WaitForResults(FractureBuilder.Fracture(details), callback, piecesParent, transferMass, hideAfterFracture, res);
                    while (it.MoveNext())
                    {
                        Debug.LogWarning("DinoFracture: Sync fracture taking more than one iteration");
                    }
                }
            }
            return(res);
        }
Beispiel #3
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);
        }