Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

23.10.2014, 06:01

[Unity] Workaround gesucht: 2D Array im Inspector

Hallo Leute,

Wie der Titel schon sagt, bin ich auf der Suche nach einem Workaround, sodass ich über den Object-Inspector von Unity ein 2-dimensionales Array initialisieren kann.

Der Hintergrund ist folgender: Ich habe in meinem Spiel das Raumschiff des Spielers in 3 verschiedenen Typen in jeweils 4 verschiedenen Farben. Daher würde es sich anbieten, ein Sprite[,] sprites = Sprite[3, 4] Array zu haben, sodass ich z.B. mit sprites[0, 0] auf Typ 1, Farbe 1 zugreifen kann. (Ich hoffe das ist verständlich?)

Unfortunately, ist es in Unity nicht möglich mit dem Object-Inspector ein 2D-Array zu belegen. Sonst hätte ich einfach die jeweiligen Sprites dort schön reinziehen können um an die Referenzen zu kommen.
Meine jetziger Versuch sieht folgendermaßen aus:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[System.Serializable] 
public class ShipSpriteContainer {
    public Sprite[,] sprites = new Sprite[3, 4];

     [SerializeField]
    private Sprite[] model1 = new Sprite[4];
    [SerializeField]
    private Sprite[] model2 = new Sprite[4];
    [SerializeField]
    private Sprite[] model3 = new Sprite[4];

    public ShipSpriteContainer() {
        // System.Array.Copy (model1, sprites [0], model1.Length);
        // System.Array.Copy (model2, sprites [1], model2.Length);
        // System.Array.Copy (model3, sprites [2], model3.Length);
        sprites [0, 0] = model1 [0];
    }
 }

Ich habe eine eigene Klasse ShipSpriteContainer erstellt, die wiederum 3 Sprite[] Arrays beinhaltet. So kann ich schonmal im Inspector die Referenzen für die jeweiligen Sprites easy erstellen. Das Problem stellt jetzt Sprite[,] sprites = new Sprites[3,4] da. Der Plan war, den Inhalt der 3 Sprite[] Arrays in sprites zu kopieren. Leider funktioniert das nicht, da bei Unity ja erst "später", also nachdem der Constructor aufgerufen wird, die 3 Sprite[] Arrays mit dem Inhalt aus dem Inspector gefüllt werden.

Die Nutzung in einem Script sollte wie folgt aussehen:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
public class ShipSelection : MonoBehaviour {
    public int model;
    public int color;
     public ShipSpriteContainer spriteContainer;

    // Use this for initialization
    void Start () {
        Debug.Log (spriteContainer.sprites[model, color]);
    }
}


Hat jemand eine Lösung für das Problem? Mein Ansatz scheint so nicht zu funktionieren, mir fällt aber auch einfach nix anderes ein :/ Jede Hilfe ist Willkommen :D

MfG,
Bigabig

Tobiking

1x Rätselkönig

  • Private Nachricht senden

2

23.10.2014, 08:54

Mehrdimensionale Arrays kannst du soweit ich weiß nur über verschachtelte Objekte im Editor zeigen. Also dein ShipSpriteContainer könnte ein Array von ShipSpriteArrays haben, die wiederum ein Array von Sprites halten.

Ansonsten werden die Werte aus dem Editor erst nach dem Constructor eingesetzt, weswegen dieser in Unity meistens unbrauchbar ist. Stattdessen nutzt man die Awake Methode, die direkt nach dem eintragen der Werte aus dem Editor aufgerufen wird.

Und statt dem Kopieren des Arrays, wodurch du die Daten doppelt speicherst, wie wäre es mit einer Get-Methode zur vereinfachung des Zugriffs auf das Array?

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

3

23.10.2014, 09:34

Ein mehrdimensionales Array finde ich in dieser Situation nur bedingt günstig gewählt. Jeder Eintrag stellt die verschiedenen Grafiken eines einzelnen Raumschifftypen dar und es gibt eine Sammlung von Raumschiffen. Es wäre also grundsätzlich schonmal nich ganz unsinnig, eine Klasse für die Grafiken des Raumschifftypen zu erstellen, welche ein Array von Sprites besitzt, wovon wiederum ein Array an der bisherigen Stelle abgelegt wird.

Ansonsten, sollte das nicht funktionieren (was es aber eigentlich tun sollte), könntest du gucken, ob du mit Editor-Scripting an dein Ziel kommst. Du könntest für dein Objekt einen Editor definieren, der mit GUILayout.BeginHorizontal mehrzeilig entsprechende Eingabeelemente zur Verfügung stellt, über welches du dann die Sprites festlegen kannst.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

4

23.10.2014, 11:43

Ansonsten werden die Werte aus dem Editor erst nach dem Constructor eingesetzt, weswegen dieser in Unity meistens unbrauchbar ist. Stattdessen nutzt man die Awake Methode, die direkt nach dem eintragen der Werte aus dem Editor aufgerufen wird.
ah sie an, ich dachte immer Start() ist das erste^^

Und statt dem Kopieren des Arrays, wodurch du die Daten doppelt speicherst, wie wäre es mit einer Get-Methode zur vereinfachung des Zugriffs auf das Array?
jo das mit dem kopieren hat eh nicht geklappt, deshalb wars auskommentiert :D

Ein mehrdimensionales Array finde ich in dieser Situation nur bedingt günstig gewählt. Jeder Eintrag stellt die verschiedenen Grafiken eines einzelnen Raumschifftypen dar und es gibt eine Sammlung von Raumschiffen. Es wäre also grundsätzlich schonmal nich ganz unsinnig, eine Klasse für die Grafiken des Raumschifftypen zu erstellen, welche ein Array von Sprites besitzt, wovon wiederum ein Array an der bisherigen Stelle abgelegt wird.
ahhh super idee! :D habs jetzt so umgesetzt, funktioniert :thumbsup:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
[System.Serializable]
// each instance of this class represents a different type / model of the PlayerShip!
public class PlayerShip {

    public enum Model {
        Model1,
        Model2,
        Model3
    }

    public enum Color {
        Red,
        Green,
        Blue,
        Orange
    }

    // each type / model of the PlayerShip is available in different colors
    // the sprite array holds the sprites for the different colors
    public Sprite[] sprites;
}


public class ShipAppearance : MonoBehaviour {

    public PlayerShip.Model model;          // currently selected model of the PlayerShip
    public PlayerShip.Color color;          // currently selected color of the PlayerShip
    public PlayerShip[] playerShips;        // holds the references to the different model + color sprites for the PlayerShip

    private SpriteRenderer spriteRenderer;

    // Use this for initialization
    void Start () {
        spriteRenderer = GetComponent<SpriteRenderer> ();

        ChangeAppearance (model, color);
    }

    public void ChangeAppearance(PlayerShip.Model model, PlayerShip.Color color) {
        int m = (int) model;
        int c = (int) color;

        // check for errors
        if (m > playerShips.Length - 1 || m < 0) {
            Debug.LogError ("Something went wrong with the model");
            return;
        } else if  (c > playerShips[(int) model].sprites.Length - 1 || c < 0) {
            Debug.LogError ("Something went wrong with the color");
            return;
        }

        // apply the new sprite to the spriteRenderer
        spriteRenderer.sprite = playerShips [m].sprites [c];
    }
}

wie du geschrieben hast hab ich ne eigene klasse für die Raumschifftypen erstellt, die ein sprite Array beinhaltet, in dem die verschiedenen Farben abgespeichert werden. Funktioniert auch super im Editor, hatte erst gezweifelt ob der das richtig darstellt, aber alles kein problem :D


Ansonsten, sollte das nicht funktionieren (was es aber eigentlich tun sollte), könntest du gucken, ob du mit Editor-Scripting an dein Ziel kommst. Du könntest für dein Objekt einen Editor definieren, der mit GUILayout.BeginHorizontal mehrzeilig entsprechende Eingabeelemente zur Verfügung stellt, über welches du dann die Sprites festlegen kannst.
damit habe ich leider noch überhaupt keine erfahrung gemacht^^ ist, wie du aber schon richtig erkannt hast, garnicht notwendig, da es ja auch so geht ;D

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

5

23.10.2014, 13:22

Der Vorteil der separaten Klasse ist der, dass man noch weitere Eigenschaften anlegen kann, wie der Name des Schiffstyp o. ä.

Ich kann nur empfehlen, mal einen Blick auf das Editor-Scripting zu werfen. Auch wenn es nur so eine einfache Sache ist, wie einen Button hinzuzufügen, der automatisiert eine bestimmte Änderung vornimmt, kann das eine gewisse Arbeitserleichterung darstellen (abhängig vom jeweiligen Anwendungsfall).
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Werbeanzeige