วิธี 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 ตัวอย่างไปพร้อมกับภาพ ดูว่าควรมองหาอะไรตามลำดับ
[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- ดูเวอร์ชันก่อนตรวจว่า SMAPI และเกมเป็นเวอร์ชันล่าสุด ถ้ามีเวอร์ชันใหม่ให้อัปเดตก่อน
- หา Skipped modsหัวข้อนี้รวมมอดที่ SMAPI ไม่โหลด
- อ่านเหตุผลมอด Fancy Fish ต้องใช้ SpaceCore ซึ่งยังไม่ได้ติดตั้ง แก้ได้ด้วยการติดตั้งมอดในวงเล็บ
- หา ERROR จากมอดชื่อในวงเล็บบอกว่ามอดไหนรายงาน error และพังระหว่าง event อะไร
- อ่าน 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 ไม่ได้บอกชัดเจน ให้ใช้วิธีแบ่งครึ่ง
- สำรองเซฟ
- ย้ายมอดครึ่งหนึ่งออกจากโฟลเดอร์
Mods(หรือเติม.หน้าชื่อโฟลเดอร์ SMAPI จะข้ามโฟลเดอร์ที่ขึ้นต้นด้วยจุด) - ทดสอบว่าปัญหายังเกิดหรือไม่
- ทำซ้ำกับกลุ่มที่ยังมีปัญหา จนเหลือมอดตัวเดียว
อย่าลืมว่ามอดที่ถูกย้ายออกอาจเป็น 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 ของการเปิดเกมครั้งล่าสุดชื่ออะไร
SMAPI บันทึก log ล่าสุดไว้ใน SMAPI-latest.txt ในโฟลเดอร์ ErrorLogs
ตัวเลือกข้อความ because it requires mods which aren't installed (Pathoschild.ContentPatcher) หมายถึงอะไร
UniqueID ในวงเล็บคือมอดที่ขาด ติดตั้งมอดนั้นแล้วเปิดเกมใหม่
ตัวเลือกใน stack trace ควรเริ่มอ่านจากบรรทัดไหน
บรรทัดบนสุดคือจุดที่ error เกิดขึ้นจริง บรรทัดถัดลงไปคือเส้นทางที่เรียกมาถึงจุดนั้น
เติมโค้ดเขียน log ระดับคำเตือนเมื่อหาไอเท็มไม่เจอ
this.Monitor.Log($"Could not find item '{itemId}'.", LogLevel.);Warn ใช้กับสิ่งที่ผิดปกติแต่มอดยังทำงานต่อได้ ส่วน Error ใช้เมื่อทำงานต่อไม่ได้
ตัวเลือกถ้า log ไม่ได้บอกชัดว่ามอดไหนเป็นต้นเหตุ ควรทำอย่างไร
วิธีแบ่งครึ่งช่วยหามอดต้นเหตุได้เร็ว อย่าลืมสำรองเซฟก่อน
ขอความช่วยเหลือ
- อัปโหลด log ที่ smapi.io/log เพื่อได้ลิงก์ที่อ่านง่าย (เว็บทางการของ SMAPI)
- อธิบายสิ่งที่ทำก่อนเกิดปัญหา และสิ่งที่คาดว่าจะเกิด
- โพสต์ใน ชุมชน SVMT พร้อมลิงก์ log
ตรวจ log อัตโนมัติ
Log Analyzer ของ SVMT อ่าน log ตามกฎในบทนี้ แสดงสรุปเป็นภาษาไทย และทำงานในเบราว์เซอร์ทั้งหมด ไม่ส่งไฟล์ไปที่ใด ถ้าสงสัยเรื่อง dependency ระหว่างมอดหลายตัว ใช้ Dependency Checker ตรวจไฟล์ manifest.json ร่วมกันได้
เอกสารอ้างอิง
- Player Guide - Troubleshootingเอกสารทางการ
- SMAPI log parser (smapi.io/log)เอกสารทางการ
- Logging APIเอกสารทางการ
- Modder Guide - Test and troubleshootเอกสารทางการ