/// <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; } }
private void OnFracture(OnFractureEventArgs args) { if (args.OriginalObject.gameObject == gameObject) { TransferOurJoint(args); RewriteOtherJoints(args); } }
internal override void OnFracture(OnFractureEventArgs args) { if (!_ignoreOnFractured) { base.OnFracture(args); GeneratedPieces = args.FracturePiecesRootObject; GeneratedPieces.SetActive(false); } }
private void OnFracture(OnFractureEventArgs e) { for (int i = 0; i < ObjectsToDisable.Length; i++) { if (ObjectsToDisable[i] != null) { ObjectsToDisable[i].SetActive(false); } } }
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); } } } }
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); } }
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>(); } }
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>(); } } } } } }
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; } }
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); } } } }
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; } } } }
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); }