Jump to content
Unity Insider Forum

Raycast and NameToLayer


MustafGames

Recommended Posts

Gruß,

habe leider vergessen wie das nochmal war, mit dem LayerMask Zeug.

Ich dachte es wäre so richtig:

RaycastHit2D hit = Physics2D.Raycast(pos, dir, range, 1 << LayerMask.NameToLayer(layer));
Physics2D.OverlapBox(pos, scale, 0, 1 << LayerMask.NameToLayer(layer));

Wenn man das "1 <<" weglässt was passiert dann?

RaycastHit2D hit = Physics2D.Raycast(pos, dir, range, LayerMask.NameToLayer(layer));
Physics2D.OverlapBox(pos, scale, 0, LayerMask.NameToLayer(layer));

Beim prüfen von 2 oder 3 verschiedenen Layern was macht man da?

 

MfG Mustaf

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nimm statt NameToLayer einfach GetMask ;)

Benutze das aber lieber einmal am Anfang und nicht jeden Frame immer wieder. Speichere dir das Ergebnis ab und stopfe es direkt in den Raycast-Aufruf.

Da du aber danach gefragt hast, zur Erklärung: NameToLayer gibt dir den Index deines Layers zurück, also 0, 1, 2, 3, 4, ... Das ist aber keine LayerMask. Eine LayerMask ist, wie der Name "Maske" schon suggeriert, eine Bitmaske, wo bei einer Zahl (die ja aus einer Reihe Bits, also Nullen und Einsen, besteht) jedes Bit als ein Boolean (1= Ja bzw. 0 = Nein) gewertet wird.

Das folgende ist mal aus dem Stehgreif vereinfacht, aber bezüglich der tatsächlichen Werte vielleicht nicht ganz exakt. Ist halt nur zur Veranschaulichung. Ich nutze auch einfach mal nur 8 Bits ohne Vorzeichen statt 32.

Die LayerMask, die nur den Layer 0 beinhaltet, sieht also dann so aus: 00000001.
Layer 1 wäre 00000010.
Layer 2 wäre 00000100.
Layer 3 wäre 00001000.

Das X-te Bit von rechts sagt also aus, ob Layer Nummer X in der LayerMask angeschaltet ist. Deshalb auch das "1 <<".
Die Zahl 1 sieht mit 8 Bits so aus: 00000001.
"X << Y" shiftet die Bits der Zahl X um Y Bits nach links.
"1 << 3" bedeutet also, dass die 1 um 3 Stellen nach links geshiftet wird, und es kommt heraus: 00001000. Das ist eine gültige LayerMask, wo der dritte (also entsprechend der 3, wenn man von 0 anfängt zu zählen) Layer an und der Rest aus ist.

Wenn du das "1 <<" weglässt, dann passiert das alles nicht, sondern die Zahl selbst wird betrachtet. Und eine 3 sieht in Bits so aus: 00000011. Das Entspricht der LayerMask für Layer 0 und 1, und nicht Layer 3.

Die LayerMask mit Layern 0 und 3 wäre jetzt 00001001. Um diese LayerMask zu bauen, müsstest du die LayerMasks für Layer 0 und Layer 3 bauen und diese dann mit | (bitweises Oder) kombinieren. | nimmt die Bits von den Zahlen auf beiden Seiten und rechnet für das Ergebnis-Bit 1, wenn eines der beiden Bits 1 ist, sonst 0.

0 |    0 |    1 |    1 |
0      1      0      1
-      -      -      -  
0      1      1      1

Wenn wir damit also 00000001 und 00001000 zusammenrechnen:

00000001 |
00001000
--------
00001001

Und damit haben wir das, was wir wollen. Der Code wäre also

1 << LayerMask.NameToLayer("Eins") |
1 << LayerMask.NameToLayer("Zwei") |
1 << LayerMask.NameToLayer("Drei") |
  ...

Aber zum Glück ist das genau das, was GetMask schon macht, und damit sind wir wieder bei meiner anfänglichen Aussage: Finger weg von NameToLayer. Da GetMask aber params benutzt, benutze die Methode nur einmal am Anfang und speichere dir das Ergebnis. Sie öfter aufzurufen erzeugt unnötigen Müll im Speicher.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, dafür ist die Methode genau richtig.

Jeden Frame die Abfrage ausführen ist okay, aber nimm halt einen gespeicherten Wert.

Statt

private void Update()
{
  ...Physics.Raycast( ..., LayerMask.GetMask(...))...
}

machst du

private LayerMask whateverCheckLayerMask;

private void Awake()
{
  whateverCheckLayerMask = LayerMask.GetMask(...);
}

private void Update()
{
  ...Physics.Raycast( ..., whateverCheckLayerMask)...
}

Kann sein, dass du als Typ "int" statt "LayerMask" nehmen musst, bin mir gerade nicht sicher.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ok danke nun bin ich schlauer :D

Wenn man ScriptableObjects nutzt um in der Laufzeit ständig (z.b jeden Frame) Daten ein und auszulesen, gibt es da Performance Tipps oder sollte man sowas grundsätzlich lieber nicht tun?

Edit:

Also meine Methode wäre jetzt:

public static void DoSomething (LayerMask layer) {
	Physics2D.Raycast(pos, irgendwas, irgendwas, layer)...
}

//In einem anderen Script wird dann das benutzt:

void Update () {
	DoSomething(1 << 0); //Müsste ja dann NUR der Default Layer sein?
}

Stimmt das so?

Bei gameObject.layer == layer.value?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...