Jump to content
Unity Insider Forum

Problem beim Ändern der Koordinaten


Recommended Posts

Hallo :)

Ich habe folgendes Problem:

 

public RawImage crosshair;
[serializeField]
Turret_Control turretControl;
public int offset;
public float positionX;
public float positionY;
public float positionZ;

void Start () {

  offset = 23;

  positionX = turretControl.gun.transform.position.x;
  positionY = turretControl.gun.transform.position.y + offset;
  positionZ = turretControl.gun.transform.position.z;
}


void Update () {


  positionX = turretControl.gun.transform.position.x;
  positionY = turretControl.gun.transform.position.y + offset;
  positionZ = turretControl.gun.transform.position.z;

  crosshair.transform.position.x = positionX;
  crosshair.transform.position.y = positionY;
  crosshair.transform.position.z = positionZ;

}
 

 

Ziel vom ganzen Spaß soll sein, dass das Fadenkreuz (crosshair) der Position des Geschätzes folgt.

Leider bekomme ich beim Update Probleme, da er anscheinend die Position nicht verändern kann?

Ich weiß leider nicht warum, und ich komme auch einfach nicht drauf :(

 

Es kommt bei den drei unteren Codezeilen im Update folgende Fehlermeldung:

"CS1612: Cannot modify a value type return value of `UnityEngine.Transform.position'. Consider storing the value in a temporary variable"

 

Ich habe doch Variablen gesetzt. Nur möchte ich doch die Position verändern, und keine Variable.

Weil selbst wenn ich eine Variable änder, letzten Endes muss ich doch eh die Position verändern.

 

Vielleicht bin ich auch einfach nur zu blöd^^

Naja, vielleicht könnt ihr mir ja helfen, wahrscheinlich ist dass ein ganz einfacher und peinlicher Fehler, ist ja genau mein Stil :D

 

LG Tobi

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich vermute mal dein "Crosshair" steckt in einem Canvas.

Wenn es noch nicht so ist, erstelle ein Canvas und packe da dein RawImage hinein und skaliere es auf die Größe des Canvas.

Das Problem ist nicht ganz so einfach, und ich habe dir mal eine Funktion rausgesucht:

 

private Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
	 //Vector position (percentage from 0 to 1) considering camera size.
	 //For example (0,0) is lower left, middle is (0.5,0.5)
	 Vector2 temp = camera.WorldToViewportPoint(position);

	 //Calculate position considering our percentage, using our canvas size
	 //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
	 temp.x *= canvas.sizeDelta.x;
	 temp.y *= canvas.sizeDelta.y;

	 //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
	 //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
	 //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) ,
	 //returned value will still be correct.

	 temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
	 temp.y -= canvas.sizeDelta.y * canvas.pivot.y;

	 return temp;
 }

 

Du brauchst nun noch das RectTransform deines Canvas:

RectTransform myRT = myCanvas.GetComponent<RectTransform>;

 

Dann noch deine Camera und dann rufst du es auf:

RectTransform myRT = myCanvas.GetComponent<RectTransform>;
Vector2 newPos = WorldToCanvasPosition(myRT, myCamera, turretControl.gun.transform.position);
myRT.anchoredPosition =  newPos;

 

Mache dir am besten 2 public Variablen, wo du dein GUI Canvas und deine Maincamera draufziehst:

public Canvas myCanvas;
public Camera myCamera;

 

Hier noch eine andere "ähnliche" Lösung:

http://answers.unity3d.com/questions/799616/unity-46-beta-19-how-to-convert-from-world-space-t.html

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wow :)

Das muss ja echt viel Arbeit gewesen sein.

Tausend Danke :)

 

Ich werde mir dass mal morgen genauer anschauen (möchte das ja auch verstehen

und nicht nur abschreiben)^^

 

Mein Crossfire steckt schon in einem Canvas. Allerdings sind auf dem Canvas noch andere

RawImage Objekte. Weiß nicht ob das was ausmacht.

 

LG Tobi :D:lol:

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wow :)

Das muss ja echt viel Arbeit gewesen sein.

Tausend Dank :)

 

Ich werde mir dass mal morgen genauer anschauen (möchte das ja auch verstehen

und nicht nur abschreiben)^^

 

Mein Crossfire steckt schon in einem Canvas. Allerdings sind auf dem Canvas noch andere

RawImage Objekte. Weiß nicht ob das was ausmacht.

 

LG Tobi :D:lol:

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sollte egal sein, es verschiebt ja eh das ganze Canvas samt Inhalt (ansonsten das Fadenkreuz eben in einen eigenen Canvas stecken). Ist aber ungetestet, also ich hoffe dass die Berechnungen in der Funktion dann auch zum gewünschten Ergebnis kommen, ansonsten muss man da noch einmal an den Canvaseinstellungen oder der Funktion selbst "schrauben" bis alles passt :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hey Ikarus,

 

ich seh da ehrlich gesagt keinen Unterschied^^

Und es macht übrigens auch keinen, die unteren drei sind doch das Problem ;)

 

 crosshair.transform.position.x = positionX;
 crosshair.transform.position.y = positionY;
 crosshair.transform.position.z = positionZ;

 

Achso, hatte ich überlesen :)

 

Und wie steht's mit

crosshair.transform.position = new Vector3(positionX,positionY,positionZ);

Das sollte aber klappen. Zumindest interpretiere ich die Fehlermeldung so, wenn sich das auf die drei Zeilen bezieht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

transform.position.xyz ist in C# readonly, du darfst das nicht so überschreiben.

Du darfst transform.position nur als ganzes mit einem neuen Vector3 setzen so wie Ikarus es im letzten Post vorgeschlagen hat.

 

In UnityScript geht das übrigens, da macht der Compiler das für dich aber sowas find ich irgendwie immer doof ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Morgen :D

 

Danke Tiwaz, da wäre ich nicht drauf gekommen^^

 

@Zer0Cool:

Ich wollte mir das mal genauer anschauen, was du da geschrieben hast.

Ich werde das mal versuchen, muss jedoch erwähnen dass ich meinen Code umgeschrieben habe.

 

Nachdem das Crosshair zuvor auf dem Canvas des Main_UI steckte habe ich für das Crossfire nun ein eigenes Canvas gemacht. Allerdings habe ich dort auch die Nachladeanzeige gemacht, da die sich ja immer neben dem Crossfire befinden soll...

 

Wollte das nur erwähnen, denke dass das vielleicht wichtig ist, da der Inhalt ja genauso groß wie das Canvas sein soll?

LG :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also ich muss ganz ehrlich sagen dass das ziemlich kompliziert ist.

Ich bin mir nicht sicher ob ich das korrekt verstehe.

 

Ich hab das Script nun erstmal so:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CrossfireManager : MonoBehaviour {

public Canvas myCanvas;
public Camera myCamera;

[serializeField]
IngameUIManager uiManager;

[serializeField]
Turret_Control turretControl;

public RawImage crosshair;

// Fadenkreuz
public Texture crosshair_armed;
public Texture crosshair_disarmed;

// Nachladeanzeige
public Text reload_time_text; // Nachladezeit-Anzeige

void Start () {

 crosshair.texture = (Texture)crosshair_disarmed;
 turretControl.reloading = true;
 uiManager.is_armed = false;
 reload_time_text.enabled = false;

 // Test Anfang
 public Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
			 //Vector position (percentage from 0 to 1) considering camera size.
			 //For example (0,0) is lower left, middle is (0.5,0.5)
			 Vector2 temp = camera.WorldToViewportPoint(position);
			 //Calculate position considering our percentage, using our canvas size
			 //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
			 temp.x *= canvas.sizeDelta.x;
			 temp.y *= canvas.sizeDelta.y;
			 //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
			 //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
			 //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) ,
			 //returned value will still be correct.
			 temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
			 temp.y -= canvas.sizeDelta.y * canvas.pivot.y;

 RectTransform myRT = myCanvas.GetComponent<RectTransform>;

 Vector2 newPos = WorldToCanvasPosition(myRT, myCamera, turretControl.gun.transform.position);
 myRT.anchoredPosition =  newPos;
			 return temp;
	 }
 // Test Ende
}

void Update () {

 WorldToCanvasPosition();

 if(uiManager.is_armed == true) {

  reload_time_text.enabled = true;
  if(turretControl.reloadTime - turretControl.timeSinceReload > 0) {

   reload_time_text.text = "Reloading: " + Mathf.Round((turretControl.reloadTime - turretControl.timeSinceReload)) + "s";

 }
 if(turretControl.reloadTime - turretControl.timeSinceReload <= 0) {

   reload_time_text.color = Color.green;
   reload_time_text.text = "Loaded";

  }
 if(uiManager.is_armed == false) {

  reload_time_text.enabled = false;

 }

}

}
}

 

Bei folgenden Fehlermeldungen:

(38,22): error CS1525: Unexpected symbol `public
(66,14): error CS0116: A namespace can only contain types and namespace declarations
(94,1): error CS8025: Parsing error

 

Ich weiß zwar was gemeint ist, nur kann ich damit nichts anfangen. Also zumindest mit der ersten Fehlermeldung nicht.

Wie gesagt, da ich leider das Script nicht ganz verstehe ist es schwer die Fehler zu korrigieren, zumindest so dass das Script am Ende funktioniert.

 

LG Tobi

Link zu diesem Kommentar
Auf anderen Seiten teilen

Okay, hab die Funktion mal außerhalb der Start() und Update() geparkt.

Allerdings geht dann wenn ich die Funktion in der Update bzw. Start aufrufen möchte das void nicht, ich denke das hat damit zu tun dass natürlich das "temp" zurückt gegeben wird ("return temp;")

 

public class CrossfireManager : MonoBehaviour {

public Canvas myCanvas;
public Camera myCamera;

[serializeField]
IngameUIManager uiManager;

[serializeField]
Turret_Control turretControl;

public RawImage crosshair;

// Fadenkreuz
public Texture crosshair_armed;
public Texture crosshair_disarmed;

// Nachladeanzeige
public Text reload_time_text; // Nachladezeit-Anzeige

void Start () {

 crosshair.texture = (Texture)crosshair_disarmed;
 turretControl.reloading = true;
 uiManager.is_armed = false;
 reload_time_text.enabled = false;

void Update () {

 //WorldToCanvasPosition();

 if(uiManager.is_armed == true) {

  reload_time_text.enabled = true;
  if(turretControl.reloadTime - turretControl.timeSinceReload > 0) {

   reload_time_text.text = "Reloading: " + Mathf.Round((turretControl.reloadTime - turretControl.timeSinceReload)) + "s";

  }
  if(turretControl.reloadTime - turretControl.timeSinceReload <= 0) {

   reload_time_text.color = Color.green;
   reload_time_text.text = "Loaded";

  }
  if(uiManager.is_armed == false) {

   reload_time_text.enabled = false;

  }

 }

}
// Test Anfang
 public Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
			 //Vector position (percentage from 0 to 1) considering camera size.
			 //For example (0,0) is lower left, middle is (0.5,0.5)
			 Vector2 temp = camera.WorldToViewportPoint(position);
			 //Calculate position considering our percentage, using our canvas size
			 //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
			 temp.x *= canvas.sizeDelta.x;
			 temp.y *= canvas.sizeDelta.y;
			 //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
			 //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
			 //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) ,
			 //returned value will still be correct.
			 temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
			 temp.y -= canvas.sizeDelta.y * canvas.pivot.y;

 RectTransform myRT = myCanvas.GetComponent<RectTransform>;

 Vector2 newPos = WorldToCanvasPosition(myRT, myCamera, turretControl.gun.transform.position);
 myRT.anchoredPosition =  newPos;
			 return temp;
	 }
 // Test Ende
}
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was genau bedeutet das:

 

void Start () {

 crosshair.texture = (Texture)crosshair_disarmed;
 turretControl.reloading = true;
 uiManager.is_armed = false;
 reload_time_text.enabled = false;

void Update () {

 

Ich persönlich bevorzuge ja die Schreibweise, in der man sieht, was auf und zu ist, wird aber leider nicht unterstützt vom Editor bzw. falls doch, weiss ich nicht wie.

 

void Start ()
{
 crosshair.texture = (Texture)crosshair_disarmed;
 turretControl.reloading = true;
 uiManager.is_armed = false;
 reload_time_text.enabled = false;

void Update ()
{

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das ist für verschiedene Dinge.

reload_time_text ist einfach nur die Anzeige der Nachladezeit.

is_armed aus dem uiManager ist einfach nur dein boolean ob die Waffen aktiviert wurden.

reloading hat ebenfalls damit zu tun.

Das ganz oben crosshair.texture ändert dann einfach nur die Textur.

Das ist da mit drin, weil das halt auf dem Canvas ist.

Das Canvas zeigt einmal das Fadenkreuz und einmal die Nachladezeit an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Achso, ich habe den Fehler gefunden.

Ich habe allerdings auch den Code mal auskommentiert, weiß nicht ob das überhaupt so richtig "abgeschrieben" ist^^

Hier nochmal das Script:

 

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CrossfireManager : MonoBehaviour {

public Canvas myCanvas;
public Camera myCamera;

[serializeField]
IngameUIManager uiManager;

[serializeField]
Turret_Control turretControl;

public RawImage crosshair;

// Fadenkreuz
public Texture crosshair_armed;
public Texture crosshair_disarmed;

// Nachladeanzeige
public Text reload_time_text; // Nachladezeit-Anzeige

void Start () {

 crosshair.texture = (Texture)crosshair_disarmed;
 turretControl.reloading = true;
 uiManager.is_armed = false;
 reload_time_text.enabled = false;

}

void Update () {

 //WorldToCanvasPosition();

 if(uiManager.is_armed == true) {

  reload_time_text.enabled = true;
  if(turretControl.reloadTime - turretControl.timeSinceReload > 0) {

   reload_time_text.text = "Reloading: " + Mathf.Round((turretControl.reloadTime - turretControl.timeSinceReload)) + "s";

  }
  if(turretControl.reloadTime - turretControl.timeSinceReload <= 0) {

   reload_time_text.color = Color.green;
   reload_time_text.text = "Loaded";

  }
  if(uiManager.is_armed == false) {

   reload_time_text.enabled = false;

  }

 }

}
/* Test Anfang
 public Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
			 //Vector position (percentage from 0 to 1) considering camera size.
			 //For example (0,0) is lower left, middle is (0.5,0.5)
			 Vector2 temp = camera.WorldToViewportPoint(position);
			 //Calculate position considering our percentage, using our canvas size
			 //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
			 temp.x *= canvas.sizeDelta.x;
			 temp.y *= canvas.sizeDelta.y;
			 //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
			 //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
			 //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) ,
			 //returned value will still be correct.
			 temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
			 temp.y -= canvas.sizeDelta.y * canvas.pivot.y;

 RectTransform myRT = myCanvas.GetComponent<RectTransform>;

 Vector2 newPos = WorldToCanvasPosition(myRT, myCamera, turretControl.gun.transform.position);
 myRT.anchoredPosition =  newPos;
			 return temp;
	 }
  Test Ende */
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hoffe wir können diese doch ziemlich lange Thema dann jetzt bald als gelöst betrachten^^

So ganz kompliziert ist dass dann am Ende doch nicht, zumindest wenn man es erstmal verstanden hat und die fehlende "()" ergänzt hat^^

 

Also die Funktion selbst scheint zu laufen, zumindest gibt sie mir keine Fehler im Compiler wieder.

Eventuell muss ich noch schauen, ob das so passt dass der zwei Objekte auf dem Canvas sind, mal schauen.

 

Ich habe nur noch ein Problem beim aufrufen der Funktion in Update():

WorldToCanvasPosition();

Dieser Fehlercode kommt dann:

"CS1501: No overload for method `WorldToCanvasPosition' takes `0' arguments"

 

Gut, die Fehlermeldung ist insofern klar, dass ich der Funktion etwas übergeben muss.

genauer genommen natürlich die Variablen die am Anfang der Funktion in den () genannt werden.

 

Nur, irgendwie klappt das nicht. Dann kann er immer irgendwas nicht umwandeln oder es kommen sonstwie komische Fehler raus.

"WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position);"

So dachte ich mir das, nur dann ist "canvas" ein "unexpected symbol"...

Jedenfalls, egal wie ich die fülle, irgendwie klappt das nicht:

Daher die Frage, und hoffentlich die letzte zu dem Thema^^:

Was kommt da rein?

 

Hier nochmal die Funktion:

public Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
			 //Vector position (percentage from 0 to 1) considering camera size.
			 //For example (0,0) is lower left, middle is (0.5,0.5)
			 Vector2 temp = camera.WorldToViewportPoint(position);
			 //Calculate position considering our percentage, using our canvas size
			 //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
			 temp.x *= canvas.sizeDelta.x;
			 temp.y *= canvas.sizeDelta.y;
			 //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
			 //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
			 //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) ,
			 //returned value will still be correct.
			 temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
			 temp.y -= canvas.sizeDelta.y * canvas.pivot.y;

 RectTransform myRT = myCanvas.GetComponent<RectTransform>();

 Vector2 newPos = WorldToCanvasPosition(myRT, myCamera, turretControl.gun.transform.position);
 myRT.anchoredPosition =  newPos;
			 return temp;
	 }

 

Danke schon mal für die Hilfe :)

Ich glaube ich kann sagen dass ich alleine niemals so weit gekommen wäre.

 

Liebe Grüße,

Tobi :)

 

Edit: Ich muss noch erwähnen, falls ich die hier vorher erstellen muss:

"RectTransform canvas, Camera camera, Vector3 position", dass habe ich nicht gemacht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du hast zu viel in die Funktion gesteckt, die Funktion war:

private Vector2 WorldToCanvasPosition(RectTransform canvas, Camera camera, Vector3 position) {
	 //Vector position (percentage from 0 to 1) considering camera size.
	 //For example (0,0) is lower left, middle is (0.5,0.5)
	 Vector2 temp = camera.WorldToViewportPoint(position);
	 //Calculate position considering our percentage, using our canvas size
	 //So if canvas size is (1100,500), and percentage is (0.5,0.5), current value will be (550,250)
	 temp.x *= canvas.sizeDelta.x;
	 temp.y *= canvas.sizeDelta.y;
	 //The result is ready, but, this result is correct if canvas recttransform pivot is 0,0 - left lower corner.
	 //But in reality its middle (0.5,0.5) by default, so we remove the amount considering cavnas rectransform pivot.
	 //We could multiply with constant 0.5, but we will actually read the value, so if custom rect transform is passed(with custom pivot) ,
	 //returned value will still be correct.
	 temp.x -= canvas.sizeDelta.x * canvas.pivot.x;
	 temp.y -= canvas.sizeDelta.y * canvas.pivot.y;
	 return temp;
 }

 

 

Und dann solltest du die Funktion so verwenden:

void Update () {
 RectTransform myRT = myCanvas.GetComponent<RectTransform>();
 Vector2 newPos = WorldToCanvasPosition(myRT, myCamera, turretControl.gun.transform.position);
 myRT.anchoredPosition =  newPos;
 ...
 ...
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Oh Super danke :)

Ich habe mich länger nicht gemeldet, weil ich entschieden habe

dass es besser wäre mich erst etwas um meine C#-Kenntnisse

zu kümmern.

 

Ich komme ja eigentlich eher aus der Designer-Ecke, aber schaden kann es nicht.

Sonst hätte ich hier sicherlich noch alles vollgepostet^^

 

Dennoch finde ich es toll dass dennoch selbst nach so lange Pause nach geantwortet wird.

Ich werde den Code morgen implementieren.

 

Danke nochmal :)

Liebe Grüße ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...