Noxen Geschrieben 20. August 2014 Melden Share Geschrieben 20. August 2014 Hey, ich hab da mal ne doofe Frage Ich spiele zur Zeit einfach nur ein wenig mit Unity rum und versuche daraus zu lernen bzw neues zu lernen. Es geht mir im Moment um folgendes: ich habe ein Objekt, wenn ich auf dieses klicke kann ich eine "kugel" vor dem Objekt erstellen lassen. Wenn ich diese Kugel nun anklicke und dann irgendwo auf das Terrain, bewegt diese sich dorthin. Das funktioniert. Wenn ich nun aber 2 Kugeln habe, bewegen sich beide an diese Stelle... using UnityEngine; using System.Collections; public class cklick : MonoBehaviour { public GameObject kugel; RaycastHit hit; GameObject[] obj ; public GameObject[] unit; int manyUnits = 0; string clicked; void Update () { obj = GameObject.FindGameObjectsWithTag ("Building"); unit = GameObject.FindGameObjectsWithTag ("Unit"); manyUnits = unit.Length; if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit)){ if (hit.collider.name != null && hit.collider.name != "Terrain"){ clicked = hit.collider.name; } if (hit.collider.name == "Terrain" && clicked == "kugel(Clone)"){ move.newPos = hit.point; } } } } void OnGUI(){ GUI.Box (new Rect (900, 30, 200, 550), "Menue: "+ clicked); if (clicked == "Base") { if(GUI.Button (new Rect (910, 50, 70, 50), "Erstellen")){ Vector3 vec3 = new Vector3 (obj[1].transform.position.x+obj[1].transform.localScale.x/2+kugel.transform.localScale.x/2+1,obj[1].transform.position.y+kugel.transform.localScale.y/2+1, obj[1].transform.position.z); Instantiate(kugel, vec3, Quaternion.identity); move.newPos = vec3; } } if (clicked == "MoneyDrop") GUI.Button (new Rect(910,50,70,50),"Upgrade"); } } das Script "move" mit der Vector3 variablen "newPos" hängt am Kugelprefab. using UnityEngine; using System.Collections; public class move : MonoBehaviour { public static Vector3 newPos; //Vector3 nPos = new Vector3(newPos.x,newPos.y + transform.localScale.y/2 , newPos.z); void Update () { if(newPos != transform.position) transform.position = Vector3.Lerp (transform.position, new Vector3(newPos.x,newPos.y + transform.localScale.y/2 , newPos.z), Time.deltaTime); } } Wie bekomme ich das hin, dass ich jedes Object einzeln ansprechen kann? Achja und eine frage hab ich noch. Wie kann man (außer über einen Collider) feststellen, ob ein Object in der nähe ist? Ich habe mir RayCast mal angeschaut, damit kann man ja aber nur in eine richtung raycasten, oder? Vielen Dank schonmal im vorraus. Gruß Noxen Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Djeurissen Geschrieben 20. August 2014 Melden Share Geschrieben 20. August 2014 In deinem Script "move" hast du die static Variable newPos, wenn du nun move.newPos = Whatever machst weißt du der Variable newPos einen neuen Wert zu. http://msdn.microsoft.com/de-de/library/98f28cdx.aspx Dadurch das newPos static ist, greift jedes Script auf ein und diesselbe Variable zu. Dementsprechend sollte das static dort schonmal weg. Nun kannst du nicht mehr durch move.newPos auf die Variable zugreifen was auch gut so ist, immerhin weiß niemand welches "move" script du eigentlich meinst. Aber du hast immernoch deine hit variable und darüber kannst du auf dein "move" skript mit GetComponent zugreifen. Und nun, warum rufst du in Update die ganze Zeit "GameObject.FindGameObjectsWithTag ("Building");" auf? Das frisst ganz schön Performance, da Unity dafür durch alle Gameobjects rennen muss die zurzeit existieren. Ist es denn nötig die Anzahl an Gebäuden immer wieder zu updaten? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 20. August 2014 Autor Melden Share Geschrieben 20. August 2014 In deinem Script "move" hast du die static Variable newPos, wenn du nun move.newPos = Whatever machst weißt du der Variable newPos einen neuen Wert zu. http://msdn.microsof...y/98f28cdx.aspx Dadurch das newPos static ist, greift jedes Script auf ein und diesselbe Variable zu. Dementsprechend sollte das static dort schonmal weg. Nun kannst du nicht mehr durch move.newPos auf die Variable zugreifen was auch gut so ist, immerhin weiß niemand welches "move" script du eigentlich meinst. Aber du hast immernoch deine hit variable und darüber kannst du auf dein "move" skript mit GetComponent zugreifen. Klingt erstmal gut. Aber wie komm ich über Hit auf das move-script und an die Variable? Denn, wenn ich auf Terrain klicke hab ich ja ein Hit auf das Terrain... Und nun, warum rufst du in Update die ganze Zeit "GameObject.FindGameObjectsWithTag ("Building");" auf? Das frisst ganz schön Performance, da Unity dafür durch alle Gameobjects rennen muss die zurzeit existieren. Ist es denn nötig die Anzahl an Gebäuden immer wieder zu updaten? Naja, man sollte auch weitere Gebäude bauen können. Irgendwann mal .... In erster Linie war es aber bisher nur zu Testzwecken gedacht, um damit etwas herrum zu Experimentieren. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Djeurissen Geschrieben 20. August 2014 Melden Share Geschrieben 20. August 2014 Ja du fragst doch zuvor ab, ob du ein Objekt mit dem Namen Kugel{Clone} angeklickt hast, speicher doch anstatt des Namens einfach das Gameobject, dadurch das newPos public ist wirst du dann mit GetComponent an move kommen und in move änderst du dann newPos Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 20. August 2014 Autor Melden Share Geschrieben 20. August 2014 Ich habs jetzt ne Weile versucht, hab aber keine Ahnung, wie ich das anstellen soll.... Denn, dass ganze muss ja Dynamisch sein, dass ich jederzeit wieder eine Erstellen und so benutzen kann.... Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Hrungdak Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Ich habs jetzt ne Weile versucht, hab aber keine Ahnung, wie ich das anstellen soll.... Denn, dass ganze muss ja Dynamisch sein, dass ich jederzeit wieder eine Erstellen und so benutzen kann.... Ich denke, dass irgendwas das zentrale Objekt ist, Spieler oder so? Die ausgewählte Kugel wird im PlayerController einfach in einer Variablen gespeichert. private GameObject selectedKugel; Wenn du jetzt eine Kugel anklickst, wird diese im PlayerController als aktiv gespeichert. Beim Klick auf das Terrain schickst du der selektierten Kugel den Move-Befehl. Du kannst der Kugel z.B. mit SendMessage Nachrichten schicken, also z.B. selectedKugel.SendMessage("Move", newPos); Wenn ich deinen Code oben richtig interpretiere, bewegen sich alle Kugeln auf eine neu erzeugte Kugel zu? Das static muss weg, wie schon Djeurissen sagte. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Jopp, das static habe ich bereits entfernt. Hab es jetzt soweit umgeschrieben und mich mit SendMessage etwas befasst. Damit kann ich zwar auf eine Methode eines Objectes zugreifen: selectedKugel.SendMessage("Move", hit.point); void Move(Vector3 pos){ if(pos != transform.position) transform.position = Vector3.Lerp (transform.position, new Vector3(pos.x,pos.y + transform.localScale.y/2 , pos.z), Time.deltaTime); } Und das macht, was es erstmal soll. Ich kann alle (auch nachträglich erzeugten) Objecte extra bewegen. Dummerweise bewegen sich die Objecte immer nur bei "Klick" und nicht konstant an diese position. Habe es schon mit einer while-Schleife versucht: void Move(Vector3 pos){ while(pos != transform.position) transform.position = Vector3.Lerp (transform.position, new Vector3(pos.x,pos.y + transform.localScale.y/2 , pos.z), Time.deltaTime); } Hängt sich Unity auf Und in Update kann ich ja keine Parameter angeben ( Update(Vector3 pos) ). Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Hrungdak Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Wenn ich weiter darüber nachdenke, würde ich der Kugel mit SendMessage so was schicken wie SendMessage("Gehezu", position); Im Update der Kugel stellst du fest, dass die Kugel die Endposition noch nicht erreicht hat. Daraufhin rufst du die Move-Funktion auf, die dann mit der entsprechenden Kugelgeschwindigkeit auf die Endposition zurollt. While ist hier falsch. Einfach mit transform.Transform die Kugel in Richtung Endpunkt bewegen. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Was genau hat euch von SendMessage überzeugt? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Hrungdak Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Was genau hat euch von SendMessage überzeugt? Mein beschränktes Wissen über Unity. Da gibts natürlich mehr und vermutlich bessere Methoden. Aber Performance ist atm nicht das Problem von Noxen, denke ich. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Was genau hat euch von SendMessage überzeugt? Es funktioniert schonmal besser als vorher Aber wenn du eine bessere Idee hast, bin ganz Ohr Wenn ich weiter darüber nachdenke, würde ich der Kugel mit SendMessage so was schicken wie SendMessage("Gehezu", position); Im Update der Kugel stellst du fest, dass die Kugel die Endposition noch nicht erreicht hat. Daraufhin rufst du die Move-Funktion auf, die dann mit der entsprechenden Kugelgeschwindigkeit auf die Endposition zurollt. While ist hier falsch. Einfach mit transform.Transform die Kugel in Richtung Endpunkt bewegen. Ja, aber das is dann das selbe, wie ich es habe. "Gehezu" ist nur eine Methode in der ich mit "position" den Parameter direkt übergebe. Demnach kann ich ja in Update nicht auf "position" zugreifen, oder? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 So, ich hab nun mein ganzen Script nochmal etwas überarbeitet. Durch das ganze testen hatte ich kaum noch überblick Jetzt funktioniert alles bestens. Bekomme jkedoch eine Fehlermeldung bei "selected.name == "Baracke" ".Er sagt: "NullReferenceException". Aber, es funktioniert^^ Da ich bereits anfragen hatte, wenn es funktioniert, hier der Code: private GameObject selected; private GameObject chosen; void Update () { if (Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit)){ if (hit.collider.name != "Terrain"){ selected = hit.collider.gameObject; } if (hit.collider.name == "Terrain" && selected.tag == "Unit"){ selected.GetComponent<move>().pos = hit.point; } } } } void OnGui(){ GUILayout.BeginArea (new Rect (900, 50, 200, 550), "Menue"); if (selected.name == "Baracke") { if(GUILayout.Button ("Kugel")) CreateUnit(kugel); GUILayout.EndArea (); } void CreateUnit(GameObject unit){ Vector3 vec3 = new Vector3 (selected.transform.position.x+selected.transform.localScale.x/2+kugel.transform.localScale.x/2+1,selected.transform.position.y+kugel.transform.localScale.y/2, selected.transform.position.z); chosen = Instantiate(unit, vec3, Quaternion.identity) as GameObject; chosen.GetComponent<move> ().pos = vec3; } Und die Move an jenes Prefab gehängt: using UnityEngine; using System.Collections; public class move : MonoBehaviour { public Vector3 pos; void Update () { if(pos != transform.position) transform.position = Vector3.Lerp (transform.position, new Vector3(pos.x,pos.y + transform.localScale.y/2 , pos.z), Time.deltaTime); } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 selected kann und ist nicht zugewisen, daher kommt diese Fehlermeldung, bis selected einen Wert bekommt. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Ah, ok, habs grad gesehen. Ist dann ja nicht ganz so wild. Eine frage habe ich nun aber noch: Wie kann man (außer über einen Collider) feststellen, ob ein Object in der nähe ist? Ich habe mir RayCast mal angeschaut, damit kann man ja aber nur in eine richtung raycasten, oder? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Du hast da mehrere Möglichkeiten, entweder checkst du alle Collider ob sie in der Nähe sind oder du nimmst einen Sphere Test: http://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Naja, idealerweise wüsste ich gern direkt die Vector3 koordinaten, wenn er etwas "entdeckt" hat, damit die "Einheit" zb darauf schießen kann Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Die kannst du durch die oben genannte Methode bekommen. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Jopp, Habs rausbekommen, wie Wieso schießt der aber nicht direct in die Richtung? Wenn ich die Kugel in die nähe bewege, schießt das Object, aber nicht dahin, wohin es soll... float radius = 10f; float timer = 2f; Vector3 direction; public GameObject bullet; void Update () { timer -= Time.deltaTime; if(timer <= 0){ Collider[] hitColliders = Physics.OverlapSphere(transform.position, radius); int i = 0; while (i < hitColliders.Length) { if(hitColliders[i].tag == "Unit"){ direction = new Vector3(hitColliders[i].transform.position.x,hitColliders[i].transform.position.y,hitColliders[i].transform.position.z); Shoot(direction); } i++; } timer = 2f; } } void Shoot(Vector3 direction){ GameObject shotBullet = Instantiate (bullet, transform.position, Quaternion.identity) as GameObject; shotBullet.rigidbody.AddForce (direction); } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Weil deine direction keine Richtung sondern ein Punkt ist. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Genau und auf diesen Punkt soll er quasi Schießen^^ Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 21. August 2014 Melden Share Geschrieben 21. August 2014 Dann musst du diesen Punkt in eine Richtung vom Schützen zum Ziel umwandeln. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 21. August 2014 Autor Melden Share Geschrieben 21. August 2014 Jo, Wüsst ich aber nicht annähernd, wie ich das mache... oder ich drehe das ganze Objekt in die Zielrichtung... Da weiß ich aber auch noch nicht ... Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Hrungdak Geschrieben 22. August 2014 Melden Share Geschrieben 22. August 2014 Jo, Wüsst ich aber nicht annähernd, wie ich das mache... oder ich drehe das ganze Objekt in die Zielrichtung... Da weiß ich aber auch noch nicht ... Schau dir mal Vector3.RotateTowards() an. Vielleicht hilft dir das weiter. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Mark Geschrieben 22. August 2014 Melden Share Geschrieben 22. August 2014 Ich würde einfach Richtung = (Ziel - Start).normalized machen. RotateTowards ist aber auch ganz nett. Nur für den Fall hier nicht so ganz. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Noxen Geschrieben 22. August 2014 Autor Melden Share Geschrieben 22. August 2014 Also, es funktionieren beide Varianten. Erkenne auch direkt keinen Unterschied, außer, dass ich an Code spare Vielen Dank an euch. Das hat mir sehr weitergeholfen Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.