public PhysPart SpawnPart(Transform parent) { Transform part = null; //Attempt to find part blueprint asset, which has a reference to the part prefab we want to spawn. ScriptablePartBP partAsset = Resources.Load <ScriptablePartBP>("PartBlueprints/" + partName); if (partAsset == null) //If the part blueprint can't be found, handle the error. { part = new GameObject("Invalid Part! (\"" + partName + "\")").transform; part.gameObject.AddComponent <PhysPart>().partName = partName; Debug.LogError("Invalid Part! (\"" + partName + "\")", parent); } else { part = Object.Instantiate(partAsset.partPrefab).transform; //Spawn the prefab part.name = partName; } part.SetParent(parent); PhysPart phys = part.GetComponent <PhysPart>(); phys.connections.Clear(); //Clear connections if any are carried over e.g. if the prefab is not cleansed of connections. phys.ApplyBlueprint(this); //Let part handle setting its values based on the blueprint. return(phys); }
public PhysPart SpawnPartInHand(PartBlueprint bp) { PhysPart p = SetCurrPart(SpawnEditorPart(bp)); p.transform.rotation = lastObjRot; return(p); }
public static PhysPart[] GetConnectedParts(PhysPart startPart, bool drawDebugLines = false) { List <PhysPart> visitedParts = new List <PhysPart>(); List <PhysPart> partsToVisit = new List <PhysPart>(); partsToVisit.Add(startPart); PhysPart currPart = partsToVisit[0]; while (partsToVisit.Count > 0) { Vector3 prevPartPos = currPart.transform.position; currPart = partsToVisit[0]; if (drawDebugLines) { Debug.DrawLine(prevPartPos, currPart.transform.position, Color.cyan, 1.5f); } visitedParts.Add(currPart); partsToVisit.Remove(currPart); foreach (PartConnection c in currPart.connections) { if (!visitedParts.Contains(c.toPart) && !partsToVisit.Contains(c.toPart)) { partsToVisit.Add(c.toPart); } } } return(visitedParts.ToArray()); }
public void HighlightPart(PhysPart p, Color c) { if (p == null) { return; } p.gameObject.AddComponent <Proxy_HighlightPart>().HighlightPart(c); }
public void ApplyThrust() { Vector3 thrustForce = -exhaustPoint.forward * currThrust; if (MiscUtils.IsVectorValid(thrustForce) && MiscUtils.IsVectorValid(exhaustPoint.position) && thrustForce != Vector3.zero) { //Thrust force on self rb.AddForceAtPosition(thrustForce, exhaustPoint.position); //Push force against anything hit by exhaust if (exhaustPushBodiesRange == 0) { return; } //Every 10th fixedupdate, scan if anything is hit by the exhaust. if (fixedUpdateCounter % 10 == 0) { exhaustPushTarget = null; exhaustPushPart = null; RaycastHit hit = new RaycastHit(); if (Physics.SphereCast(exhaustPoint.position, exhaustPushRadius, exhaustPoint.forward, out hit, exhaustPushBodiesRange)) { //if (hit.transform == body.transform) return; //ignore hitting self exhaustTargetDistanceFactor = Mathf.Max(1 - (hit.distance / exhaustPushBodiesRange), 0); //Scale effects down as distance increases exhaustPushPoint = hit.point; //If hit any interactable physics body, apply a force pushing away due to the exhaust. if (hit.transform.CompareTag("InteractablePhysBody")) { InteractablePhysBody other = hit.transform.GetComponent <InteractablePhysBody>(); if (!other.physicsReady) { return; //ignore if body is not set up properly yet } exhaustPushTarget = other; //keep track of this object until next scan } //if hit a part, apply heat. if (hit.collider.CompareTag("PhysPart")) { exhaustPushPart = hit.collider.GetComponentInParent <PhysPart>(); //keep track of part until next scan } } } //Apply force and heat to what we hit last scan every fixedupdate if (exhaustPushTarget != null) { Vector3 pushForce = -thrustForce * exhaustTargetDistanceFactor; exhaustPushTarget.rb.AddForceAtPosition(pushForce, exhaustPushPoint); if (exhaustPushPart) { exhaustPushPart.TakeDamage((exhaustPushHeatDamage * exhaustTargetDistanceFactor) * Time.fixedDeltaTime, DamageType.HEAT); } } } }
public static bool IsConnectedToPart(PhysPart startPart, PhysPart targetPart, bool drawDebugLines = false) { if (startPart == null || targetPart == null) { return(false); } List <PhysPart> visitedParts = new List <PhysPart>(); List <PhysPart> partsToVisit = new List <PhysPart>(); partsToVisit.Add(startPart); PhysPart currPart = partsToVisit[0]; bool foundConnection = false; while (partsToVisit.Count > 0) { if (partsToVisit[0] == null) { visitedParts.Add(partsToVisit[0]); partsToVisit.RemoveAt(0); currPart = partsToVisit[0]; //make next part currPart continue; } Vector3 prevPartPos = currPart.transform.position; currPart = partsToVisit[0]; if (drawDebugLines) { Debug.DrawLine(prevPartPos, currPart.transform.position, Color.green * 0.95f, 1.5f); } visitedParts.Add(currPart); partsToVisit.Remove(currPart); if (currPart == targetPart) { foundConnection = true; break; } else { foreach (PartConnection c in currPart.connections) { if (!visitedParts.Contains(c.toPart) && !partsToVisit.Contains(c.toPart)) { partsToVisit.Add(c.toPart); } } } } return(foundConnection); }
public PhysPart SetCurrPart(PhysPart p, bool recalcConnectedParts = true) { PhysPart oldPart = currPart; if (oldPart) //Deal with previously held part { foreach (Collider c in oldPart.GetComponentsInChildren <Collider>()) //make previously held part tangible again { //c.enabled = true; c.gameObject.layer = currPartTrueLayer; } lastObjRot = oldPart.transform.rotation; //save previous obj rotation } //Deal with held part transition currPart = p; if (recalcConnectedParts) { if (oldPart) //Reconnect old held part appropriately { oldPart.connections = CalculatePartConnections(oldPart); oldPart.RecalcConnections(true); } if (currPart) //Disconnect new held part { currPart.DisconnectLiteFromAllParts(); } MakeAllDisconnectedPartsGhosty(); } //Deal with currently held part if (p != null) { foreach (Collider c in currPart.GetComponentsInChildren <Collider>()) //make part being held intangible { //c.enabled = false; currPartTrueLayer = c.gameObject.layer; c.gameObject.layer = LayerMask.NameToLayer("Ignore Raycast"); } MakePartGhosty(currPart, true); //make curr part render ghosty } return(p); }
public void DisconnectPart(PhysPart part, float carryStress = 0f, bool lite = false) { if (part == null) { RecalcConnections(); return; } List <PartConnection> connectionsToRemove = new List <PartConnection>(); foreach (PartConnection c in connections) //remove connections from this to other { if (c.toPart == part) { connectionsToRemove.Add(c); } } while (connectionsToRemove.Count > 0) { connections.Remove(connectionsToRemove[0]); connectionsToRemove.RemoveAt(0); } foreach (PartConnection c in part.connections) //remove connections from other to this { if (c.toPart == this) { connectionsToRemove.Add(c); } } while (connectionsToRemove.Count > 0) { part.connections.Remove(connectionsToRemove[0]); connectionsToRemove.RemoveAt(0); } if (!lite) { UpdateTransformStructureIfDisconnected(); part.UpdateTransformStructureIfDisconnected(); } if (carryStress > 0) //carry leftover stress { part.ApplyStress(carryStress); } }
/// <summary> /// checks if the part is connected to another with connections which don't go through parts listed in invalidParts. /// </summary> public static bool IsConnectedToPartIgnoringInvalidParts(PhysPart startPart, PhysPart targetPart, PhysPart[] invalidParts, bool drawDebugLines = false) { if (startPart == null || targetPart == null) { return(false); } List <PhysPart> visitedParts = new List <PhysPart>(); visitedParts.AddRange(invalidParts); List <PhysPart> partsToVisit = new List <PhysPart>(); partsToVisit.Add(startPart); PhysPart currPart = partsToVisit[0]; bool foundConnection = false; while (partsToVisit.Count > 0) { Vector3 prevPartPos = currPart.transform.position; currPart = partsToVisit[0]; if (drawDebugLines) { Debug.DrawLine(prevPartPos, currPart.transform.position, Color.green, 1.5f); } visitedParts.Add(currPart); partsToVisit.Remove(currPart); if (currPart == targetPart) { foundConnection = true; break; } else { foreach (PartConnection c in currPart.connections) { if (!visitedParts.Contains(c.toPart)) { partsToVisit.Add(c.toPart); } } } } return(foundConnection); }
public List <PartConnection> CalculatePartConnections(PhysPart p) { if (p == currPart) { return(new List <PartConnection>()); //If part is currently held, it has no connections. } List <PartConnection> connections = new List <PartConnection>(); foreach (PhysPart otherP in currCraft.Parts) { if (otherP == p) { continue; //skip if checking against self } if (otherP == currPart) { continue; //skip if checking against currently held part } bool intersects = false; foreach (Collider c in p.colliders) //check for each collider of our part { foreach (Collider otherC in otherP.colliders) //and check against each collider of other part { if (c.bounds.Intersects(otherC.bounds)) { intersects = true; break; } } if (intersects) { break; } } if (intersects) { connections.Add(new PartConnection(otherP, p)); } } return(connections); }
private void OnCollisionEnter(Collision collision) { //Transfer collisions to appropriate parts PhysPart partHit = null; if (collision.contacts[0].thisCollider.GetComponent <PhysPart>()) { partHit = collision.contacts[0].thisCollider.GetComponent <PhysPart>(); } else if (collision.contacts[0].otherCollider.GetComponent <PhysPart>()) { partHit = collision.contacts[0].otherCollider.GetComponent <PhysPart>(); } if (partHit != null) { partHit.OnImpact(collision); } }
void MakePartGhosty(PhysPart p, bool ghosty) { MeshRenderer[] rends = p.GetComponentsInChildren <MeshRenderer>(); if (ghosty) { foreach (MeshRenderer r in rends) { r.material = GhostyMaterial; } } else { Material[] trueMats = p.GetComponent <EditorPartData>().trueRendMaterials; for (int i = 0; i < rends.Length; i++) { rends[i].material = trueMats[i]; } } p.mat_emissiveOn = false; //Material emission will need to be turned on again }
public void SetOriginPart(PhysPart p) { if (p == null) { Debug.LogError("Tried to set origin of craft \"" + name + "\" to null part.", this); return; } if (!p.transform.IsChildOf(transform)) { Debug.LogError("Tried to set origin of craft \"" + name + "\" to part \"" + p.name + "\", which does not belong to the craft.", p); return; } originPart = p; p.transform.SetAsFirstSibling(); if (Parts.Contains(p)) { Parts.Remove(p); } Parts.Insert(0, p); }
IEnumerator DestroyPartsCoroutine(List <PhysPart> parts, float timePerPart) { WaitForSeconds wait = new WaitForSeconds(timePerPart); while (parts.Count > 0) { //choose random part int index = Random.Range(0, parts.Count - 1); if (parts[index] == null) { parts.RemoveAt(index); continue; } //skip and remove if something went wrong //keep track of part, remove from list, destroy part PhysPart p = parts[index]; parts.RemoveAt(index); p.DestroyPart(0, true, PhysPart.DestructionType.GENERIC); yield return(wait); //wait specified delay until processing next part } gameObject.AddComponent <Autodestroy>().destroyTimer = 0.01f; //destroy this gameobject }
public void UpdatePhysParts(bool simpleRecalc = false) { Parts = new List <PhysPart>(GetComponentsInChildren <PhysPart>()); if (Parts.Count == 0) { if (!simpleRecalc) { DestroySelf(); } return; } if (!simpleRecalc) { //Disable all but the first AutoBalancer component AutoBalancer[] balancerParts = GetComponentsInChildren <AutoBalancer>(); for (int i = 0; i < balancerParts.Length; i++) { if (i == 0) { balancerParts[i].enabled = true; } else { balancerParts[i].enabled = false; } } //Destroy all invalid parts foreach (PhysPart p in Parts) { if (p.name.Contains("Invalid Part!")) { p.DestroyPart(); } } } originPart = Parts[0]; }
public PhysPart MakePartEditorFriendly(PhysPart p) { //Make it non-solid foreach (Collider c in p.GetComponentsInChildren <Collider>()) { c.isTrigger = true; } //Disable all components List <PartComponent> components = new List <PartComponent>(p.components); while (components.Count > 0) { components[0].enabled = false; components.RemoveAt(0); } p.enabled = false; //Remember materials p.gameObject.AddComponent <EditorPartData>().RememberRendMaterials(); return(p); }
public static MultipartPhysBody SpawnCraftFromBlueprint(CraftBlueprint bp, Vector3 position, Vector3 rotation) { //Set up transform structure before adding any parts etc. Transform t = new GameObject(bp.craftName).transform; //Main craft t.position = position; t.eulerAngles = rotation; t.SetParent(GameplayManager.GameplayTransform); Transform body = new GameObject("Body").transform; //Body (part holder) body.SetParent(t); body.localPosition = body.localEulerAngles = Vector3.zero; //Set up components t.gameObject.AddComponent <Rigidbody>(); MultipartPhysBody craft = t.gameObject.AddComponent <MultipartPhysBody>(); //Set up parts List <PhysPart> spawnedParts = new List <PhysPart>(); foreach (PartBlueprint p in bp.parts) { PhysPart part = p.SpawnPart(body); spawnedParts.Add(part); } //Set up part connections foreach (ConnectionBlueprint c in bp.connections) { spawnedParts[c.fromIndex].connections.Add(new PartConnection(spawnedParts[c.toIndex], spawnedParts[c.fromIndex])); } //Disable input until it gets overriden by a system which is responsible for this (player spawning, AI spawning, etc.) craft.SetBalancerInputActive(false); return(craft); }
private void Update() { if (currCraft != null) { //Shortcuts if (Input.GetKeyDown(KeyCode.C)) { PlayerManager.instance.cam.ReturnToOrigin(); CraftSpawnMenu.instance.SpawnCraftFromBlueprint(GetBlueprintFromCurrCraft()); ClearCurrCraft(); } if (Input.GetKeyDown(KeyCode.O)) { HighlightPart(currCraft.GetOriginPart(), Color.yellow); } //Temp if (Input.GetKeyDown(KeyCode.Alpha1)) { GrabPartFromList("StructuralCube0"); } if (Input.GetKeyDown(KeyCode.Alpha2)) { GrabPartFromList("Engine0"); } if (Input.GetKeyDown(KeyCode.Alpha0)) { GrabPartFromList("ControlChip0"); } //Part Actions Input if (canDoActions) { if (currPart != null) { if (Input.GetMouseButtonDown(0)) //Place { SetCurrPart(null); } if (Input.GetMouseButtonDown(1)) //Remove { currPart.transform.SetParent(null); //So it instantly is recognised as not a part anymore currPart.DestroyPartLite(); SetCurrPart(null, false); MakeAllDisconnectedPartsGhosty(); //In case destroyed part was the origin, make sure that parts connected to new origin are non-ghosty. } //Rotate if (Input.GetKeyDown(KeyCode.A)) { currPart.transform.Rotate(0, -15f, 0, Space.Self); } if (Input.GetKeyDown(KeyCode.D)) { currPart.transform.Rotate(0, 15f, 0, Space.Self); } if (Input.GetKeyDown(KeyCode.W)) { currPart.transform.Rotate(15f, 0, 0, Space.Self); } if (Input.GetKeyDown(KeyCode.S)) { currPart.transform.Rotate(-15f, 0, 0, Space.Self); } if (Input.GetKeyDown(KeyCode.Q)) { currPart.transform.Rotate(0, 0, -15f, Space.Self); } if (Input.GetKeyDown(KeyCode.E)) { currPart.transform.Rotate(0, 0, 15f, Space.Self); } if (Input.GetKeyDown(KeyCode.R)) { currPart.transform.eulerAngles = Vector3.zero; } } else if (currPart == null) { if (Input.GetMouseButtonDown(0)) { if (Input.GetKey(KeyCode.O)) //Set Origin { RaycastHit h = CastRayThroughMouse(); if (h.collider != null && h.collider.GetComponent <PhysPart>()) { PhysPart p = h.collider.GetComponent <PhysPart>(); currCraft.SetOriginPart(p); HighlightPart(p, Color.yellow); MakeAllDisconnectedPartsGhosty(); } } else if (Input.GetKey(KeyCode.LeftAlt)) //Clone { RaycastHit h = CastRayThroughMouse(); if (h.collider != null && h.collider.GetComponent <PhysPart>()) { PhysPart p = h.collider.GetComponent <PhysPart>(); PartBlueprint bp = p.GetBlueprint(); lastObjRot = p.transform.rotation; SpawnPartInHand(bp); } } else //Pick Up { RaycastHit h = CastRayThroughMouse(); if (h.collider != null && h.collider.GetComponent <PhysPart>()) { SetCurrPart(h.collider.GetComponent <PhysPart>()); } } } } } } }
protected virtual void Awake() //called as soon as object is instantiated { part = GetComponent <PhysPart>(); }
public PartConnection(PhysPart to, PhysPart from) { toPart = to; fromPart = from; }
private void Awake() { part = GetComponent <PhysPart>(); }
public PhysPart SpawnEditorPart(PartBlueprint bp) { PhysPart p = bp.SpawnPart(currCraft.transform.GetChild(0)); return(MakePartEditorFriendly(p)); }