ระดับกลาง30 นาทีบทที่ 6

วิธี Debug มอดและแก้ Error ด้วย SMAPI log

วิธีหาไฟล์ SMAPI log อ่านบรรทัด error และ stack trace แยกมอดที่เป็นต้นเหตุ และแก้ปัญหาที่พบบ่อย เช่น ขาด dependency มอดซ้ำ และมอดไม่รองรับเวอร์ชัน

เขียนโดย Pokpong Limpaphan · อัปเดต

สถานะการตรวจสอบ: ตรวจกับเอกสารทางการแล้ว

เนื้อหาตรวจสอบกับเอกสารทางการแล้ว แต่ยังไม่ได้ทดสอบในเกมจริงทุกขั้นตอน (ตรวจล่าสุด )

ตรวจกับ: ข้อความใน ModResolver.cs และ LogManager.cs ของ SMAPI (สาขา develop)

รูปแบบข้อความอ้างอิงซอร์สโค้ดของ SMAPI เวอร์ชันอื่นอาจใช้ถ้อยคำต่างไปเล็กน้อย

สิ่งที่จะได้เรียนรู้

  • หาไฟล์ SMAPI-latest.txt บนทุกระบบปฏิบัติการ
  • อ่านรูปแบบบรรทัด log และระดับความรุนแรง
  • แยกสาเหตุของมอดที่ถูกข้ามจากข้อความของ SMAPI
  • อ่าน stack trace เพื่อหามอดที่เกี่ยวข้อง

สิ่งที่ต้องมีก่อนเริ่ม

  • ติดตั้ง SMAPI แล้ว
สารบัญ

เมื่อมอดไม่ทำงานหรือเกมเกิด error คำตอบเกือบทั้งหมดอยู่ในไฟล์ log ของ SMAPI บทนี้สอนวิธีอ่าน log อย่างเป็นระบบ ทั้งในฐานะผู้เล่นและผู้สร้างมอด

หาไฟล์ log

SMAPI บันทึก log ของการเปิดเกมครั้งล่าสุดไว้ในไฟล์ SMAPI-latest.txt

ระบบ ตำแหน่ง
Windows %appdata%\StardewValley\ErrorLogs\SMAPI-latest.txt
macOS ~/.config/StardewValley/ErrorLogs/SMAPI-latest.txt
Linux / Steam Deck ~/.config/StardewValley/ErrorLogs/SMAPI-latest.txt

ถ้าเกมปิดตัวกะทันหัน อาจมีไฟล์ SMAPI-crash.txt อยู่ในโฟลเดอร์เดียวกันด้วย

อ่านรูปแบบบรรทัด log

ทุกบรรทัดมีรูปแบบเดียวกัน

[เวลา ระดับ แหล่งที่มา] ข้อความ
[08:15:21 ERROR Example Broken Mod] This mod failed in the GameLoop.DayStarted event.
  • เวลา ช่วยเทียบว่าเกิดอะไรขึ้นก่อนหลัง
  • ระดับ มี TRACE, DEBUG, INFO, WARN, ERROR และ ALERT
  • แหล่งที่มา คือชื่อมอดที่เขียนข้อความนั้น หรือ SMAPI และ game สำหรับข้อความจาก SMAPI และตัวเกม

บรรทัดที่ไม่มีวงเล็บนำหน้า (เช่น at ...) เป็นส่วนต่อของข้อความก่อนหน้า มักเป็น stack trace

ขั้นตอนการอ่าน log

ภาพรวมว่าควรดูอะไรก่อนหลัง

flowchart TD
  A["เปิด SMAPI-latest.txt"] --> B{"มี SMAPI เวอร์ชันใหม่?"}
  B -- ใช่ --> U["อัปเดต SMAPI ก่อน"]
  B -- ไม่ --> C{"มีหัวข้อ Skipped mods?"}
  C -- ใช่ --> D["อ่านเหตุผลหลังคำว่า because แล้วแก้ตามตาราง"]
  C -- ไม่ --> E{"มี ERROR พร้อม exception?"}
  E -- ใช่ --> F["ดูชื่อมอดในวงเล็บและ stack trace"]
  E -- ไม่ --> G["ดู WARN หรือแบ่งครึ่งมอดเพื่อหาต้นเหตุ"]

ลองไล่อ่าน log ตัวอย่างไปพร้อมกับภาพ ดูว่าควรมองหาอะไรตามลำดับ

ลำดับการอ่าน SMAPI log
[08:15:20 INFO  SMAPI] SMAPI 4.5.2 with Stardew Valley 1.6.15
[08:15:21 ERROR SMAPI] Skipped mods
[08:15:21 ERROR SMAPI]    - Fancy Fish 1.0.0 because it requires mods which aren't installed (spacechase0.SpaceCore).
[08:15:30 ERROR Example Mod] This mod failed in the GameLoop.DayStarted event.
System.NullReferenceException: Object reference not set to an instance of an object.
 at ExampleMod.ModEntry.OnDayStarted(Object sender, DayStartedEventArgs e) in ModEntry.cs:line 42
  1. ดูเวอร์ชันก่อนตรวจว่า SMAPI และเกมเป็นเวอร์ชันล่าสุด ถ้ามีเวอร์ชันใหม่ให้อัปเดตก่อน
  2. หา Skipped modsหัวข้อนี้รวมมอดที่ SMAPI ไม่โหลด
  3. อ่านเหตุผลมอด Fancy Fish ต้องใช้ SpaceCore ซึ่งยังไม่ได้ติดตั้ง แก้ได้ด้วยการติดตั้งมอดในวงเล็บ
  4. หา ERROR จากมอดชื่อในวงเล็บบอกว่ามอดไหนรายงาน error และพังระหว่าง event อะไร
  5. อ่าน exception และ stack traceบรรทัดบนสุดของ stack trace คือจุดที่เกิด error ในตัวอย่างคือ ModEntry.cs บรรทัด 42

1. ดูส่วนหัว

บรรทัดแรกบอกเวอร์ชัน SMAPI เกม และระบบปฏิบัติการ ถ้า SMAPI แจ้งว่ามีเวอร์ชันใหม่ (You can update SMAPI to ...) ให้อัปเดตก่อนแก้ปัญหาอื่น

2. ดูรายการ Skipped mods

SMAPI รวบรวมมอดที่โหลดไม่ได้ไว้ในหัวข้อ Skipped mods พร้อมเหตุผลท้ายคำว่า because

ข้อความจาก SMAPI ความหมาย วิธีแก้
it requires mods which aren't installed (...) ขาด dependency ที่อยู่ในวงเล็บ ติดตั้งมอดที่ระบุ
it needs newer versions of some mods: ... dependency เก่าเกินไป อัปเดตมอดที่ระบุ
it needs the '...' mod, which couldn't be loaded dependency ถูกข้ามด้วยเหตุผลอื่น แก้มอด dependency ตัวนั้นก่อน
you have multiple copies of this mod installed ติดตั้งมอดเดียวกันซ้ำหลายโฟลเดอร์ ลบโฟลเดอร์ที่ระบุแล้วติดตั้งใหม่ชุดเดียว
it needs SMAPI X or later SMAPI เก่ากว่าที่มอดต้องการ อัปเดต SMAPI
it needs Stardew Valley X or later เกมเก่ากว่าที่มอดต้องการ อัปเดตเกม
it's no longer compatible มอดไม่รองรับเกมหรือ SMAPI ปัจจุบัน หาเวอร์ชันใหม่ หรือนำมอดออก
its DLL '...' doesn't exist ไม่มีไฟล์ .dll ตาม EntryDll ดาวน์โหลดมอดใหม่ หรือ build โปรเจกต์ให้ถูก
its dependencies have a circular reference dependency อ้างอิงกันเป็นวงกลม แก้ Dependencies ใน manifest

3. หา ERROR และ exception

ค้นหาคำว่า ERROR แล้วดูชื่อในวงเล็บ ถ้าเป็นชื่อมอด แปลว่ามอดนั้นรายงาน error เอง ตัวอย่าง

[08:15:21 ERROR Example Broken Mod] This mod failed in the GameLoop.DayStarted event. Technical details:
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExampleBrokenMod.ModEntry.OnDayStarted(Object sender, DayStartedEventArgs e) in ModEntry.cs:line 42
   at StardewModdingAPI.Framework.Events.ManagedEvent`1.Raise(TEventArgs args)
  • บรรทัดแรกบอกว่ามอดไหนพังระหว่าง event อะไร
  • บรรทัดที่สองคือชนิดของ exception
  • บรรทัด at ... คือ stack trace อ่านจากบนลงล่าง บรรทัดบนสุดคือจุดที่เกิด error

ถ้าแหล่งที่มาเป็น game หรือ SMAPI ให้ดู stack trace ว่ามี namespace ที่ไม่ใช่ StardewValley, StardewModdingAPI หรือ System หรือไม่ ถ้ามี อาจเป็นมอดที่เกี่ยวข้อง แต่ยังสรุปแน่นอนไม่ได้ เพราะมอดที่แก้โค้ดเกม (Harmony) อาจทำให้ error ไปเกิดในโค้ดของเกม

4. ดู WARN

คำเตือนไม่ได้แปลว่าพังเสมอไป แต่ถ้ามอดทำงานผิดปกติ คำเตือนจากมอดนั้นมักบอกเหตุผล เช่น Content Patcher จะเตือนว่า patch ไหนถูกข้ามเพราะอะไร

วิธีแยกหามอดต้นเหตุ

เมื่อ log ไม่ได้บอกชัดเจน ให้ใช้วิธีแบ่งครึ่ง

  1. สำรองเซฟ
  2. ย้ายมอดครึ่งหนึ่งออกจากโฟลเดอร์ Mods (หรือเติม . หน้าชื่อโฟลเดอร์ SMAPI จะข้ามโฟลเดอร์ที่ขึ้นต้นด้วยจุด)
  3. ทดสอบว่าปัญหายังเกิดหรือไม่
  4. ทำซ้ำกับกลุ่มที่ยังมีปัญหา จนเหลือมอดตัวเดียว

อย่าลืมว่ามอดที่ถูกย้ายออกอาจเป็น dependency ของมอดอื่น

สำหรับผู้สร้างมอด: เขียน log ให้มีประโยชน์

this.Monitor.Log("Loaded 3 custom crops.", LogLevel.Debug);
this.Monitor.Log($"Could not find item '{itemId}', skipping.", LogLevel.Warn);

try
{
    // โค้ดที่อาจผิดพลาด
}
catch (Exception ex)
{
    this.Monitor.Log($"Failed to apply crop data: {ex}", LogLevel.Error);
}
  • ใส่ข้อมูลที่ช่วยหาสาเหตุ เช่น ID ของไอเท็มที่หาไม่เจอ
  • ใช้ LogLevel.Trace สำหรับข้อมูลละเอียดที่ไม่ต้องแสดงใน console
  • ใส่ {ex} ทั้งก้อนเพื่อให้ได้ stack trace ครบ
  • ใช้ try/catch เฉพาะจุดที่รู้ว่าจัดการ error ได้จริง อย่าครอบทุกอย่างจนซ่อนปัญหา

แบบฝึกหัด

ลองทำแบบฝึกหัดเพื่อทบทวนบทนี้ ตอบผิดได้ไม่จำกัดครั้ง กด "ดูเฉลย" ถ้าติด

ตัวเลือกไฟล์ log ของการเปิดเกมครั้งล่าสุดชื่ออะไร

ตัวเลือกข้อความ because it requires mods which aren't installed (Pathoschild.ContentPatcher) หมายถึงอะไร

ตัวเลือกใน stack trace ควรเริ่มอ่านจากบรรทัดไหน

เติมโค้ดเขียน log ระดับคำเตือนเมื่อหาไอเท็มไม่เจอ

this.Monitor.Log($"Could not find item '{itemId}'.", LogLevel.);

ตัวเลือกถ้า log ไม่ได้บอกชัดว่ามอดไหนเป็นต้นเหตุ ควรทำอย่างไร

ขอความช่วยเหลือ

  1. อัปโหลด log ที่ smapi.io/log เพื่อได้ลิงก์ที่อ่านง่าย (เว็บทางการของ SMAPI)
  2. อธิบายสิ่งที่ทำก่อนเกิดปัญหา และสิ่งที่คาดว่าจะเกิด
  3. โพสต์ใน ชุมชน SVMT พร้อมลิงก์ log

ตรวจ log อัตโนมัติ

Log Analyzer ของ SVMT อ่าน log ตามกฎในบทนี้ แสดงสรุปเป็นภาษาไทย และทำงานในเบราว์เซอร์ทั้งหมด ไม่ส่งไฟล์ไปที่ใด ถ้าสงสัยเรื่อง dependency ระหว่างมอดหลายตัว ใช้ Dependency Checker ตรวจไฟล์ manifest.json ร่วมกันได้

เอกสารอ้างอิง

ค้นหาใน SVMT

กรองตามประเภท

พิมพ์คำที่ต้องการค้นหา (ภาษาไทยหรืออังกฤษ)