Jump to content
Unity Insider Forum

Objecte per klick bewegen lassen


Noxen

Recommended Posts

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

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

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

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

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

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

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

So, ich hab nun mein ganzen Script nochmal etwas überarbeitet. Durch das ganze testen hatte ich kaum noch überblick :P

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

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

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

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...