Jump to content
Unity Insider Forum

2D Gitter erstellen


Prayer90

Recommended Posts

Hallo zusammen,

ich stehe noch ganz am Anfang mit meinen Unity und C# Kenntnissen, daher entschuldige ich mich schonmal vorab für meine unqualifizierten Fragen.
Im Moment versuche ich ein Spiel nachzubauen, was ich früher mal im GM 8 gebaut hatte. Es geht um eine Grid basierte Tower Defense mit zufällig generierten Maps.

Die Umgebung soll vorab, in einem auf Zahlen basierten Gitter generiert werden. Dieses wird im zweiten Schritt Zelle für Zelle ausgewertet. Je nach Zellwert werden dann verschiedene Objekte generiert.

Meine Frage: Auf welche Art und Weise erstelle ich am besten das Zahlengrid?

  • Zellen müssen per Koordinate ansprechbar und bearbeitbar sein

Im GM 8 gab es dafür extra eine Grid Funktionen. Was ich bis jetzt gelesen hatte, kann ich in Unity entweder mit Listen oder mit Arrays arbeiten oder gibts noch eine Alternative?
Ich wollte einfach mal horchen wie Ihr Profis in einem solchen Fall vorgehen würdet.

Lg Prayer90

Link zu diesem Kommentar
Auf anderen Seiten teilen

moin Prayer90!

Da bist du schonmal auf dem richtigen weg mit Arrays oder listen. In dem fall würde ich dir ein Array vorschlagen da sich die größe deines Grids wohl nicht zur laufzeit ändert. Im Prinzip brauchst du dann eine GridCell klasse (oder struct) und eine Grid klasse... Das minimalbeispiel sähe so aus:

 

	public class GridCell
	{
		public int X;
		public int Y;

		public GridCell(int x, int y)
		{
			X = x;
			Y = y;
		}
	}

	public class Grid
	{
		public int Width;
		public int Height;

		private GridCell[] _grid;

		public Grid(int width, int height)
		{
			Width = width;
			Height = height;
			_grid = new GridCell[Width * Height];
			InitGridCells();
		}

		private void InitGridCells()
		{
			for (int y = 0; y < Height; y++)
			{
				for (int x = 0; x < Width; x++)
				{
					_grid[y * Height + x] = new GridCell(x, y);
				}
			}
		}

		public GridCell GetCell(int x, int y)
		{
			return _grid[y * Height + x];
		}
	}

mit z.B. new Grid(10, 10) erzeugst du ein neues 10x10 großes Grid.

Die Zellen werden in einem 1-dimensionalen Array abgelegt und der index der gewünschten Zelle wird mit y * Height + x errechnet. Mal dir das am besten mal auf wenn du nicht verstanden hast wie das funktioniert, das ist finde ich sehr hilfreich :). Die andere möglichkeit wäre ein 2Dimensionales Array. Aber die gängigere variante ist denke ich diese hier.

Viel spaß beim durchdenken und coden ! 🙂

Cxyda

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hey Prayer90,

da gibt es mehrere möglichkeiten .. aber die einfachste wäre wohl mithilfe des Singleton Patterns

kurz gesagt fügst du in deinen constructor von deiner Grid klasse sowas hier ein:

public class Grid
{
  // Diese 2 Zeile hier brauchst du
  public static Grid Instance => _instance;
  private Grid _instance;
  
  // .. hier steht wahrscheinlich anderer code in deiner klasse
  
  // und hier dein constructor fügst du noch eine Zeile ein...
  public Grid(int width, int height)
  {
    // und diese Zeile brauchst du noch
    _instance = this;
    // mehr constructor code ...
  }
  
}

 

Dann kannst du aus jedem deiner anderen scripte Grid.Instance aufrufen und hast zugriff auf dein Grid. Du musst allerdings aufpassen das du den constructor (also grid grid = new Grid(10, 10)) aufrufst bevor du irgendwo anders Grid.Instance aufrufst. Sonst bekommst du eine NullreferenceException.

An dieser stelle sei noch gesagt das dieser Ansatz einige (unschöne) eigenschaften hat die du oben in dem link zum SingletonPattern nachlesen kannst. Aber fürs erste geht das so

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ok, das mit der Grid-Übergabe habe ich hinbekommen, Dankeschön.

Mittlerweile kann ich analog dem obigen Video ein Grid erzeugen, dieses wie ich es brauche mit Werten füllen.
Anschließend wird jede Zelle im Grid ausgelesen und entsprechend dem Wert der Zelle, ein Objekt erzeugt.

Das erzeugte Objekt bekommt das Grid übergeben und soll sich anhand der umliegenden Zellen (Werte) ausrichten (s. Anhang).
Für jede Richtung (16 Möglichkeiten) hat das Objekt ein separates Mesh.

Es werden immer die Zellen nach oben, links, unten und rechts angeschaut, wenn ein entsprechendes Feld angrenzt, dann wird ein bool auf true gesetzt.
Je nach Auswertungsergebnis wird der entsprechende Mesh Renderer aktiviert.

//Auswertung-------------------------------------------------------------
        //4 mal true---------------------
        //Viereck
        if (oben == true && rechts == true && unten == true && links == true)
        {felsen16.GetComponent<MeshRenderer>().enabled = true;}

        //3 mal---------------------
        //oben
        if (oben == false && rechts == true && unten == true && links == true)
        { felsen12.GetComponent<MeshRenderer>().enabled = true; }
        //rechts
        if (oben == true && rechts == false && unten == true && links == true)
        { felsen13.GetComponent<MeshRenderer>().enabled = true; }
        //unten
        if (oben == true && rechts == true && unten == false && links == true)
        {felsen10.GetComponent<MeshRenderer>().enabled = true;}
        //links
        if (oben == true && rechts == true && unten == true && links == false)
        { felsen11.GetComponent<MeshRenderer>().enabled = true; }

Das funktioniert bis dahin ganz gut (Außenbegrenzung im Anhang).

 

Sowie allerdings mehr als zwei der if Conditions false sind. Bekomme ich eine Fehlermeldung:

UnassignedReferenceException: The variable felsen11 of TestGrid has not been assigned

//2 mal---------------------
if (oben == false && rechts == false && unten == true && links == true)
{ felsen11.GetComponent<MeshRenderer>().enabled = true; }

Das verstehe ich allerdings nicht, "felsen11" benutzte ich ja in der Abfrage darüber auch und da funktioniert es. 🤔

Kann mir jemand erklären wie der Fehler zustande kommt? Ich stehe gerade völlig auf dem Schlauch.

 

 

 

Hilfe.png

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...