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.04.2016, 15:43

[C# Unity3D]Prefabs in ArrayList

Hallo,

undzwar möchte ich, dass beim Übertreten einer Schwelle eine zufällige Karte geladen wird. Hierzu möchte ich alle Prefabs-Maps aus einem Ordner in eine ArrayList packen.

C#-Quelltext

1
2
3
4
    public GameObject[] allMaps;
    void Start () {
        allMaps = Resources.LoadAll("Maps")as GameObject[];
    }


Doch wenn ich mir irgendetwas aus dem Array auslesen lassen will wie z.b.

C#-Quelltext

1
Debug.Log("Maps " + allMaps.Length);

dann kommt diese Fehlermeldung:
NullReferenceException: Object reference not set to an instance of an object

Ich weis jetzt leider nicht ob er überhaupt etwas in das Array geschrieben hat oder ob nur die Auslesung nicht funktioniert hat.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

23.04.2016, 16:33

Soweit ich das im Kopf habe musst du in deinem Asset-Ordner einen Ordner mit dem Namen Resources haben um so auf Assets zuzugreifen. In deinem Fall müsste im Asset Ordner also der Pfad Resources/Maps vorhanden sein. Ist das bei dir der Fall? Ansonsten mach mal einen Screenshot von deiner Ordnerstruktur und zeig die hier vielleicht. Möglicherweise fällt da was auf.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

3

23.04.2016, 16:49

Habe es jetzt in einen extra Resourcesordner Ordner gepackt, aber es kommt immernoch die selbe Fehlermeldung. Hier mal das ganze Script

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
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;

public class LoadNewArea : MonoBehaviour {

    public string levelToLoad;
    public GameObject[] allMaps;
    void Start () {
        allMaps = Resources.LoadAll("Maps")as GameObject[];
        Debug.Log("Maps " + allMaps.Length);
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    void OnTriggerEnter2D(Collider2D other)
    {

        if(other.gameObject.name == "Player")
        {
            SceneManager.LoadScene(levelToLoad);
        }

    }

    public void ChooseMap()
    {
       // float random = Random.value();

    }
}


und hier die Fehlermeldung in Unity:

NullReferenceException: Object reference not set to an instance of an object
LoadNewArea.Start () (at Assets/Scripts/LoadNewArea.cs:11)
»TightOrange« hat folgendes Bild angehängt:
  • assets.PNG

Tobiking

1x Rätselkönig

  • Private Nachricht senden

4

23.04.2016, 17:29

Wenn du nicht mal Length aufrufen kannst, existiert das Array gar nicht. Wenn du as verwendest, passiert das wenn der cast fehlschlägt. Sind beide Files in dem Ordner Prefabs? Wenn nicht könntest du noch nach File Typ filtern. In der Doku von load gibt es ein beispiel http://docs.unity3d.com/ScriptReference/Resources.Load.html

5

23.04.2016, 17:40

Also gerade sind die Files im Ordner "Resources" in dem Unterordner "Maps". Ich habe es auch mit dem Type Filtern probiert,

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
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;

public class LoadNewArea : MonoBehaviour {

    public string levelToLoad;
    public GameObject[] allMaps;
    void Start () {
        allMaps = Resources.LoadAll("Assets/Rescources/Maps", typeof(GameObject))as GameObject[];
        Debug.Log("Maps " + allMaps.Length);
    }
    
    // Update is called once per frame
    void Update () {
    
    }

    void OnTriggerEnter2D(Collider2D other)
    {

        if(other.gameObject.name == "Player")
        {
            SceneManager.LoadScene(levelToLoad);
        }

    }

    public void ChooseMap()
    {
       // float random = Random.value();

    }
}


allerdings hat sich dadurch nichts verändert. Gibt es denn noch eine andere Möglichkeit für die Grundproblematik? Also das ich eine zufällige Map aus dem Ordner auswähle?

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

23.04.2016, 17:46

Guck mal hier. Da wird im Prinzip genau das gemacht was du möchtest.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

7

23.04.2016, 19:15

Ich glaube auf der von Schorsch verlinkten Seite wird ebenfalls auf diesen Fehler eingegangen:
LoadAll liefert ein UnityEngine.Object[] zurückgeliefert. Ein Array kann aber nicht in einen Arraytypen einer abgeleitenen Klasse (GameObject) gecastet werden, auch wenn alle enthaltenen Elemente von diesem Typ sind. Wie Tobiking schon erklärt hat, wird im Falle eines Fehlschlags beim Casten null zurückgeliefert.
Du wirst also über das Object[] in irgendeiner Weise iterieren müssen und die Elemtente einzeln untersuchen. Auf der von Schorsch verlinkten Seite wird dafür bereits ein Beispiel geliefert. Beachte aber, dass du using System.Collections.Generic; hinzufügen musst, um die generische Klasse List verwenden zu können.

Für die Zukunft: du solltest schauen, dass du nach Möglichkeit immer die generische Varianten von Methoden in Unity aufrufst, da dort eine bessere Typsicherheit gegeben ist. GetComponent<Transform>() ist besser als GetComponent(typeof(Transform)) oder GetComponent("Transform").
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Superwayne

Treue Seele

Beiträge: 242

Beruf: Student & App Entwickler (Xamarin)

  • Private Nachricht senden

8

24.04.2016, 11:53

Wie bereits erwähnt funktioniert "as GameObject[]" so nicht. Stattdessen könntest du folgendes verwenden:

C#-Quelltext

1
2
Object[] tmp = Resources.LoadAll("Assets/Rescources/Maps", typeof(GameObject));
allMaps = Array.ConvertAll(tmp, item => (GameObject)item);

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

9

24.04.2016, 12:07

Wie bereits erwähnt funktioniert "as GameObject[]" so nicht. Stattdessen könntest du folgendes verwenden:

C#-Quelltext

1
2
Object[] tmp = Resources.LoadAll("Assets/Rescources/Maps", typeof(GameObject));
allMaps = Array.ConvertAll(tmp, item => (GameObject)item);

Aber nur, solange sich in dem Verzeichnis auch ausschließlich Prefabs befinden. Und statt 2 Iterationen zu haben, wäre es sinnvoller, beim Iterieren bereits die gewünschte Operation durchzuführen.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Superwayne

Treue Seele

Beiträge: 242

Beruf: Student & App Entwickler (Xamarin)

  • Private Nachricht senden

10

24.04.2016, 16:05

Wie bereits erwähnt funktioniert "as GameObject[]" so nicht. Stattdessen könntest du folgendes verwenden:

C#-Quelltext

1
2
Object[] tmp = Resources.LoadAll("Assets/Rescources/Maps", typeof(GameObject));
allMaps = Array.ConvertAll(tmp, item => (GameObject)item);

Aber nur, solange sich in dem Verzeichnis auch ausschließlich Prefabs befinden. Und statt 2 Iterationen zu haben, wäre es sinnvoller, beim Iterieren bereits die gewünschte Operation durchzuführen.

Der TypeFilter bei Resources.LoadAll sorgt doch dafür, dass nur GameObjects geladen werden?
Das mit den 2 Iterationen stimmt natürlich. Ich habe jetzt über die weitere Verwendung der Objekte nicht nachgedacht.

Werbeanzeige