„Obiekt, który chcesz utworzyć, ma wartość zerową” Ale to działa, czy mogę zignorować błąd?

18

Nigdy mi się to nie zdarzyło, więc jestem trochę zdezorientowany.

GameObject someObject = Instantiate (Resources.Load ("Prefabs/Items/" + someName)) as GameObject;

To generuje błąd, ale obiekt jest w rzeczywistości tworzony i wszystko działa zgodnie z przeznaczeniem. Błąd nie zatrzymuje programu bez względu na to, ile razy go odtwarzam.

Czy mogę zignorować ten błąd lub czy jest jakiś problem, którego nie widzę?

użytkownik4676310
źródło
32
nigdy nie należy ignorować błędów. Są zawsze z jakiegoś powodu;)
Gabriele Vierti
5
Chcę poprzeć pomysł, aby nigdy nie ignorować błędów tylko dlatego, że „działa”. Z definicji, jeśli występuje błąd, to nie działa. Jasne, może wydawać się, że robi wszystko, co chcesz, ale to tylko oznacza, że ​​nie znalazłeś jeszcze złamanego bitu.
Pozew funduszu Moniki z

Odpowiedzi:

46

Jeśli obiekt zostanie utworzony poprawnie, pomimo Intantiate()wygenerowania wyjątku przez linię, oznacza to, że błąd pochodzi z innej instancji skryptu - może przypadkowo mieć drugą kopię w scenie.

Jedna instancja jest poprawnie skonfigurowana i działa Instantiate()zgodnie z oczekiwaniami bez błędów, więc obiekt jest tworzony zgodnie z potrzebami.

Inna instancja jest niepoprawnie skonfigurowana i zgłasza błąd. Ale jeśli patrzysz tylko na poprawnie skonfigurowaną instancję, ten błąd wydaje się pochodzić znikąd i nie ma widocznych konsekwencji.

Możesz wydrukować ścieżkę do obiektu na Start - lub w teście zerowym tuż przed linią naruszającą - aby wyśledzić niechciane duplikaty scen.

Absolutnie nie należy ignorować tego błędu.

W najlepszym razie niepotrzebnie pali cykle obliczeniowe. W najgorszym przypadku jest to znak, że twoja gra robi coś, czego nie do końca rozumiesz, i może to być przyczyną znacznie większych problemów.

DMGregory
źródło
12
+1, błędy to nie to samo, co ostrzeżenia, jeśli wystąpi błąd, nigdy nie wiadomo, kiedy nastąpi eskalacja do awarii całej gry.
TomTsagk
13
Ignorowanie ostrzeżeń nie zawsze jest bezpieczne. Nawet jeśli nie jest to błąd, może potencjalnie doprowadzić do awarii gry.
Sean Burton
2
Zgadzam się z @SeanBurton, ignorowanie ostrzeżeń nie jest bezpieczną praktyką. Należy zignorować ostrzeżenie tylko wtedy, gdy rozumiesz, co go powoduje i masz pewność, że nie powoduje problemów w kodzie. Nawet wtedy zadaj sobie pytanie, czy nie możesz zrobić tego lepiej.
Jack Aidley,
3
Każdy projekt, nad którym pracowałem z dużym zespołem, w pewnym momencie był tak przeciążony „ignorowalnymi” ostrzeżeniami, że zaczynał maskować prawdziwe problemy. Zdecydowanie zalecałbym też poważne potraktowanie ostrzeżeń, a jeśli jest to nieuniknione, wyłączenie go dla odpowiedniego wiersza wraz z komentarzem jasno określającym, dlaczego można bezpiecznie pominąć generowanie ostrzeżenia.
DMGregory
1
Jestem w 100% z @DMGregory, pracowałem tylko w bardzo małych zespołach, ale parę razy ostrzeżenia zaczęły się kumulować, strasznie było znaleźć „autentyczne” problemy, bo ciągle za nimi tęsknisz. Moim zadaniem jest utrzymanie dziennika w czystości, z wyjątkiem testowania, nawet jeśli muszę wyłączyć ostrzeżenia w kodzie wtyczek (proszę, nie rób wtyczek z ostrzeżeniami KIEDYKOLWIEK), na dłuższą metę jest o wiele lepiej. Edycja: aby było jasne, nigdy nie wyłączaj ostrzeżeń, chyba że masz 100% pewności, że nie ma innego wyjścia (co zdarza się 0,001% czasu), zawsze je naprawiaj.
Trisibo
21

Odpowiedź

Zacznę od bezpośredniej odpowiedzi na pytanie:

to działa, czy mogę zignorować błąd?

Państwo dało . Nie powinieneś , bo to znaczy, że coś idzie nie tak. Przyzwyczaiłbyś się do tego błędu, ale może on „ukryć się” lub spowodować kolejny błąd.

Obecnie masz komunikat o błędzie i nadal działa poprawnie. Odwrotnie, nie działa i nie ma (a raczej: nie rozpoznaje) informacji zwrotnej, dlaczego, jest znacznie gorzej!

Rada

Aby dowiedzieć się, skąd to się bierze, podziel to wszystko na kilka linii.

string resourceLocation = "Prefabs/Items/" + someName;
Object prefab = Resources.Load(resourceLocation);
Object instance = Instantiate(prefab);
GameObject someObject = instance as GameObject;

Błąd mówi tylko, w której linii to się wydarzyło. Jeśli błąd wystąpi w tym kodzie, numer linii powie Ci więcej o tym, która część poszła tutaj źle. Radzę też użyć ogólnej wersji Resources.Load, która dałaby nam o jeden krok mniej do zmartwienia:

string resourceLocation = "Prefabs/Items/" + someName;
GameObject prefab = Resources.Load<GameObject>(resourceLocation);
GameObject someObject = Instantiate(prefab);

Dowiedz się dlaczego

  • Teraz trochę doświadczenia Unity mówi nam, że „Obiekt, który chcesz utworzyć, ma wartość zerową” jest spowodowany Instantiate().
  • Oznacza prefabto , że jest null.
  • To oznacza Resources.Loadzwroty null.
  • DokumentacjaResources.Load mówi „ Powroty aktywo na pathrazie można go znaleźć w przeciwnym razie zwraca NULL.
  • Oznacza to, że nie znajduje podanej ścieżki (ciąg, który wywołałem resourceLocation)

Coś jest nie tak z tą ścieżką, więc oczywistym pierwszym krokiem byłoby sprawdzenie, czym tak naprawdę jest, dzięki Debug.Log. Ponieważ „wszystko działa zgodnie z przeznaczeniem”, prawdopodobne jest, że w miejscu, w którym działa jedna wersja, zachodzi pewne powielanie, a druga daje ten błąd.

W takim przypadku dobrym pomysłem jest skorzystanie z 2-parametrowej wersji Debug.Log Debug.Log(resourceLocation, gameObject);. Teraz, jeśli klikniesz komunikat dziennika w edytorze Unity, wybierze GameObjectskąd pochodzi.

Raphael Schmitz
źródło