// 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); }
// Check for connectivity public void CheckConnectivity() { // Do once checkNeed = false; // Clear all activated/demolished shards CleanUpActivatedShards(cluster); // No shards to check if (cluster.shards.Count == 0) { return; } // Reinit neibs after cleaning RFShard.ReinitNeibs(cluster.shards); // List of shards to be activated List <RFShard> soloShards = new List <RFShard>(); // TODO do not collect solo uny shards // Check for solo shards and collect RFCluster.GetSoloShards(cluster, soloShards); // Reinit neibs before connectivity check RFShard.ReinitNeibs(cluster.shards); // Connectivity check RFCluster.ConnectivityCheck(cluster); // Get not connected and not unyielding child cluster CheckUnyielding(cluster); // TODO ONE NEIB DETACH FOR CHILD CLUSTERS // Activate not connected shards. if (soloShards.Count > 0) { for (int i = 0; i < soloShards.Count; i++) { soloShards[i].rigid.Activate(); } } // Clusterize childClusters or activate their shards if (cluster.HasChildClusters == true) { if (clusterize == true) { Clusterize(); } else { for (int c = 0; c < cluster.childClusters.Count; c++) { for (int s = 0; s < cluster.childClusters[c].shards.Count; s++) { cluster.childClusters[c].shards[s].rigid.Activate(); } } } } // Stop checking. Everything activated if (cluster.shards.Count == 0) { checkConnectivity = false; } }
// Demolish connected cluster static void DemolishClusterConnected(RayfireRigid scr) { // TODO If demolition.chunkRadius == 100. Detach all. // TODO Infinite demolition to detached frags. // Get detach radius distance float detachRadius = scr.limitations.bboxSize / 100f * scr.clusterDemolition.contactRadius; // Damage radius. TODO reset it. if (scr.clusterDemolition.damageRadius > 0) { detachRadius = scr.clusterDemolition.damageRadius; } // Detached solo fragments List <RFShard> detachShards = new List <RFShard>(); // Get all colliders TODO input mask by gameobject List <Collider> detachColliders = Physics.OverlapSphere(scr.limitations.contactPoint, detachRadius).ToList(); // No colliders to detach if (detachColliders.Count == 0) { return; } // Detach contacted fragments to solo. IMPROVE force spread by shards connection info. Connectivity check for (int i = scr.physics.clusterColliders.Count - 1; i >= 0; i--) { if (detachColliders.Contains(scr.physics.clusterColliders[i])) { // Detach shard ans im them solo detachShards.Add(scr.clusterDemolition.cluster.shards[i]); scr.clusterDemolition.cluster.shards.RemoveAt(i); // Destroy colliders to keep original cluster in scene scr.DestroyCollider(scr.physics.clusterColliders[i]); scr.physics.clusterColliders.RemoveAt(i); } } // No detach shards if (detachShards.Count == 0) { return; } // Prepare scr.fragments = new List <RayfireRigid>(); // Create parent for all fragments. GameObject root = new GameObject(scr.gameObject.name + "_root"); root.transform.parent = RayfireMan.inst.transForm; scr.rootChild = root.transform; scr.rootChild.position = scr.transForm.position; scr.rootChild.rotation = scr.transForm.rotation; // Get tm list for detached shards List <Transform> detachChildren = detachShards.Select(t => t.tm).ToList(); // Add rigid component to detached children AddRigidComponent(scr, detachChildren); // Parent to main root for (int i = 0; i < detachChildren.Count; i++) { detachChildren[i].parent = root.transform; } // All shards were detached. Set demolished state if (scr.clusterDemolition.cluster.shards.Count == 0) { scr.limitations.demolished = true; return; } // Check cluster for connectivity and return list of not connected clusters scr.clusterDemolition.cluster.childClusters = RFCluster.ConnectivityCheck(scr.clusterDemolition.cluster.shards); // CLuster is demolished scr.limitations.demolished = true; // Main cluster connected. Create new cluster based on left shards. IMPORTANT. attempt to use old cluster with old RB cause sim instability if (scr.clusterDemolition.cluster.childClusters.Count == 0) { CreateClusterRuntime(scr, scr.clusterDemolition.cluster); } // Main cluster not connected. Create connected cluster for every cluster in list else { foreach (RFCluster cls in scr.clusterDemolition.cluster.childClusters) { CreateClusterRuntime(scr, cls); } } // Turn off demolition for solo fragments if (scr.clusterDemolition.meshDemolition == false) { foreach (var frag in scr.fragments) { if (frag.objectType == ObjectType.Mesh) { frag.demolitionType = DemolitionType.None; } } } }