“ วัตถุที่คุณต้องการอินสแตนซ์เป็นโมฆะ” แต่ใช้งานได้ฉันจะเพิกเฉยต่อข้อผิดพลาดได้หรือไม่


18

สิ่งนี้ไม่เคยเกิดขึ้นกับฉันดังนั้นฉันจึงสับสนเล็กน้อย

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

สิ่งนี้ทำให้เกิดข้อผิดพลาด แต่วัตถุนั้นเป็นอินสแตนซ์จริงและทุกอย่างทำงานได้ตามที่ต้องการ ข้อผิดพลาดไม่ได้หยุดโปรแกรมไม่ว่าฉันจะทำซ้ำหลายครั้ง

ฉันสามารถละเว้นข้อผิดพลาดนี้หรือมีปัญหาบางอย่างที่ฉันไม่เห็นหรือไม่


32
คุณไม่ควรละเลยข้อผิดพลาด พวกเขาอยู่ที่นั่นเสมอด้วยเหตุผล;)
Gabriele Vierti

5
ฉันต้องการที่จะคิดที่สองที่จะไม่ละเลยข้อผิดพลาดเพียงเพราะ "ใช้งานได้" ตามคำนิยามหากมีข้อผิดพลาดมันไม่ทำงาน แน่นอนว่ามันอาจจะทำทุกสิ่งที่คุณต้องการ แต่นั่นก็หมายความว่าคุณยังไม่พบบิตที่เสียหาย
คดีของกองทุนโมนิกา

คำตอบ:


46

หากวัตถุนั้นถูกสร้างขึ้นอย่างถูกต้องแม้จะIntantiate()มีข้อผิดพลาดเกิดขึ้นข้อผิดพลาดนั้นมาจากอินสแตนซ์อื่นของสคริปต์ - คุณอาจมีสำเนาที่สองในฉากของคุณโดยไม่ได้ตั้งใจ

หนึ่งอินสแตนซ์ถูกกำหนดค่าอย่างถูกต้องและดำเนินการInstantiate()ตามที่คาดไว้โดยไม่มีข้อผิดพลาดดังนั้นวัตถุจะถูกสร้างขึ้นตามที่ต้องการ

อีกอินสแตนซ์ถูกกำหนดค่าไม่ถูกต้องและส่งข้อผิดพลาด แต่หากคุณเพียงแค่ดูตัวอย่างที่กำหนดค่าอย่างถูกต้องข้อผิดพลาดนี้จะดูเหมือนมาจากที่อื่นและไม่มีผลลัพธ์ที่มองเห็นได้

คุณสามารถพิมพ์พา ธ ไปยังวัตถุใน Start - หรือในการตรวจสอบ null ก่อนที่จะมีการละเมิดบรรทัด - เพื่อช่วยติดตามฉากที่ไม่ต้องการซ้ำซ้อน

คุณไม่ควรละเลยข้อผิดพลาดนี้อย่างแน่นอน

ที่ดีที่สุดก็คือการเผาไหม้รอบการคำนวณโดยไม่จำเป็น ที่แย่ที่สุดมันเป็นสัญญาณว่าเกมของคุณกำลังทำสิ่งที่คุณไม่เข้าใจอย่างเต็มที่และนั่นอาจเป็นสาเหตุของปัญหาที่ใหญ่กว่านั้น


12
+1 ข้อผิดพลาดจะไม่เหมือนกับคำเตือนหากมีข้อผิดพลาดคุณจะไม่มีทางรู้ว่าเมื่อไรที่มันจะบานปลายทั้งเกมล้มเหลว
TomTsagk

13
ไม่ปลอดภัยเสมอไปที่จะเพิกเฉยต่อคำเตือน แม้ว่าจะไม่ใช่ข้อผิดพลาด แต่ก็อาจนำไปสู่สถานการณ์ที่เกมล้มเหลวได้
Sean Burton

2
ฉันเห็นด้วยกับ @SeanBurton การเพิกเฉยต่อคำเตือนไม่ใช่วิธีปฏิบัติที่ปลอดภัย คุณควรเพิกเฉยต่อคำเตือนหากคุณเข้าใจว่าอะไรเป็นสาเหตุของปัญหาและสบายใจที่จะไม่ทำให้เกิดปัญหาในรหัสของคุณ ถึงแม้จะถามตัวเองว่าคุณไม่สามารถทำได้ดีขึ้น
Jack Aidley

3
ทุกโครงการที่ฉันทำงานกับทีมขนาดใหญ่มีอยู่ช่วงหนึ่งที่ได้รับมากจนเต็มไปด้วยคำเตือน "เพิกเฉย" ว่ามันเริ่มปกปิดปัญหาของแท้ ดังนั้นฉันก็ควรสนับสนุนให้ปฏิบัติตามคำเตือนอย่างจริงจังด้วยเช่นกันและหากมีสิ่งใดที่หลีกเลี่ยงไม่ได้ให้ปิดการใช้งานสำหรับบรรทัดที่เกี่ยวข้องพร้อมกับความคิดเห็นที่ระบุอย่างชัดเจนว่าทำไมมันปลอดภัยที่จะข้ามการสร้างคำเตือนนั้น
DMGregory

1
ฉัน 100% กับ @DMGregory ฉันได้ทำงานกับทีมเล็ก ๆ เท่านั้น แต่การเตือนหลายครั้งเริ่มซ้อนกันมันน่ากลัวมากที่พบปัญหา "ของแท้" หรือคุณจะคิดถึงพวกเขาตลอดเวลา MO ของฉันคือการรักษาบันทึกให้สะอาดยกเว้นสำหรับการทดสอบแม้ว่าฉันจะต้องปิดการใช้งานคำเตือนเกี่ยวกับรหัสของปลั๊กอิน (โปรดอย่าทำปลั๊กอินด้วยคำเตือนที่เคย) มันดีกว่ามากใน IMO ระยะยาว แก้ไข: ชัดเจนไม่ปิดการเตือนเว้นแต่คุณจะแน่ใจ 100% ว่าไม่มีวิธีอื่นใด (ซึ่งเกิดขึ้น 0.001% ของเวลา) ให้แก้ไขจริงเสมอ
Trisibo

21

ตอบ

ให้ฉันเริ่มต้นด้วยการตอบคำถามของคุณโดยตรง:

ใช้งานได้ฉันสามารถเพิกเฉยต่อข้อผิดพลาดได้หรือไม่

คุณสามารถทำได้ คุณไม่ควรเพราะมันหมายถึงบางสิ่งผิดปกติ คุณจะคุ้นเคยกับข้อผิดพลาดนี้ แต่อาจ "ซ่อน" หรือทำให้เกิดข้อผิดพลาดอื่น

ขณะนี้คุณมีข้อผิดพลาดและยังคงทำงานได้อย่างถูกต้อง ในทางกลับกันมันไม่ทำงานและไม่มีข้อเสนอแนะ (หรือมากกว่า: ไม่รับรู้) ทำไมมันแย่กว่ามาก!

คำแนะนำ

เพื่อหาว่าสิ่งนี้มาจากไหนให้แยกสิ่งนี้ทั้งหมดออกเป็นหลายบรรทัด

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

ข้อผิดพลาดเพียงบอกคุณว่ามันเกิดขึ้นที่บรรทัดใด หากเกิดข้อผิดพลาดในรหัสนี้หมายเลขบรรทัดจะแจ้งให้คุณทราบเพิ่มเติมว่าส่วนใดผิดพลาดที่นี่ นอกจากนี้ฉันขอแนะนำให้ใช้เวอร์ชันทั่วไปResources.Loadซึ่งจริง ๆ แล้วจะช่วยให้เราลดขั้นตอนหนึ่งที่ต้องกังวลเกี่ยวกับ:

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

หาสาเหตุ

  • ตอนนี้บิตของประสบการณ์ความสามัคคีบอกเราว่า“วัตถุที่คุณต้องการที่จะยกตัวอย่างเป็นโมฆะ” Instantiate()ที่เกิดจากการ
  • ดังนั้นที่หมายถึงคือ prefabnull
  • ดังนั้นที่หมายถึงผลตอบแทน Resources.Loadnull
  • เอกสารResources.Loadกล่าวว่า " ผลตอบแทนสินทรัพย์ที่pathถ้ามันสามารถพบได้มิฉะนั้นจะส่งกลับ null. "
  • ดังนั้นหมายความว่าไม่พบเส้นทางที่กำหนด (สตริงที่ฉันเรียกresourceLocation)

มีข้อผิดพลาดเกิดขึ้นกับเส้นทางนี้ดังนั้นขั้นตอนแรกที่ชัดเจนคือการดูว่าจริง ๆ แล้วมันคือ Debug.Log ในฐานะ "ทุกอย่างทำงานได้ตามที่ต้องการ" มีความเป็นไปได้ที่จะมีการทำซ้ำบางอย่างเกิดขึ้นในที่ที่รุ่นหนึ่งทำงานได้และอีกรุ่นหนึ่งให้ข้อผิดพลาดนี้แก่คุณ

ในกรณีที่เป็นความคิดที่ดีที่จะใช้รุ่น 2 พารามิเตอร์ของ Debug.Log(resourceLocation, gameObject);Debug.Log ตอนนี้ถ้าคุณคลิกที่ข้อความบันทึกในตัวแก้ไข Unity มันจะเลือกGameObjectตำแหน่งที่มาจาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.