示例#1
0
    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);
    }
示例#2
0
    public PhysPart SpawnPartInHand(PartBlueprint bp)
    {
        PhysPart p = SetCurrPart(SpawnEditorPart(bp));

        p.transform.rotation = lastObjRot;
        return(p);
    }
示例#3
0
    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());
    }
示例#4
0
 public void HighlightPart(PhysPart p, Color c)
 {
     if (p == null)
     {
         return;
     }
     p.gameObject.AddComponent <Proxy_HighlightPart>().HighlightPart(c);
 }
示例#5
0
    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);
                }
            }
        }
    }
示例#6
0
    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);
    }
示例#7
0
    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);
    }
示例#8
0
    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);
        }
    }
示例#9
0
    /// <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);
    }
示例#10
0
    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);
    }
示例#11
0
    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);
        }
    }
示例#12
0
 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
 }
示例#13
0
    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
    }
示例#15
0
    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];
    }
示例#16
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);
    }
示例#17
0
    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);
    }
示例#18
0
    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>());
                            }
                        }
                    }
                }
            }
        }
    }
示例#19
0
 protected virtual void Awake() //called as soon as object is instantiated
 {
     part = GetComponent <PhysPart>();
 }
示例#20
0
 public PartConnection(PhysPart to, PhysPart from)
 {
     toPart   = to;
     fromPart = from;
 }
 private void Awake()
 {
     part = GetComponent <PhysPart>();
 }
示例#22
0
    public PhysPart SpawnEditorPart(PartBlueprint bp)
    {
        PhysPart p = bp.SpawnPart(currCraft.transform.GetChild(0));

        return(MakePartEditorFriendly(p));
    }