// Clusterize not connected groups void Clusterize() { for (int i = 0; i < cluster.childClusters.Count; i++) { // set demolishable state for child cluster cluster.demolishable = demolishable; // Set bound cluster.childClusters[i].bound = RFCluster.GetShardsBound(cluster.childClusters[i].shards); // Create cluster cluster.childClusters[i].shards[0].rigid.simulationType = SimType.Dynamic; // TODO IN BETTER WAY cluster.childClusters[i].shards[0].rigid.objectType = ObjectType.ConnectedCluster; RFDemolitionCluster.CreateClusterRuntime(cluster.childClusters[i].shards[0].rigid, cluster.childClusters[i]); cluster.childClusters[i].shards[0].rigid.objectType = ObjectType.Mesh; // Copy preview cluster.childClusters[i].rigid.clusterDemolition.cn = showConnections; cluster.childClusters[i].rigid.clusterDemolition.nd = showNodes; // Destroy components for (int s = 0; s < cluster.childClusters[i].shards.Count; s++) { Destroy(cluster.childClusters[i].shards[s].rigid.physics.rigidBody); Destroy(cluster.childClusters[i].shards[s].rigid); } } }
// Init collapse after connection loss static void CollapseCluster(RayfireRigid scr) { // Collect solo shards, remove from cluster, no need to reinit List <RFShard> detachShards = new List <RFShard>(); RFCluster.GetSoloShards(scr.clusterDemolition.cluster, detachShards); // Clear fragments in case of previous demolition if (scr.HasFragments == true) { scr.fragments.Clear(); } // Dynamic cluster connectivity check, all clusters are equal, pick biggest to keep as original if (scr.simulationType == SimType.Dynamic || scr.simulationType == SimType.Sleeping) { // Check left cluster shards for connectivity and collect not connected child clusters. Should be before ClusterizeDetachShards RFCluster.ConnectivityCheck(scr.clusterDemolition.cluster); // Cluster is not connected. Set biggest child cluster shards to original cluster. Cant be 1 child cluster here RFCluster.ReduceChildClusters(scr.clusterDemolition.cluster); } // Kinematik/ Inactive cluster, Connectivity check if cluster has uny shards. Main cluster keeps all not activated else if (scr.simulationType == SimType.Kinematic || scr.simulationType == SimType.Inactive) { RFCluster.ConnectivityUnyCheck(scr.clusterDemolition.cluster); } // Init final cluster ops RFDemolitionCluster.PostDemolitionCluster(scr, detachShards); }
// Copy from public void CopyFrom(RFDemolitionCluster demolition) { meshDemolition = demolition.meshDemolition; connectivity = demolition.connectivity; contactRadius = demolition.contactRadius; Reset(); }
// Slice object public void Slice() { if (objectType == ObjectType.Mesh || objectType == ObjectType.SkinnedMesh) { RFDemolitionMesh.SliceMesh(this); } else if (objectType == ObjectType.ConnectedCluster) { RFDemolitionCluster.SliceConnectedCluster(this); } }
// Demolish cluster IEnumerator DelayedClusterCor(RayfireRigid rigid, Collider coll) { // Wait life time yield return(new WaitForSeconds(delay)); // Activate if (rigid != null && coll != null) { RFDemolitionCluster.DemolishConnectedCluster(rigid, new[] { coll }); } }
void ClusterSetupUI() { GUILayout.BeginHorizontal(); if (GUILayout.Button("Setup Cluster", GUILayout.Height(25))) { if (Application.isPlaying == false) { foreach (var targ in targets) { if (targ as RayfireRigid != null) { RFPhysic.DestroyColliders(targ as RayfireRigid); (targ as RayfireRigid).clusterDemolition.cluster = new RFCluster(); (targ as RayfireRigid).clusterDemolition.clsCount = 1; (targ as RayfireRigid).clusterDemolition.minorClusters = null; (targ as RayfireRigid).SetComponentsBasic(); (targ as RayfireRigid).SetParticleComponents(); if (RFDemolitionCluster.Clusterize(targ as RayfireRigid) == false) { Debug.Log("RayFire Rigid: " + (targ as RayfireRigid).name + " has no children with mesh."); } SetDirty(targ as RayfireRigid); } } } } if (GUILayout.Button("Reset Cluster", GUILayout.Height(25))) { if (Application.isPlaying == false) { foreach (var targ in targets) { if (targ as RayfireRigid != null) { RFPhysic.DestroyColliders(targ as RayfireRigid); (targ as RayfireRigid).clusterDemolition.cluster = new RFCluster(); (targ as RayfireRigid).clusterDemolition.clsCount = 1; (targ as RayfireRigid).clusterDemolition.minorClusters = null; SetDirty(targ as RayfireRigid); } } } } EditorGUILayout.EndHorizontal(); }
/// ///////////////////////////////////////////////////////// /// Activation /// ///////////////////////////////////////////////////////// // Check for RayFire Rigid component activation void ActivationCheck(Collider coll) { // Get rigid from collider or rigid body RayfireRigid rigid = coll.attachedRigidbody == null ? coll.GetComponent <RayfireRigid>() : coll.attachedRigidbody.GetComponent <RayfireRigid>(); // Has no rigid if (rigid == null) { return; } // Activation if (rigid.activation.byActivator == true) { if (rigid.simulationType == SimType.Inactive || rigid.simulationType == SimType.Kinematic) { if (delay <= 0) { rigid.Activate(); } else { StartCoroutine(DelayedActivationCor(rigid)); } } } // Connected cluster one fragment detach if (rigid.objectType == ObjectType.ConnectedCluster) { if (demolishCluster == true) { if (delay <= 0) { RFDemolitionCluster.DemolishConnectedCluster(rigid, new[] { coll }); } else { StartCoroutine(DelayedClusterCor(rigid, coll)); } } } }
// Clusterize void Clusterize() { // TODO skip if minor nested cluster if (objectType == ObjectType.NestedCluster) { if (clusterDemolition.cluster.id > 1) { return; } } // Fail check if (RFDemolitionCluster.Clusterize(this) == true) { return; } // Fail physics.exclude = true; Debug.Log("RayFire Rigid: " + name + " has no children with mesh. Object Excluded from simulation.", gameObject); }
void ClusterSetupUI() { GUILayout.BeginHorizontal(); if (GUILayout.Button("Setup Cluster", GUILayout.Height(25))) { if (Application.isPlaying == false) { foreach (var targ in targets) { if (targ as RayfireRigid != null) { RFDemolitionCluster.SetupCluster(targ as RayfireRigid); SetDirty(targ as RayfireRigid); } } } } if (GUILayout.Button("Reset Cluster", GUILayout.Height(25))) { if (Application.isPlaying == false) { foreach (var targ in targets) { if (targ as RayfireRigid != null) { RFPhysic.DestroyColliders(targ as RayfireRigid); (targ as RayfireRigid).clusterDemolition.cluster = new RFCluster(); (targ as RayfireRigid).clusterDemolition.clsCount = 1; (targ as RayfireRigid).clusterDemolition.minorClusters = null; SetDirty(targ as RayfireRigid); } } } } EditorGUILayout.EndHorizontal(); }
// Define components void SetComponentsPhysics() { // Excluded from simulation if (physics.exclude == true) { return; } // Physics components physics.rigidBody = GetComponent <Rigidbody>(); physics.meshCollider = GetComponent <Collider>(); // Mesh Set collider if (objectType == ObjectType.Mesh) { RFPhysic.SetMeshCollider(this); } // Cluster check TODO EXPOSE IN UI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (objectType == ObjectType.NestedCluster || objectType == ObjectType.ConnectedCluster) { // No children mesh for clustering bool clusteringState = RFDemolitionCluster.Clusterize(this); if (clusteringState == false) { physics.exclude = true; Debug.Log("RayFire Rigid: " + name + " has no children with mesh. Object Excluded from simulation.", gameObject); return; } } // Rigid body if (simulationType != SimType.Static && physics.rigidBody == null) { physics.rigidBody = gameObject.AddComponent <Rigidbody>(); physics.rigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } }
// Demolish object public void Demolish() { // Profiler.BeginSample ("Demolition"); // Debug.Log (limitations.demolitionShould); // Initialize if not if (initialized == false) { Initialize(); } // Timestamp float t1 = Time.realtimeSinceStartup; // Restore position and rotation to prevent high collision offset transForm.position = physics.position; transForm.rotation = physics.rotation; // Demolish mesh or cluster to reference if (RFReferenceDemolition.DemolishReference(this) == false) { return; } // Demolish mesh and create fragments. Stop if runtime caching or no meshes/fragments were created if (RFDemolitionMesh.DemolishMesh(this) == false) { return; } /* EXPERIMENTAL * // TODO Clusterize * bool clusterize = true; * if (clusterize == true && objectType == ObjectType.Mesh && demolitionType == DemolitionType.Runtime) * { * * foreach (var frag in fragments) * { * Destroy (frag.physics.rigidBody); * Destroy (frag); * } * * RayfireRigid scr = this.rootChild.gameObject.AddComponent<RayfireRigid>(); * this.CopyPropertiesTo (scr); * scr.demolitionType = DemolitionType.Runtime; * scr.objectType = ObjectType.ConnectedCluster; * * scr.limitations.contactPoint = this.limitations.contactPoint; * scr.limitations.contactNormal = this.limitations.contactNormal; * scr.limitations.contactVector3 = this.limitations.contactVector3; * * scr.physics.velocity = this.physics.velocity; * * scr.clusterDemolition.cluster = new RFCluster(); * scr.Initialize(); * * scr.physics.rigidBody.velocity = this.physics.velocity; * scr.limitations.demolitionShould = true; * //scr.Demolish(); * RayfireMan.DestroyFragment (this, rootParent); * return; * } */ // Demolish cluster to children nodes if (RFDemolitionCluster.DemolishCluster(this) == true) { return; } // Check fragments and proceed TODO separate flow for connected cls demolition if (limitations.demolished == false) { limitations.demolitionShould = false; demolitionType = DemolitionType.None; return; } // Connectivity check activation.CheckConnectivity(); // Fragments initialisation InitMeshFragments(); // Sum total demolition time RayfireMan.inst.maxTimeThisFrame += Time.realtimeSinceStartup - t1; // Init particles RFParticles.InitDemolitionParticles(this); // Init sound RFSound.DemolitionSound(sound, limitations.bboxSize); // Event demolitionEvent.InvokeLocalEvent(this); RFDemolitionEvent.InvokeGlobalEvent(this); // Destroy demolished object RayfireMan.DestroyFragment(this, rootParent); // Timestamp // float t2 = Time.realtimeSinceStartup; // Debug.Log (t2 - t1); // Profiler.EndSample(); }
// Demolish object public void Demolish() { // Profiler.BeginSample ("Demolition"); // Debug.Log (limitations.demolitionShould); // Initialize if not if (initialized == false) { Initialize(); } // Timestamp float t1 = Time.realtimeSinceStartup; // Restore position and rotation to prevent high collision offset transForm.position = physics.position; transForm.rotation = physics.rotation; // Demolish mesh or cluster to reference if (RFReferenceDemolition.DemolishReference(this) == false) { return; } // Demolish mesh and create fragments. Stop if runtime caching or no meshes/fragments were created if (RFDemolitionMesh.DemolishMesh(this) == false) { return; } // Demolish cluster to children nodes if (RFDemolitionCluster.DemolishCluster(this) == true) { return; } // Check fragments and proceed TODO separate flow for connected cls demolition if (limitations.demolished == false) { limitations.demolitionShould = false; demolitionType = DemolitionType.None; return; } // Connectivity check activation.CheckConnectivity(); // Fragments initialisation InitMeshFragments(); // Sum total demolition time RayfireMan.inst.maxTimeThisFrame += Time.realtimeSinceStartup - t1; // Init particles RFParticles.InitDemolitionParticles(this); // Event demolitionEvent.InvokeLocalEvent(this); RFDemolitionEvent.InvokeGlobalEvent(this); // Destroy demolished object RayfireMan.DestroyFragment(this, rootParent); // Timestamp // float t2 = Time.realtimeSinceStartup; // Debug.Log (t2 - t1); // Profiler.EndSample(); }
// Impact hit to rigid bodies. Activated inactive, detach clusters void ImpactHit(RayfireRigid rigid, RaycastHit hit, Vector3 impactPoint, Vector3 shootVector) { // Prepare impact list List <Rigidbody> impactRbList = new List <Rigidbody>(); // Hit object Impact activation and detach before impact force if (radius == 0) { // Inactive Activation if (rigid.objectType == ObjectType.Mesh) { if (rigid.simulationType == SimType.Inactive || rigid.simulationType == SimType.Kinematic) { if (rigid.activation.byImpact == true) { rigid.Activate(); } } } // Connected cluster one fragment detach if (rigid.objectType == ObjectType.ConnectedCluster) { if (demolishCluster == true) { RFDemolitionCluster.DemolishConnectedCluster(rigid, new[] { hit.collider }); } } // Collect for impact impactRbList.Add(hit.collider.attachedRigidbody); } // Group by radius Impact activation and detach before impact force if (radius > 0) { // Get all colliders impactColliders = null; impactColliders = Physics.OverlapSphere(impactPoint, radius, mask); // TODO tag filter if (tagFilter != untagged) { // && colliders[i].CompareTag (tagFilter) == false) } // No colliders. Stop if (impactColliders == null) { return; } // Connected cluster group detach first, check for rigids in range next if (rigid.objectType == ObjectType.ConnectedCluster) { if (demolishCluster == true) { RFDemolitionCluster.DemolishConnectedCluster(rigid, impactColliders); } } // Collect all rigid bodies in range RayfireRigid scr; List <RayfireRigid> impactRigidList = new List <RayfireRigid>(); for (int i = 0; i < impactColliders.Length; i++) { // Get rigid from collider or rigid body scr = impactColliders[i].attachedRigidbody == null ? impactColliders[i].GetComponent <RayfireRigid>() : impactColliders[i].attachedRigidbody.transform.GetComponent <RayfireRigid>(); // Collect uniq rigids in radius if (scr != null) { if (impactRigidList.Contains(scr) == false) { impactRigidList.Add(scr); } } // Collect RigidBodies without rigid script else { if (affectRigidBodies == true) { if (impactColliders[i].attachedRigidbody == null) { if (impactRbList.Contains(impactColliders[i].attachedRigidbody) == false) { impactRbList.Add(impactColliders[i].attachedRigidbody); } } } } } // Group Activation first for (int i = 0; i < impactRigidList.Count; i++) { if (impactRigidList[i].activation.byImpact == true) { if (impactRigidList[i].simulationType == SimType.Inactive || impactRigidList[i].simulationType == SimType.Kinematic) { impactRigidList[i].Activate(); } } } // Collect rigid body from rigid components if (strength > 0) { for (int i = 0; i < impactRigidList.Count; i++) { // Skip inactive objects if (impactRigidList[i].simulationType == SimType.Inactive && affectInactive == false) { continue; } // Collect impactRbList.Add(impactRigidList[i].physics.rigidBody); } } } // NO Strength if (strength == 0) { return; } // No rigid bodies if (impactRbList.Count == 0) { return; } // Apply force for (int i = 0; i < impactRbList.Count; i++) { // Skip static and kinematik objects if (impactRbList[i] == null || impactRbList[i].isKinematic == true) { continue; } // Add force impactRbList[i].AddForceAtPosition(shootVector * strength, impactPoint, ForceMode.VelocityChange); } }
// Demolish object to reference public static bool DemolishReference(RayfireRigid scr) { if (scr.demolitionType == DemolitionType.ReferenceDemolition) { // Get instance GameObject referenceGo = scr.referenceDemolition.GetReference(); // Has reference if (referenceGo != null) { // Instantiate turned off reference bool refState = referenceGo.activeSelf; referenceGo.SetActive(false); GameObject fragRoot = scr.InstantiateGo(referenceGo); referenceGo.SetActive(refState); fragRoot.name = referenceGo.name; // Set tm scr.rootChild = fragRoot.transform; scr.rootChild.position = scr.transForm.position; scr.rootChild.rotation = scr.transForm.rotation; scr.rootChild.transform.parent = RayfireMan.inst.transForm; // Clear list for fragments scr.fragments = new List <RayfireRigid>(); // Check root for rigid props RayfireRigid rootScr = fragRoot.gameObject.GetComponent <RayfireRigid>(); // Reference Root has not rigid. Add to if (rootScr == null && scr.referenceDemolition.addRigid == true) { // Add rigid and copy rootScr = fragRoot.gameObject.AddComponent <RayfireRigid>(); rootScr.initialization = RayfireRigid.InitType.AtStart; scr.CopyPropertiesTo(rootScr); // Copy particles RFParticles.CopyParticles(scr, rootScr); // Single mesh TODO improve if (fragRoot.transform.childCount == 0) { rootScr.objectType = ObjectType.Mesh; } // Multiple meshes if (fragRoot.transform.childCount > 0) { rootScr.objectType = ObjectType.MeshRoot; } } // Activate and init rigid scr.rootChild.gameObject.SetActive(true); // Reference has rigid if (rootScr != null) { // Create rigid for root children if (rootScr.objectType == ObjectType.MeshRoot) { for (int i = 0; i < rootScr.fragments.Count; i++) { rootScr.fragments[i].limitations.currentDepth++; } scr.fragments.AddRange(rootScr.fragments); scr.DestroyRigid(rootScr); } // Get ref rigid else if (rootScr.objectType == ObjectType.Mesh || rootScr.objectType == ObjectType.SkinnedMesh) { rootScr.meshDemolition.runtimeCaching.type = CachingType.Disable; RFDemolitionMesh.DemolishMesh(rootScr); // TODO COPY MESH DATA FROM ROOTSCR TO THIS TO REUSE scr.fragments.AddRange(rootScr.fragments); RayfireMan.DestroyFragment(rootScr, rootScr.rootParent, 1f); } // Get ref rigid else if (rootScr.objectType == ObjectType.NestedCluster || rootScr.objectType == ObjectType.ConnectedCluster) { rootScr.Default(); rootScr.limitations.contactPoint = scr.limitations.contactPoint; RFDemolitionCluster.DemolishCluster(rootScr); rootScr.physics.exclude = true; scr.fragments.AddRange(rootScr.fragments); RayfireMan.DestroyFragment(rootScr, rootScr.rootParent, 1f); } // Has rigid by has No fragments. Stop demolition if (scr.HasFragments == false) { scr.demolitionType = DemolitionType.None; return(false); } } } // Has no rigid, has No fragments, but demolished scr.limitations.demolished = true; } return(true); }
// Demolish object to reference public static bool DemolishReference(RayfireRigid scr) { if (scr.demolitionType == DemolitionType.ReferenceDemolition) { // Demolished scr.limitations.demolished = true; // Turn off original scr.gameObject.SetActive(false); // Get instance GameObject refGo = scr.referenceDemolition.GetReference(); // Has no reference if (refGo == null) { return(true); } // Instantiate turned off reference with null parent GameObject instGo = Object.Instantiate(refGo, scr.transForm.position, scr.transForm.rotation); instGo.name = refGo.name; // Set root to manager or to the same parent if (RayfireMan.inst != null && RayfireMan.inst.advancedDemolitionProperties.parent == RFManDemolition.FragmentParentType.Manager) { instGo.transform.parent = RayfireMan.inst.transform; } else { instGo.transform.parent = scr.transForm.parent; } // Set tm scr.rootChild = instGo.transform; // Copy scale if (scr.referenceDemolition.inheritScale == true) { scr.rootChild.localScale = scr.transForm.localScale; } // Clear list for fragments scr.fragments = new List <RayfireRigid>(); // Check root for rigid props RayfireRigid refScr = instGo.gameObject.GetComponent <RayfireRigid>(); // Reference Root has not rigid. Add to if (refScr == null && scr.referenceDemolition.addRigid == true) { // Add rigid and copy refScr = instGo.gameObject.AddComponent <RayfireRigid>(); // Copy rigid scr.CopyPropertiesTo(refScr); // Copy particles RFParticles.CopyParticles(scr, refScr); // Single mesh TODO improve if (instGo.transform.childCount == 0) { refScr.objectType = ObjectType.Mesh; } // Multiple meshes if (instGo.transform.childCount > 0) { refScr.objectType = ObjectType.MeshRoot; } } // Activate and init rigid instGo.transform.gameObject.SetActive(true); // Reference has rigid if (refScr != null) { // Init if not initialized yet refScr.Initialize(); // Create rigid for root children if (refScr.objectType == ObjectType.MeshRoot) { for (int i = 0; i < refScr.fragments.Count; i++) { refScr.fragments[i].limitations.currentDepth++; } scr.fragments.AddRange(refScr.fragments); scr.DestroyRigid(refScr); } // Get ref rigid else if (refScr.objectType == ObjectType.Mesh || refScr.objectType == ObjectType.SkinnedMesh) { refScr.meshDemolition.runtimeCaching.type = CachingType.Disable; RFDemolitionMesh.DemolishMesh(refScr); // TODO COPY MESH DATA FROM ROOTSCR TO THIS TO REUSE scr.fragments.AddRange(refScr.fragments); RayfireMan.DestroyFragment(refScr, refScr.rootParent, 1f); } // Get ref rigid else if (refScr.objectType == ObjectType.NestedCluster || refScr.objectType == ObjectType.ConnectedCluster) { refScr.Default(); // Copy contact data refScr.limitations.contactPoint = scr.limitations.contactPoint; refScr.limitations.contactVector3 = scr.limitations.contactVector3; refScr.limitations.contactNormal = scr.limitations.contactNormal; // Demolish RFDemolitionCluster.DemolishCluster(refScr); // Collect new fragments scr.fragments.AddRange(refScr.fragments); //refScr.physics.exclude = true; //RayfireMan.DestroyFragment (refScr, refScr.rootParent, 1f); } } } return(true); }