/// <summary> /// This method allows to check if the part enters in the terrain. /// </summary> public bool CheckTerrainClipping() { if (!AdvancedFeatures) { return(false); } if (!UseTerrainPrevention) { return(false); } Collider[] Colliders = PhysicExtension.GetNeighborsTypesByBox <Collider>(GetWorldPartTerrainBounds().center, TerrainBounds.extents, transform.rotation, Physics.AllLayers); for (int i = 0; i < Colliders.Length; i++) { if (Colliders[i] as TerrainCollider || Colliders[i].GetComponentInParent <VoxelandCollider>()) { return(true); } } return(false); }
/// <summary> /// This method allows to change the state all the sockets which hit the part bounds. /// </summary> public void ChangeAreaState(OccupancyType type) { SocketBehaviour[] Sockets = PhysicExtension.GetNeighborsTypesByBox <SocketBehaviour>(GetWorldPartMeshBounds().center, GetWorldPartMeshBounds().extents, transform.rotation, LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower()), QueryTriggerInteraction.Collide); for (int i = 0; i < Sockets.Length; i++) { if (Sockets[i] != null) { if (Sockets[i].AttachedPart != this) { if (Sockets[i].AllowPart(this) && type == OccupancyType.Busy) { Sockets[i].ChangeAreaState(type, LayerMask.NameToLayer(Constants.LAYER_DEFAULT.ToLower()), LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower()), Sockets[i].AttachedPart); Sockets[i].ChangeState(type, this); } else if (type == OccupancyType.Free) { Sockets[i].ChangeAreaState(type, LayerMask.NameToLayer(Constants.LAYER_DEFAULT.ToLower()), LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower()), Sockets[i].AttachedPart); Sockets[i].ChangeState(type, this); } } } } }
private void CheckContacts() { Collider[] Colliders = PhysicExtension.GetNeighborsTypesBySphere <Collider>(transform.position, Radius, LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower())); for (int i = 0; i < Colliders.Length; i++) { SocketBehaviour Socket = Colliders[i].GetComponent <SocketBehaviour>(); if (Socket != null) { if (Socket != this) { if (Socket.AllowPart(Socket.AttachedPart)) { for (int x = 0; x < BusySpaces.Count; x++) { Socket.AddOccupancy(BusySpaces[x].Part); } } } } } if (DisableOnGroundContact) { Colliders = PhysicExtension.GetNeighborsTypesBySphere <Collider>(transform.position, Radius, LayerMask.NameToLayer(Constants.LAYER_DEFAULT.ToLower())); for (int i = 0; i < Colliders.Length; i++) { if (Colliders[i] as TerrainCollider || Colliders[i].GetComponentInParent <VoxelandCollider>() || Colliders[i].GetComponentInParent <VoxelandCollider>()) { DisableCollider(); } } } }
/// <summary> /// This method allows to apply the physics on this part. /// </summary> public void ApplyPhysics() { if (!BuildManager.Instance.UsePhysics) { return; } if (!AdvancedFeatures) { return; } if (!UseConditionalPhysics) { return; } if (AffectedByPhysics) { return; } if (CurrentState == StateType.Queue) { return; } for (int i = 0; i < PhysicsIgnoreTags.Length; i++) { GameObject[] IgnoreCollider = GameObject.FindGameObjectsWithTag(PhysicsIgnoreTags[i]); for (int x = 0; x < IgnoreCollider.Length; x++) { if (IgnoreCollider[x].GetComponent <Collider>() != null) { for (int y = 0; y < Colliders.Count; y++) { Physics.IgnoreCollision(Colliders[y], IgnoreCollider[x].GetComponent <Collider>()); } } } } if (GetComponent <Rigidbody>() != null) { if (PhysicsConvexOnAffected) { for (int i = 0; i < Colliders.Count; i++) { if (Colliders[i].GetComponent <MeshCollider>() != null) { Colliders[i].GetComponent <MeshCollider>().convex = true; } } } GetComponent <Rigidbody>().isKinematic = false; GetComponent <Rigidbody>().AddForce(UnityEngine.Random.insideUnitSphere, ForceMode.Impulse); } ChangeAreaState(OccupancyType.Free); AffectedByPhysics = true; DisableAllSockets(); PhysicExtension.SetLayerRecursively(gameObject, LayerMask.NameToLayer(Constants.LAYER_IGNORE)); Destroy(this); Destroy(gameObject, PhysicsLifeTime); EventHandlers.AffectedPart(this); }
/// <summary> /// This method allows to check if the part is stable. /// </summary> public bool CheckStability() { if (BuildManager.Instance != null) { if (!BuildManager.Instance.UsePhysics) { return(true); } } if (!AdvancedFeatures) { return(true); } if (!UseConditionalPhysics) { return(true); } if (CustomDetections.Length != 0) { bool[] Results = new bool[CustomDetections.Length]; for (int i = 0; i < CustomDetections.Length; i++) { if (CustomDetections[i] != null) { PartBehaviour[] Parts = PhysicExtension.GetNeighborsTypesByBox <PartBehaviour>(transform.TransformPoint(CustomDetections[i].Position), CustomDetections[i].Size, transform.rotation, PhysicsLayers); for (int p = 0; p < Parts.Length; p++) { PartBehaviour Part = Parts[p].GetComponent <PartBehaviour>(); if (Part != null) { if (Part != this) { if (!Part.AffectedByPhysics && Part.CurrentState != StateType.Queue && CustomDetections[i].CheckType((int)Part.Type)) { Results[i] = true; } } } } Collider[] Colliders = PhysicExtension.GetNeighborsTypesByBox <Collider>(transform.TransformPoint(CustomDetections[i].Position), CustomDetections[i].Size, transform.rotation, PhysicsLayers); for (int x = 0; x < Colliders.Length; x++) { bool UseTerrain = Application.isPlaying == true ? BuildManager.Instance.BuildingSupport == SupportType.TerrainCollider : BuildManager.Instance.BuildingSupport == SupportType.TerrainCollider; if (UseTerrain) { if (CustomDetections[i].RequiredSupports.Contains(SurfaceType.TerrainCollider)) { if (CustomDetections[i].RequiredSupports.ToList().Find(entry => entry == SurfaceType.TerrainCollider) == SurfaceType.TerrainCollider) { if (Colliders[x] as TerrainCollider) { Results[i] = true; } } } } else { if (BuildManager.Instance.BuildingSupport == SupportType.SurfaceCollider && CustomDetections[i].RequiredSupports.ToList().Contains(SurfaceType.SurfaceCollider)) { if (Colliders[x].GetComponent <SurfaceCollider>() != null) { Results[i] = true; } } if (CustomDetections[i].RequiredSupports.ToList().Contains(SurfaceType.AllCollider)) { Results[i] = true; } } } } } return(Results.All(result => result)); } return(false); }
/// <summary> /// This method allows to update the placement preview. /// </summary> public void UpdatePreview() { HasSocket = false; if (CameraType == RayType.TopDown) { Physics.Raycast(GetRay(), out TopDownHit, Mathf.Infinity, LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower()), QueryTriggerInteraction.Ignore); } if (RayDetection == DetectionType.Overlap) { SocketBehaviour[] Sockets = PhysicExtension.GetNeighborsTypesBySphere <SocketBehaviour>(GetTransform.position, ActionDistance, LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower())); if (Sockets.Length > 0) { UpdateSnapsMovement(Sockets); } else { UpdateFreeMovement(); } } else { SocketBehaviour Socket = null; if (Physics.Raycast(GetRay(), out RaycastHit Hit, ActionDistance, LayerMask.NameToLayer(Constants.LAYER_SOCKET.ToLower()))) { if (Hit.collider.GetComponent <SocketBehaviour>() != null) { Socket = Hit.collider.GetComponent <SocketBehaviour>(); } } Debug.Log(Socket); if (Socket != null) { UpdateSnapsMovement(new SocketBehaviour[1] { Socket }); } else { UpdateFreeMovement(); } } if (CurrentMode == BuildMode.Placement || CurrentMode == BuildMode.Edition) { foreach (SocketBehaviour Socket in BuildManager.Instance.Sockets) { if (Socket != null) { Socket.EnableColliderByPartType(SelectedPrefab.Type); } } } AllowPlacement = !HasCollision(); if (AllowPlacement && CurrentPreview.RequireSockets && !HasSocket) { AllowPlacement = false; } if (AllowPlacement && OutOfRangeDistance != 0) { AllowPlacement = Vector3.Distance(GetTransform.position, CurrentPreview.transform.position) < ActionDistance; } CurrentPreview.gameObject.ChangeAllMaterialsColorInChildren(CurrentPreview.Renderers.ToArray(), AllowPlacement ? BuildManager.Instance.PreviewAllowedColor : BuildManager.Instance.PreviewDeniedColor, SelectedPrefab.PreviewColorLerpTime, SelectedPrefab.PreviewUseColorLerpTime); }