Jump to content
Unity Insider Forum

NullReferenceException: A null value was found where an object instance was required.


steave007

Recommended Posts

Hey Leute,

 

Ich bin etwas verwirrt weil mein ultimativer Weltherrschaftsplan nicht funktioniert:

 

Ich habe eine static var in dem Script "mainApp"

 

static var orderedWp : GameObject[,];

 

Und hier soll dieser Array verändert werden:

#pragma strict
static var sizeX : float = 0;
static var sizeY : float = 0;
static var editMode : boolean = false; //true = hinzufügen, false = löschen
var waypoint : GameObject;
var ground : GameObject;
var wpManager : GameObject;
static var nextPos : Vector3 = Vector3(1,0,2);

function Generate () {
for(var x : int = 0;x<sizeX;x+=4)
{
 for(var y : int = 0;y<sizeY;y+=4)
 {
  var newWp = Instantiate(waypoint,nextPos,Quaternion.identity);
  newWp.transform.parent = wpManager.transform;
  mainApp.orderedWp[x,y] = newWp;
  nextPos.z+=4;
 }
 nextPos.z = 2;
 nextPos.x+=4;
}
}

 

dann krieg ich den Fehler:

NullReferenceException: A null value was found where an object instance was required.

 

Warum??

 

Laut Konsole liegt es an: mainApp.orderedWp[x,y] = newWp;

aber newWp ist doch ein GAmeObject

 

Danke, steave007

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nein, es könnte auch ein Transform sein oder sonst was. Instantiate gibt nur ein Object zurück.

 

Mach mal:

 

var newWp = (GameObject)Instantiate(waypoint,nextPos,Quaternion.identity);

 

Hast du das waypoint GameObject im Inspector draufgezogen? Erscheint es in der Hirarchy?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie funktioniert der Zugriff auf diesen Array??

Ich hab jetzt:

pathArray.push(mainApp.orderedWp[coordinates.x,coordinates.z]);

Im Array coordinates wird ein Vector3 gespeichert.

Der Befehl soll also zu dem Array pathArray den jeweils zum Vector3 zugehörigen Punkt liefern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Finger weg von ArrayList, wir sind schließlich auch keine Höhlenmenschen mehr.

 

List ist das was du suchst, es gibt zwar noch eine ganze Menge anderer Möglichkeiten aber eine List ist das was am häufigsten verwendet wird und auch am einfachsten zu verstehen ist.

 

List<T> ist eine Klasse die ein drunter liegendes Array automatisch vergrößert wenn der Platz dieses Arrays nicht mehr ausreicht. Darüber musst du dir nicht unbedingt Gedanken machen.

 

Um List<T> zu verwenden brauchst du ein using in C# bzw import in US, und zwar folgendes:

 

using System.Collections.Generic;

import System.Collections.Generic;

 

Dir wird ja aufgefallen dass ich List<T> schreibe, die Spitzen Klammern bedeuten hier dass List eine GEnerische Klasse ist und das T gibt an welcher Typ für die List verwendet werden soll, in deinem Fall wäre dies das GameObject, geschrieben wird das ganze dann als:

 

List<GameObject> listeVonGameObjects;

 

In US ist dies leicht anders:

var listeVonGameObjects : List.<GameObject>;

 

vor dem Benutzen muss es natürlich erzeugt werden so wie jede andere Instanz auch:

 

listeVonGameObjects = new List<GameObject>();

 

In US vermutlich so:

listeVonGameObjects = List.<GameObject>();

 

Neue Elemente werden so hinzugefügt:

 

listeVonGameObjects.Add(neuesGameObject);

 

Und so wieder entfernt:

listeVonGameObjects.Remove(neuesGameObject);

 

Oder:

 

listeVonGameObjects.RemoveAt(index);

 

Wobei der Index die Position in der List beschreibt.

 

In deinem Ausgangspost hast du ein 3 Dimensionales Array gehabt, das kannst du so direkt nicht mit der List verwenden, da die List 1 Dimensional ist, aber man kann 3D zu 1D Konvertieren, was aber keine gute Idee ist wenn deine Liste wachsen soll. Also entweder dir fällt da etwas schlaues ein oder du versuchst etwas anderes:

 

Das Dictionary!

 

Das Dictionary<TKey, TValue> speichert 2 Werte, einmal ein Schlüssel anhand der Wert gefunden werden kann und eben der Wert.

 

Du könntest die Position als Schlüssel nehmen und das GameObject als Wert:

 

Dictionary<Vector3, GameObject> meinDictionary;

 

Erzeugung funktioniert auf die gleiche Weise wie bei der List, deswegen erspare ich mir diesen Beispielcode mal.

 

Aber interessant ist wiederum das anlegen:

 

Entweder so:

Vector3 position = new Vector3(x, y, z);
meinDictionary[position] = meinGameObject;

 

oder so:

Vector3 position = new Vector3(x, y, z);
meinDictionary.Add(position, meinGameObject);

 

Der Unterschied der beiden Methoden ist: Die Variante mit Add wirft eine Exception/Fehler wenn es den Eintrag an der "position" schon gibt.

 

Auslesen geht so:

Vector3 position = new Vector3(x, y, z);
GameObject meinGameObject = meinDictionary[position];

 

Oder so:

Vector3 position = new Vector3(x, y, z);
GameObject meinGameObject;
if (meinDictionary.TryGet(position, out meinGameObject))
{
 ...
}

 

Der Unterschied hier ist: Die Erste Variante schmeißt einen Fehler wenn es den Eintrag nicht gibt.

 

Löschen kann man Einträge so:

 

Vector3 position = new Vector3(x, y, z);
meinDictionary.Remove(position);

 

Das alles ist natürlich sehr leicht langsamer und komplexer zu verwenden als einfach ein fixes 3 Dimensionales Array, überlege also ob du das brauchst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank für den ausführlichen Post.

Leider schreib ich allerdings in JavaScript, wo es meines Wissens nach keine Dictionary gibt (ich hab zumindest in der Scripting Reference keine gefunden korrigiert mich wenn ich falsch liege). Da steht nur etwas von Hashtable, ist das was ähnliches?

 

Vielleicht hilft es weiter wenn ich mein Vorhaben genau beschreibe:

 

Ich programmiere gerade am Bresenham-Algorithmus für meine Belegarbeit. Als funktioniert soweit so gut und die Funktion liefert einen Array mit Vector3 Punkten die zum Weg gehören.

Nun reichen diese Punkte alleine allerdings nicht, denn ich kann nur mit Waypoints weiterarbeiten die ich nach dem A*-Tutorial gebastelt habe.

 

Deshalb dachte ich mir: Der Script der die Wegpunkte erstellt wirft sie einfach gleich in einen 2D-Array.

Erste Dimension: x-Koordinate

Zweite Dimension: y(bzw. z)-Koordinate

 

Jetzt will ich praktisch mit meinen Vector3 Variablen den richtigen Wegpunkt auswählen und damit weiter arbeiten können...

 

Was empfehlt ihr mir also zu nehmen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dictionary gehört zu Mono/.Net das geht auch mit UnityScript, auch wenn sich da alles kacke anfühlt und benutzt. Nutz gleich C# :>

 

Aber zu dem was du vorhast: GameObjekte haben immer die Transform Komponente welche dir ihre Position im Raum mitteilen können, wieso also genau ein 2D Array?

 

Ich vermute mal es geht dir dabei um einen schnellen und einfachen Zugriff.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja es geht vor allem um Schnelligkeit, der Bresenham-Algorithmus muss am Ende schneller sein als A*

Ich bin durch den restlichen Code an US gebunden...

Also gibt es vielleicht doch irgendeine Möglichkeit das so ähnlich zu machen wie ich das geplant habe? Weil sonst müsste der Bresenham-Algorithmus statt mit Koordinaten ja die ganze Zeit schon mit Waypoint.transform.position arbeiten...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...