18.1 สร้างพอร์ตโฟลิโอเกม

เฟส 18 · พอร์ตโฟลิโอ, อาชีพ และสัมภาษณ์ · เวลาเรียน: ongoing

ปล่อยเกมและเดโมที่เล็ก จบ และเนี้ยบ ความลึกและความเสร็จชนะปริมาณ — โปรเจกต์เด็ด ๆ อันเดียวเหนือกว่าทูทอเรียลทำครึ่ง ๆ สิบอัน

มาถึงตอนนี้คุณสร้างของจริงมาแล้วหลายอย่างระหว่างเรียนหลักสูตรนี้ ทั้ง data structure, ระบบ gameplay เล็ก ๆ, บางทีก็ shader หรือ tool สักตัว แต่งานพวกนั้นจะไม่มีประโยชน์อะไรเลยตอนสมัครงาน ถ้าไม่มีใครนอกหัวของคุณเห็นมัน เข้าใจว่าคุณสร้างอะไร แล้วตัดสินได้ว่าคุณจะทำแบบนี้ซ้ำได้อีกไหมถ้าอยู่ในทีมของเขา นั่นคืองานทั้งหมดของ portfolio (ชุดผลงานสาธารณะที่คัดสรรมาอย่างดี สร้างมาให้คนแปลกหน้าตัดสินภายในเวลาจำกัด) หัวข้อนี้จะพูดถึงว่าทีมที่จ้างงานเช็คอะไรจริง ๆ ตอนเปิด portfolio ของคุณ ทำไม quality ถึงชนะ quantity แบบขาดลอย strong piece ของแต่ละสาย programming และ art หน้าตาเป็นยังไง ทำไม presentation ถึงกินคะแนนไปครึ่งหนึ่ง วิธีเขียนอธิบายโปรเจกต์ให้คนแปลกหน้าเข้าใจได้ในเวลาไม่ถึงนาที วิธีทำให้โค้ดกับ README ของคุณอ่านง่ายสำหรับคนที่ไม่เคยเห็น codebase คุณมาก่อน ควรเอาผลงานไปโพสต์ที่ไหน และแผนสร้าง portfolio แรกที่ทำได้จริงเมื่อคุณเรียนหลักสูตรนี้จบ

1. ทีมที่จ้างงานเช็คอะไรกันแน่

เรซูเม่ที่เขียนว่า "เคยใช้ Unity, C#, git" ไม่ได้บอกอะไรที่ทีมที่จ้างงานตรวจสอบได้เลย ใครก็พิมพ์ประโยคนี้ได้ไม่ว่าจริงหรือไม่จริง แต่ portfolio piece ต่างออกไป มันคือลิงก์ที่เขาเปิดดูได้เดี๋ยวนี้ แล้วเช็คด้วยตัวเอง นี่คือเหตุผลทั้งหมดที่ portfolio สำคัญกว่าลิสต์คำกล่าวอ้าง

ตอนที่ผู้พิจารณาเปิด portfolio ของคุณ จริง ๆ แล้วเขาเช็คอยู่สองอย่าง และแทบทุกอย่างในหัวข้อนี้มีไว้ช่วยให้คุณพิสูจน์ทั้งสองอย่างนั้น

ยังมีสิ่งที่สามที่ถูกเช็คไปพร้อมกันแบบเงียบ ๆ อีกอย่าง คือคุณยอมเสียเวลาของตัวเองมากแค่ไหนเพื่อทำให้คนอื่นตัดสินผลงานคุณได้ง่ายขึ้น ผู้พิจารณาที่มีใบสมัครกองเป็นตั้งไม่ได้เป็นหนี้คุณที่ต้องมาขุดหา repository รกๆ เพื่อหาส่วนที่น่าสนใจ หัวข้อ 8 กับหัวข้อ 10 จะกลับมาพูดเรื่องนี้ตรง ๆ แต่เริ่มไว้ตรงนี้ก่อนด้วยข้อเท็จจริงที่ควรจำไว้: ผู้พิจารณาทั่วไปใช้เวลาประมาณสามสิบวินาทีถึงสองนาทีในการตัดสินใจว่าจะดู portfolio อันไหนต่อให้ลึกขึ้น

HOW A REVIEWER ACTUALLY LOOKS AT YOUR PORTFOLIO 0:00 opens the link | v 0:05 looks at the top image or video thumbnail -> boring -> tab closes | 0:15 presses play on the 30-second video -> will not load -> tab closes | 0:30 video ends -- did the mechanic look fun, did the tool look useful? | 0:45 skims two or three screenshots | 1:00 reads the first two sentences of the writeup | 1:30 if still interested -> opens the code, skims file names, opens one file | 3:00 if still interested -> reads the full writeup, maybe plays the build Most portfolios lose the reviewer before 0:30.

ไม่มีอะไรใน timeline นี้ที่ไม่แฟร์หรือขี้เกียจในฝั่งผู้พิจารณาเลย สตูดิโอที่เปิดรับหนึ่งตำแหน่งอาจได้ใบสมัครเป็นร้อย ๆ การสแกนสามสิบวินาทีไม่ใช่การปฏิเสธความพยายามของคุณ — มันคือ filter และหน้าที่ของคุณคือทำให้สามสิบวินาทีแรกของ portfolio รอดจาก filter นี้ให้ได้

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

2. ความจริงที่โหดร้าย: Portfolio ส่วนใหญ่คือโฟลเดอร์ Tutorial ที่ทำค้างไว้

เปิด GitHub profile ของมือใหม่เกือบทุกคนดู คุณจะเห็นแพทเทิร์นที่คุ้นเคย: repository สิบสองถึงยี่สิบตัว ส่วนใหญ่ชื่อประมาณ Unity-Tutorial-Follow-Along, MyGame, หรือ MyGame2-final-FINAL commit history มักบอกเรื่องจริงอยู่แล้ว: commit รัว ๆ วันแรกกับวันที่สอง แล้วก็เงียบไปเลย ไม่มี README หรือมีแต่ยังเขียนว่า "TODO: write description" ไม่มีวิดีโอ ไม่มี screenshot บางทีถึงขั้นไม่รู้ว่าต้องรัน scene ไหนถึงจะเปิดโปรเจกต์ขึ้นมาได้

นี่ไม่ใช่นิสัยเสียอะไร มันเกิดขึ้นเพราะการตาม tutorial รู้สึกเหมือนได้ผลผลิตจริง ๆ — คุณพิมพ์โค้ดอยู่ วิดีโอมีความคืบหน้าให้เห็นตลอด แล้วจบแต่ละ session คุณก็มีโค้ดมากกว่าตอนเริ่ม แต่การตาม tutorial เป็นทักษะคนละอย่างกับการสร้างของจากไฟล์เปล่าแล้วตัดสินใจเองตอนมันพังในแบบที่ tutorial ไม่เคยพูดถึง tutorial ต่อให้ทำจนจบตามที่สอนเป๊ะ ๆ ส่วนใหญ่ก็แค่พิสูจน์ว่าคุณทำตามคำสั่งได้ ไม่ได้พิสูจน์ว่าคุณ debug การตัดสินใจออกแบบของตัวเองได้ และการ debug การตัดสินใจของตัวเองนี่แหละคืองานจริง ทุกวัน

ทั้งหมดนี้ไม่ได้แปลว่า tutorial เสียเวลาเปล่า มันเป็นวิธีที่เร็วที่สุดวิธีหนึ่งในการเรียนเทคนิคใหม่ และหลักสูตรนี้เองก็ใช้ตัวอย่างเล็ก ๆ แบบมีไกด์มาตลอดด้วยเหตุผลเดียวกัน ข้อผิดพลาดคือการเอา tutorial ที่ทำเสร็จมาใส่เป็น portfolio piece มันจะกลายเป็น portfolio piece ได้ก็ต่อเมื่อคุณเอาไปต่อยอดไกลกว่าที่ tutorial สอนมาก ๆ: เปลี่ยนกลไก, เพิ่มระบบที่ tutorial ไม่เคยพูดถึง, สร้างส่วนสำคัญใหม่ในแบบของตัวเอง แล้วซื่อสัตย์ใน writeup ว่าส่วนไหนมีไกด์ ส่วนไหนเป็นของคุณเอง

ข้อผิดพลาดที่พบบ่อย ปล่อย repository tutorial ที่ทำค้างไว้สิบห้าตัวเป็น public แล้วส่งลิงก์ GitHub profile ทั้งหมดบอกว่า "นี่คือ portfolio ของฉัน" ผู้พิจารณาที่คลิกเข้าไปสามตัวแล้วเจอว่าไม่มีอะไรรันได้จะไม่คลิกตัวที่สี่ ให้เลือกทำอย่างใดอย่างหนึ่ง: ทำ repository ให้เสร็จและขัดเกลาจนยืนได้ด้วยตัวเอง หรือไม่ก็ตั้งเป็น private แล้วอย่าเอามาโชว์ผู้พิจารณา ลิสต์สั้น ๆ ที่คัดมาแล้วดีกว่ากองรกยาว ๆ ที่ซื่อสัตย์เสมอ

3. Quality ชนะ Quantity: สามอันที่เสร็จ ชนะสิบอันที่ค้าง

นี่คือกฎที่สำคัญที่สุดข้อเดียวในหัวข้อนี้ และควรอธิบายว่าทำไมมันถึงจริง ไม่ใช่แค่พูดลอย ๆ เวลาของผู้พิจารณาคือทรัพยากรที่จำกัดในกระบวนการทั้งหมดนี้ ไม่ใช่จำนวนโปรเจกต์ของคุณ โปรเจกต์ที่ค้างสิบตัวทำให้ผู้พิจารณาต้องคลิกสิบครั้ง และหลังจากตัวที่สองที่รันไม่ได้หรือไม่มีอะไรให้ดูเกินวันที่สอง เขาก็เลิกคลิก — ไม่ใช่เพราะโหดร้าย แต่เพราะคลิกพลาดเก้าครั้งติดกันเป็นเหตุผลที่สมเหตุสมผลมากพอที่จะเลิกเชื่อลิงก์ที่สิบ ในขณะที่โปรเจกต์เสร็จแล้วขัดเกลาแล้วสามตัวใช้แค่สามคลิก และทุกคลิกให้รางวัลด้วยของจริงให้ดู เล่น หรืออ่าน แพทเทิร์นที่สองสร้างความเชื่อใจทุกคลิก แพทเทิร์นแรกทำลายมัน

TEN "PROJECTS" ON A GITHUB PROFILE THREE FINISHED PORTFOLIO PIECES -------------------------------------- -------------------------------- tutorial follow-along, stopped day 2 a dash mechanic with proper cancel windows, polished, 35 hrs tutorial follow-along, stopped day 1 a level-loading tool with half a platformer, no enemies yet a before/after demo video, 30 hrs another half platformer, different tutorial a rim-light shader with a written a shader that does not compile explanation of the technique, 25 hrs (6 more just like these) reviewer clicks each link and finds: reviewer clicks each link and finds: nothing that runs, nothing to judge something real, every single time

มีเหตุผลที่สองที่ quality ชนะ ซึ่งไม่เกี่ยวกับความอดทนของผู้พิจารณาเลย การทำโปรเจกต์ให้เสร็จคือสิ่งที่ทำให้ยี่สิบเปอร์เซ็นต์ที่ยากที่สุดของงานโผล่ขึ้นมา: บัคน่าเบื่อตาม edge case, ช่วงเวลาที่กลไกทำงานได้ในทางเทคนิคแต่รู้สึกผิด แล้วคุณต้องหาให้เจอว่าทำไม, การขัดเกลารอบสุดท้ายที่เปลี่ยน "มันรันได้" ให้กลายเป็น "มันไม่น่าอาย" tutorial ถูกออกแบบมาให้ข้ามยี่สิบเปอร์เซ็นต์นั้นเกือบทั้งหมด เพราะหน้าที่ของ tutorial คือพาคุณไปถึงผลลัพธ์ที่ใช้งานได้ตามตารางเวลา ไม่ใช่ทำให้คุณนั่งอยู่กับระบบครึ่ง ๆ กลาง ๆ ที่ดูแย่จนกว่าจะเข้าใจว่าทำไมมันถึงแย่ ยี่สิบเปอร์เซ็นต์นั้นแหละคือส่วนที่แยกคนทำเป็นงานอดิเรกออกจากคนที่พร้อมอยู่ในทีมจริง ๆ และมันจะโผล่ออกมาก็ต่อเมื่อคุณดันโปรเจกต์ไปจนเสร็จเท่านั้น

มีกฎง่าย ๆ ที่ตามมาจากตรงนี้โดยตรง: ถ้าโปรเจกต์ยังไม่เสร็จพอที่คนแปลกหน้าจะเปิดดูแล้วเข้าใจว่ามันทำอะไรได้ภายในประมาณสองนาที โดยไม่มีคุณยืนอธิบายอยู่ข้าง ๆ มันยังไม่ใช่ portfolio piece มันเป็นแค่ work in progress และหัวข้อ 12 จะพูดถึงมาตรฐานที่ต่ำกว่าสำหรับของแบบนั้นแทน

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

4. Strong Piece ตามสาย: Gameplay Programmer

ชิ้นงาน gameplay programming ถูกตัดสินจากสองอย่างพร้อมกัน: กลไก feel ดีไหม และโค้ดที่อยู่เบื้องหลังมองเห็นได้และมีเหตุผลรองรับไหม strong piece แทบไม่ใช่เกมทั้งเกมเลย มันคือกลไกเล็ก ๆ ที่แน่นและทำออกมาดีมากชิ้นเดียว — jump, dash, dodge roll, grapple hook, gravity-flip การพยายามทำเกมทั้งเกมที่มีห้าระบบ แต่ละระบบทำได้แค่หกสิบเปอร์เซ็นต์ ได้ portfolio piece ที่อ่อนแอกว่ากลไกเดียวที่ทำได้เก้าสิบห้าเปอร์เซ็นต์ ด้วยเหตุผลเดียวกับที่อาหารสามคอร์สที่ทุกจานสุกไม่ทั่วถึงแย่กว่าจานเดียวที่ทำสุกสมบูรณ์แบบ

"feel ดี" ไม่ใช่คำโฆษณาคลุมเครือในที่นี้ — มันคือชุดเทคนิคที่เรียนรู้ได้แบบเจาะจง และการเรียกชื่อมันใน writeup ของคุณก็เป็นส่วนหนึ่งของการพิสูจน์ว่าคุณเข้าใจสิ่งที่สร้างขึ้นมา สองอย่างที่พบบ่อยที่สุดสำหรับ movement:

writeup ที่ดีสำหรับ gameplay piece จะเรียกตัวเลขที่ปรับจริง ไม่ใช่แค่บอกว่ามีการปรับเกิดขึ้น: "coyote time เริ่มที่ 0.05 วินาทีแล้วรู้สึก unresponsive ตอน playtest ฉันปรับเป็น 0.12 วินาทีแล้วรู้สึกแฟร์โดยไม่ปล่อยให้ผู้เล่นโกง jump ช้าเห็นได้ชัด" ประโยคเดียวนั้นพิสูจน์ว่ามีการ iterate เกิดขึ้นจริง ซึ่งมีค่ากับผู้พิจารณามากกว่าคำกล่าวอ้างว่ากลไก "feel ดีมาก"

โค้ดสำคัญพอ ๆ กับ feel และต้องหาเจอง่าย ลิงก์ตรงไปที่ไฟล์เดียวที่สำคัญ — สำหรับ jump mechanic อาจจะเป็น PlayerController.cs หรือ JumpSystem.cs ไฟล์เดียว — แทนที่จะให้ผู้พิจารณาต้องขุดทั้ง repository ระหว่างการสแกนสามสิบวินาที หัวข้อ 10 จะพูดถึงวิธีทำให้ไฟล์เดียวนั้นอ่านง่ายเมื่อเขาเปิดมันขึ้นมา

5. Strong Piece ตามสาย: Graphics Programmer

ชิ้นงาน graphics ถูกตัดสินจากว่าคุณอธิบายเทคนิค rendering ด้วยคำพูดของตัวเองได้ไหม ไม่ใช่แค่ภาพสุดท้ายดูเท่ไหม ภาพ screenshot สวย ๆ อย่างเดียวแทบไม่พิสูจน์อะไรเลย ใครก็โหลด shader จาก asset store มาแล้วถ่าย screenshot ได้ หลักฐานความเข้าใจมาจากสามอย่างรวมกัน: ภาพ before ที่ชัดเจน ภาพ after ที่ชัดเจน และคำอธิบายเทคนิคด้วยคำพูดของตัวเองที่แสดงว่าคุณรู้ว่าทำไมภาพ after ถึงออกมาแบบนั้น

BEFORE (before.png) AFTER (after.png) - flat shading, one point light - a rim-light term added at grazing angles - silhouette is hard to read against - silhouette reads clearly even a dark background against a dark background - looks like a lighting bug - looks intentional, like the character is lit from behind TECHNIQUE (in the writeup, in your own words): "I compute the angle between the surface normal and the view direction. Where that angle is close to 90 degrees (the edge of the silhouette, from the camera's point of view) I add a bright rim color on top of the normal lit color. The effect is strongest at grazing angles and fades to nothing when you are looking straight at the surface."

สังเกตว่าคำอธิบายนั้นไม่ได้แค่พูดว่า "ฉันเพิ่ม rim lighting" มันอธิบายไอเดียเชิงเรขาคณิตจริง ๆ (มุมระหว่าง surface normal กับ view direction) และผลลัพธ์ภาพจริง ๆ (สว่างขึ้นที่มุม grazing จางลงเมื่อมองตรง) ระดับรายละเอียดแบบนี้คือสิ่งที่แยก "ฉันเข้าใจเทคนิคนี้" ออกจาก "ฉันตาม tutorial แล้วมันได้ผล"

writeup graphics ที่ดียังต้องเรียกชื่อ tradeoff ด้วย ไม่ใช่แค่ผลชนะ ทำไมถึงเลือกวิธีนี้แทนอีกวิธี — เช่น ทำไมเลือกเทคนิคแบบ screen-space แทนแบบ per-vertex หรือทำไมเลือก approximation ที่ถูกกว่าแทนที่จะแม่นยำทางฟิสิกส์ แล้ว approximation นั้นเสียอะไรไปบ้างใน edge case การเรียกชื่อ tradeoff แบบตั้งใจคือสัญญาณความเข้าใจจริงที่ผู้พิจารณาสาย graphics มองเห็นชัดที่สุดใน writeup สั้น ๆ

6. Strong Piece ตามสาย: Tools Programmer

งานสาย tools มีปัญหาเรื่อง presentation ที่สายอื่นไม่มี: งานมักมองไม่เห็นเลยเว้นแต่คุณจะตั้งใจสาธิตมัน วิดีโอ gameplay หรือภาพ shader before/after พูดแทนตัวเองได้อยู่แล้ว แต่ level-editor extension, batch-renaming script, หรือ build pipeline ที่ดีขึ้น ไม่มีอะไรน่าสนใจทางภาพเลยด้วยตัวมันเอง — คุณค่าทั้งหมดของมันคือ workflow ที่มันแทนที่ และ workflow คือสิ่งที่ต้องแสดงให้เห็นว่ามันเกิดขึ้นจริง screenshot จับภาพมันไม่ได้

หลักฐานที่แข็งแรงที่สุดสำหรับชิ้นงาน tools คือวิดีโอบันทึกหน้าจอสั้น ๆ ที่โชว์ before กับ after ติดกัน: "นี่คืองานเดียวกันที่ทำแบบ manual วิธีเก่า ใช้เวลาเท่านี้ — นี่คืองานเดียวกันทำด้วย tool ของฉัน ใช้เวลาเท่านี้" ตัวอย่างที่จับต้องได้: tool ที่ rename และเรียงเลขไฟล์ level ในโฟลเดอร์ใหม่ให้เรียงถูกต้องใน engine แบบ manual นักออกแบบอาจใช้เวลาสิบห้านาทีลากแล้ว rename ไฟล์สี่สิบไฟล์ทีละไฟล์ เสี่ยงพลาดได้ง่าย แต่ด้วย tool ผลลัพธ์เดียวกันใช้แค่กดปุ่มเดียวกับเวลาไม่กี่วินาที ความต่างนั้น ถ้าดูจริง ๆ ไม่ใช่แค่อ่านคำอธิบาย คือสิ่งที่ทำให้ผู้พิจารณาเข้าใจคุณค่าได้ทันที

Tip ชิ้นงาน tools ได้ประโยชน์มากจากประโยคสั้น ๆ ใน writeup ที่บอกว่า tool นี้มีไว้เพื่อใคร: "ตัวนี้ช่วยลดเวลา level designer ได้ประมาณสิบนาทีต่อ level และเขาไม่จำเป็นต้องรู้โค้ดเลยก็ใช้ได้" tool มีไว้ช่วย workflow ของคนอื่น การเรียกชื่อคนอื่นคนนั้นก็เป็นส่วนหนึ่งของการพิสูจน์ว่าคุณเข้าใจปัญหาจริง ๆ ไม่ใช่แค่โค้ด

7. Strong Piece ตามสาย: Technical Artist

Technical artist อยู่ระหว่าง art กับ code และชิ้นงานที่ดีต้องโชว์ทั้งสองฝั่งของสะพานนี้ ศิลปินส่วนใหญ่โชว์แค่ผลลัพธ์สุดท้ายที่สวยงาม แต่ portfolio piece ของ technical artist ต้องโชว์ วิธีการ ด้วย เพราะจุดประสงค์ทั้งหมดของ role นี้คือการสร้างเทคนิคที่ศิลปินคนอื่นในทีมเอาไปใช้ซ้ำและปรับแต่งได้ ไม่ใช่ภาพสุดท้ายที่ทำครั้งเดียวแล้วจบ

มีสองฟอร์แมตที่ทำสิ่งนี้ได้ดี breakdown คือชุดภาพทีละขั้นที่โชว์ effect ถูกสร้างขึ้นทีละเลเยอร์ — เช่น effect ไฟที่โชว์เป็นรูปทรง particle เปล่า ๆ ก่อน แล้วเพิ่ม color gradient แล้วเพิ่ม distortion แล้วเพิ่ม glow pass สุดท้าย เพื่อให้คนดูเห็นชัดว่าแต่ละเลเยอร์ช่วยอะไรบ้าง node graph คือกราฟ visual scripting จริง ๆ (shader graph, material graph, กราฟสไตล์ Blueprint) โชว์พร้อม annotation ของคุณเองที่อธิบายว่าแต่ละ node ทำอะไรและทำไมถึงต่อกันแบบนั้น

BASE COLOR TEXTURE --> [ Multiply ] --> [ Add Rim Light ] --> OUTPUT ^ ^ | | COLOR TINT FRESNEL TERM (a single color) (bright at grazing angles, dark straight-on)

กราฟที่มี annotation แบบนี้ทำสิ่งที่ภาพ render สุดท้ายทำไม่ได้: มันให้ผู้พิจารณาตรวจสอบได้ทีละ node ว่าคุณเข้าใจจริงว่าแต่ละส่วนของกราฟทำอะไร แทนที่จะต้องเชื่อว่าผลลัพธ์สวย ๆ นั้นไม่ได้ประกอบขึ้นมาจากการลองผิดลองถูกจนบังเอิญออกมาสวย ทั้งสองแบบเป็นวิธีสร้างของที่ใช้ได้ แต่มีแค่แบบเดียวที่พิสูจน์ว่าคุณสร้างมันขึ้นมาใหม่ได้ ปรับแต่งได้ หรือสอนคนอื่นได้ — ซึ่งเป็นสิ่งที่ role technical art ต้องการให้คุณทำจริง ๆ

8. Presentation คือครึ่งหนึ่งของคะแนน

portfolio piece สองชิ้นที่คุณภาพเบื้องหลังเท่ากันเป๊ะ ๆ อาจได้ปฏิกิริยาที่ต่างกันโดยสิ้นเชิงขึ้นอยู่กับว่านำเสนอยังไง และควรพูดตรง ๆ ว่าทำไม: ผู้พิจารณาที่สแกนใบสมัครหลายสิบใบในบ่ายเดียวแยกไม่ออกระหว่าง "ไม่มีโปรเจกต์" กับ "โปรเจกต์ดีแต่อธิบายแย่" ข้อความยาว ๆ ที่ไม่มีภาพเลยก็อ่านเหมือนข้อความยาว ๆ ไม่ว่ากลไกข้างในจะดีแค่ไหน presentation ไม่ใช่ของประดับบนงานจริง — สำหรับสามสิบวินาทีแรกที่ผู้พิจารณาให้ความสนใจ presentation คือ งานจริง เพราะมันคือส่วนเดียวที่เขาจะได้เห็นจริง ๆ

สูตรตามลำดับ จากบนลงล่างของหน้า:

================================================================== GRAVITY SNAP -- a puzzle-platformer about flipping gravity ================================================================== [ 30-SECOND VIDEO -- plays inline, shows the core mechanic first ] ................................................................ . . . (thumbnail: player flips gravity mid-air) . . . ................................................................ [ GIF: gravity flip ] [ GIF: chained flips ] [ GIF: one level, ] [ in mid-air ] [ through three rooms ] [ solved 3 ways ] [ screenshot: menu ] [ screenshot: level 4 ] [ screenshot: the ] [ level editor ] ------------------------------------------------------------ WRITEUP (below the fold -- most readers only skim this part) ------------------------------------------------------------ Problem: ... Approach: ... What was hard: ... What I would change: ... ------------------------------------------------------------ LINKS ------------------------------------------------------------ [ PLAY IN BROWSER ] [ SOURCE CODE ] [ FULL VIDEO ]

วิดีโอกับ GIF มาก่อนข้อความด้วยเหตุผลที่จับต้องได้ ไม่ใช่แค่ธรรมเนียม: screenshot นิ่ง ๆ ของกลไกที่เน้น movement หรือ feel แทบไม่มีประโยชน์เลย เพราะคุณเห็น feel ในภาพนิ่งไม่ได้ shader ต้องถูกดูตอนเคลื่อนไหวภายใต้แสงที่เปลี่ยนไป tool ต้องถูกดูอยู่ใน workflow จริง ๆ ที่มันช่วยให้เร็วขึ้น วิดีโอเป็นสื่อเดียวในลิสต์นี้ที่พิสูจน์คำกล่าวอ้างแบบ "มัน feel ดี" ได้จริง ไม่ใช่แค่กล่าวอ้างลอย ๆ ซึ่งตรงกับหลักฐานแบบที่หัวข้อ 1 บอกว่าผู้พิจารณากำลังมองหาพอดี

ข้อผิดพลาดที่พบบ่อย วิดีโอห้านาทีที่เปิดมาด้วย splash screen กับเมนูหลักสิบห้าวินาทีก่อนจะมีอะไรน่าสนใจเกิดขึ้น แทบไม่มีใครดูเกินสิบวินาทีแรกของฉากเปิดที่น่าเบื่อ ตัดวิดีโอให้เหลือช่วงที่ดีที่สุดแบบตั้งใจ — นี่เป็นทักษะที่ควรฝึกด้วยตัวมันเอง เหมือนวินัยเดียวกับการเขียน pitch ประโยคเดียวที่ดี และเป็นหนึ่งใน edit ที่คุ้มค่าที่สุดที่ทำได้กับ portfolio piece ที่มีอยู่แล้ว

9. วิธีเขียนอธิบายโปรเจกต์

project write-up มีหน้าที่เดียว: ให้คนแปลกหน้าที่ไม่เคยเห็นโค้ดคุณมาก่อนเข้าใจ ภายในเวลาไม่ถึงนาที ว่าคุณสร้างอะไร ทำไมถึงสร้างแบบนั้น และเรียนรู้อะไรระหว่างทำ โครงสร้างสี่ส่วนด้านล่างนี้ทำหน้าที่นั้นได้อย่างน่าเชื่อถือ เรียงตามลำดับที่คำถามของผู้พิจารณาที่อยากรู้จะเกิดขึ้นตามธรรมชาติ

PROBLEM one or two sentences: what were you trying to make, and for whom? | v APPROACH what did you actually build, and why that approach and not another one? | v WHAT WAS HARD the one or two things that did not work on the first try, and how you found out what was wrong and fixed it | v WHAT YOU WOULD DO DIFFERENTLY proof that you understand the tradeoffs you made, not just that the project runs

Write-up ที่อ่อนแอ

นี่คือ write-up ที่มือใหม่เกือบทุกคนเคยเขียนสักครั้ง มันไม่ได้ผิดขนาดนั้น — แค่มันไม่บอกอะไรที่ผู้พิจารณาเอาไปตัดสินอะไรได้เลย

This is a cool platformer game I made using Unity. It has jumping
and enemies. I used C# for the scripts. Check it out, link below!

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

โปรเจกต์เดียวกัน เขียนใหม่แบบแข็งแรง

โปรเจกต์เดียวกัน โค้ดเดียวกันด้วยซ้ำ เขียนใหม่ด้วยโครงสร้างสี่ส่วนจากไดอะแกรมด้านบน:

Problem
I wanted a jump that felt as responsive as the platformers I grew up
playing, where a jump pressed slightly after leaving a ledge still works.

Approach
I built a custom CharacterController2D instead of using Unity's
built-in physics jump, so I could control exactly when a jump is
allowed. I added a 0.12-second "coyote time" window after leaving
a platform, and a 0.15-second input buffer so a jump pressed just
before landing still fires the moment you land.

What was hard
My first version buffered the input but did not clear it correctly,
so a single jump press could fire twice if the player landed and then
walked off a second ledge quickly. I found the bug by logging every
jump event with a timestamp and noticing two fired within one frame.
I fixed it by clearing the buffer the instant a jump is consumed,
instead of only clearing it after the buffer window expired.

What I would do differently
I would add a small automated test for the buffer-clearing logic.
I found the double-jump bug by manually playing the game for about
twenty minutes, which is not a reliable way to catch a timing bug
this specific, and I got lucky that I noticed it at all.

ไม่มีอะไรในโปรเจกต์เบื้องหลังเปลี่ยนไปเลยระหว่างสองเวอร์ชัน — jump เดียวกัน บัคเดียวกัน fix เดียวกัน สิ่งที่เปลี่ยนคือเวอร์ชันที่สองให้ผู้พิจารณามีสี่อย่างที่จับต้องได้แยกกันไว้ตัดสิน: การตัดสินใจออกแบบจริง (coyote time กับ input buffering เรียกชื่อเจาะจง), บัคจริงพร้อมสาเหตุจริง, วิธี debug จริง (log พร้อม timestamp ไม่ใช่เดาส่ง) และความตระหนักรู้ในตัวเองจริงว่ากระบวนการที่ดีกว่าควรเป็นแบบไหน แต่ละอย่างมีค่ากับการตัดสินใจจ้างงานมากกว่าประโยค "มันมี jumping และ enemies" มาก

Tip ใช้ตัวเลขเจาะจงทุกครั้งที่ทำได้: "0.12 วินาที", "ลดงานจากสิบห้านาทีเหลือไม่กี่วินาที", "เจอหลังจาก log jump event ห้าสิบครั้ง" ตัวเลขเจาะจงอ่านแล้วเหมือนหลักฐาน คำคลุมเครืออย่าง "มีบัคบ้าง", "เร็วขึ้นเยอะ", หรือ "ดีขึ้นมาก" อ่านแล้วเหมือนคำกล่าวอ้างที่ตรวจสอบไม่ได้ ต่อให้มันเป็นจริงก็ตาม

ส่วน "what was hard" สมควรได้รับความใส่ใจเป็นพิเศษ เพราะมันมักเป็นส่วนที่น่าเชื่อถือที่สุดใน write-up ทั้งหมด และเป็นส่วนที่มือใหม่มักถูกล่อใจให้ข้ามไป การเรียกชื่อความยากจริง ๆ อย่างซื่อสัตย์ น่าเชื่อถือกับผู้พิจารณาที่มีประสบการณ์มากกว่าการอ้างว่าทุกอย่างราบรื่น — เพราะทุกคนที่เคยส่งงานจริงรู้ว่าไม่มีอะไรราบรื่นสมบูรณ์แบบเลย และผู้สมัครที่อ้างว่าราบรื่นอ่านแล้วดูเหมือนไม่มีประสบการณ์ หรือไม่ซื่อสัตย์เต็มที่เกี่ยวกับกระบวนการของตัวเอง บัคที่เจาะจงและอธิบายดี ๆ เป็นสัญญาณ portfolio ที่แข็งแรงกว่าโปรเจกต์ที่อ้างว่าไม่มีบัคเลย

10. โค้ดที่อ่านง่าย กับ README ที่ดี

โค้ดของคุณมีผู้อ่านสองแบบ และทั้งคู่ต้องสำเร็จได้แทบไม่ต้องออกแรง ไม่งั้นชิ้นงานจะถูกหักคะแนนไม่ว่ากลไกเบื้องหลังจะดีแค่ไหน ผู้อ่านคนแรกสแกนโค้ดคุณประมาณหกสิบวินาทีโดยไม่รันมัน อ่านอย่างเดียว ผู้อ่านคนที่สอง clone repository แล้วลอง build และรันจริง ๆ หัวข้อ 9 พูดถึงวิธีเขียนอธิบายโปรเจกต์ หัวข้อนี้พูดถึงการทำให้ตัวโปรเจกต์เองรอดจากผู้อ่านทั้งสองแบบ

เวอร์ชันรก

อันนี้ compile ได้ ทำงานได้ และทำตามที่ write-up แข็งแรงในหัวข้อ 9 อธิบายไว้เป๊ะ ๆ แต่มันยังเป็นไฟล์ portfolio ที่แย่ เพราะไม่มีใครสแกนหกสิบวินาทีแล้วบอกได้ว่ามันทำอะไร

public class GC : MonoBehaviour {
    public float f = 9.8f;
    bool g = false;
    void Update(){
        if(Input.GetKeyDown(KeyCode.Space)){
            g=!g;
            Physics.gravity = g ? new Vector3(0,f,0) : new Vector3(0,-f,0);
        }
    }
}

ผู้พิจารณาที่เห็นโค้ดนี้ต้อง reverse-engineer ก่อนว่า GC, f, และ g หมายถึงอะไร ก่อนจะเริ่มตัดสินได้ด้วยซ้ำว่า logic ดีหรือไม่ดี เวลา reverse-engineer นั้นหักออกมาจากหกสิบวินาทีที่หัวข้อ 1 บอกว่าคุณมีโดยตรง

เวอร์ชันสะอาด

public class GravityController : MonoBehaviour
{
    [SerializeField] float gravityStrength = 9.8f;
    bool isFlipped = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
            FlipGravity();
    }

    // Flips world gravity between pointing down (normal) and up (flipped).
    void FlipGravity()
    {
        isFlipped = !isFlipped;
        float direction = isFlipped ? 1f : -1f;
        Physics.gravity = new Vector3(0f, gravityStrength * direction, 0f);
    }
}

logic เดียวกัน จำนวนไอเดียจริงเท่ากัน แต่ผู้พิจารณาอ่านชื่อ class ชื่อ field และคอมเมนต์เดียวได้แล้วเข้าใจว่าไฟล์นี้ทำอะไร ก่อนที่จะต้องอ่าน method body อย่างละเอียดด้วยซ้ำ ชื่อที่ดีกับคอมเมนต์หนึ่งจุดที่วางไว้ถูกที่ทำงานเกือบทั้งหมดตรงนี้ — คอมเมนต์อธิบาย ทำไม ternary ถึงเลือกทิศทางแบบนั้น ซึ่งไม่ชัดเจนจากโค้ดอย่างเดียว แทนที่จะแค่พูดซ้ำสิ่งที่บรรทัดนั้นบอกอยู่แล้ว

ข้อผิดพลาดที่พบบ่อย เขียนคอมเมนต์ที่พูดซ้ำโค้ดแทนที่จะอธิบายเหตุผลเบื้องหลัง เช่น // set isFlipped to the opposite of isFlipped เหนือบรรทัด isFlipped = !isFlipped; คอมเมนต์แบบนั้นเพิ่มเวลาอ่านโดยไม่เพิ่มข้อมูลอะไรที่โค้ดยังไม่บอกอยู่แล้ว เก็บคอมเมนต์ไว้สำหรับส่วนที่ไม่ชัดเจนจากโค้ดเอง — "ทำไม" ไม่ใช่ "ทำอะไร"

README ที่ดีควรมีอะไรบ้าง

README คือไฟล์ที่ repository โชว์เป็นอันดับแรก และสำหรับ portfolio piece มันควรตอบตามลำดับ: นี่คืออะไร หน้าตาเป็นยังไง เล่นหรือรันยังไง และผู้เขียนเรียนรู้อะไร ผู้พิจารณาที่ clone repository คุณแล้วไม่เจอ README เลย หรือเจอแต่ชื่อโปรเจกต์อย่างเดียว ไม่มีทางรู้ได้เลยว่าโปรเจกต์นี้ทำงานได้จริงไหมโดยไม่ขุดหาไฟล์ source เอง — และตามหัวข้อ 1 เขาจะไม่ทำแบบนั้น

# Gravity Snap

A small puzzle-platformer where the player flips gravity to solve
rooms. Built solo in three weeks with Unity 2022 (C#).

[ GIF of the gravity-flip mechanic goes here ]

## Play it
- Browser build: https://username.itch.io/gravity-snap
- Video walkthrough: https://youtube.com/watch?v=xxxxxxx

## What this project is
- 8 hand-built levels
- a custom gravity-flip controller, see Assets/Scripts/GravityController.cs
- a small level editor used to place gravity zones, see Assets/Editor/

## How to run it from source
1. Clone the repo
2. Open the project with Unity 2022.3 LTS
3. Open Scenes/MainMenu.unity and press Play

## What was hard
Making the gravity flip feel instant but not disorienting. See the
"What was hard" section of the itch.io writeup for the three
iterations I tried before landing on the current version.

## What I would change
The level editor works, but only I can use it comfortably. It needs
on-screen labels before anyone else could use it without me
explaining every button first.

สังเกตว่า README เอาโครงสร้างสี่ส่วนเดียวกันจากหัวข้อ 9 มาใช้ซ้ำในสอง heading สุดท้าย นี่เป็นความตั้งใจ ไม่ใช่บังเอิญ — พอคุณเขียน problem, approach, difficulty, และ reflection ครั้งเดียวสำหรับ write-up บน itch.io หรือเว็บไซต์แล้ว การเอาโครงสร้างเดียวกันมาใช้ซ้ำใน README แทบไม่เสียแรงอะไรเพิ่มเลย และมันทำให้สองพื้นที่ที่สำคัญที่สุดของโปรเจกต์คุณ (หน้าที่ผู้พิจารณาเปิดเจอ กับ repository ที่เขาคลิกเข้าไป) เล่าเรื่องไปในทิศทางเดียวกัน

11. ควรโพสต์ผลงานไว้ที่ไหน และทำไม Playable Build ถึงชนะข้อความเยอะ ๆ

สถานที่ที่คุณเอาชิ้นงานที่เสร็จแล้วไปวางสำคัญพอ ๆ กับการทำมันให้เสร็จเลย เพราะสถานที่ที่ผิดเพิ่ม friction ที่หยุดผู้พิจารณาก่อนที่เขาจะได้เห็นงานคุณด้วยซ้ำ มีสามที่โฮสต์ที่ครอบคลุมสิ่งที่ portfolio ของมือใหม่ต้องการเกือบทั้งหมด

GitHub ยังสำคัญในฐานะจุดยึดทางเทคนิค — เป็นที่ที่ผู้พิจารณาที่สนใจจริง ๆ ไปอ่านโค้ดของคุณ ตามที่ timeline ในหัวข้อ 1 บอกไว้ตรงนาที 1:30 แต่สังเกตว่ามันอยู่ตรงไหนใน timeline นั้น — หลังจากวิดีโอกับ GIF ทำให้ผู้พิจารณาสนใจแล้ว ไม่ใช่แทนที่มัน ลิงก์ GitHub ที่ไม่มี playable build ไม่มีภาพอะไรแนบมาเลยเท่ากับขอให้ผู้พิจารณาจินตนาการเองทั้งหมด ซึ่งคนส่วนใหญ่ไม่ทำ

เหตุผลพื้นฐานที่ playable build หรือวิดีโอชนะข้อความยาว ๆ นั้นง่ายมาก: มันคือการพิสูจน์ด้วยการสาธิต ไม่ใช่พิสูจน์ด้วยคำกล่าวอ้าง ข้อความบอกได้ว่า "movement มัน responsive" GIF แค่โชว์ movement แล้วให้ผู้พิจารณาตัดสินเองว่าจริงไหม — ซึ่งทั้งน่าเชื่อถือกว่า เพราะเขาสรุปความเห็นเอง และประเมินได้เร็วกว่า เพราะตัดสินคลิปสามวินาทีใช้แรงน้อยกว่าอ่านและเชื่อย่อหน้าข้อความ

Tip itch.io free tier เพียงพอสำหรับ portfolio ตอน export WebGL หรือ HTML5 build ให้ทดสอบใน browser จริง ๆ ก่อนเผยแพร่หน้า export setting ที่รันได้ปกติใน editor บางทีพังแบบเงียบ ๆ ใน browser build และ browser build ที่พังแย่กว่าไม่มี build เลยด้วยซ้ำ เพราะมันเสียสามสิบวินาทีที่หัวข้อ 1 บอกว่าคุณมีไปฟรี ๆ

12. โชว์ Work in Progress ต่อสาธารณะเพื่อสร้างร่องรอย

ทุกอย่างในหัวข้อนี้จนถึงตอนนี้พูดถึงชิ้นงานที่เสร็จแล้ว มีหลักฐานอีกแบบหนึ่งที่เสริมกันได้ดีที่ควรสร้างควบคู่กันไป: ร่องรอยสาธารณะของ devlog (อัปเดตสั้น ๆ ที่โพสต์สม่ำเสมอโชว์โปรเจกต์ระหว่างที่ยังสร้างไม่เสร็จ) โพสต์ไว้ที่ไหนสักที่ที่มองเห็นได้ เช่นหน้า devlog บน itch.io, บล็อกส่วนตัว, หรือบัญชีโซเชียล

WEEK 1 devlog -- "collision with slopes is broken, here is why" WEEK 2 devlog -- "fixed the slope bug, gif of smooth movement now" WEEK 4 devlog -- "first playable level, feedback wanted" WEEK 6 devlog -- "added the gravity-flip mechanic, still feels floaty" WEEK 8 devlog -- "tuned gravity flip, feels snappy now, gif attached" WEEK 9 devlog -- "postmortem: three things I would do differently"

ชิ้นงานที่เสร็จแล้วพิสูจน์ว่าคุณทำของเสร็จได้ ร่องรอย devlog พิสูจน์สิ่งที่ชิ้นงานเสร็จชิ้นเดียวพิสูจน์ไม่ได้: คุณรักษาความพยายามต่อเนื่องได้หลายสัปดาห์ ทำงานต่อได้แม้กลไกยังรู้สึกผิดอยู่ และรับ feedback ระหว่างทางได้ ไม่ใช่โชว์งานหลังจากขัดเกลาเสร็จแล้วเท่านั้น พฤติกรรมเหล่านี้แหละคือสิ่งที่งานจริงต้องการทุกวัน มากกว่าโมเมนต์ "ship it" ที่ดราม่าจุดเดียวที่ portfolio piece ที่เสร็จแล้วจับภาพไว้ ผู้พิจารณาที่เห็นทั้งชิ้นงานที่เสร็จแล้วและร่องรอยรก ๆ รายสัปดาห์ที่นำไปสู่มัน จะได้ภาพที่ครบถ้วนและน่าเชื่อถือกว่าอย่างใดอย่างหนึ่งเพียงลำพัง

ข้อผิดพลาดที่พบบ่อย ปฏิบัติต่อโพสต์ devlog เหมือนต้องขัดเกลาระดับเดียวกับ portfolio piece ที่เสร็จแล้วจากหัวข้อ 3 ความคาดหวังแบบนั้นทำให้เกิด analysis paralysis แล้วสุดท้ายไม่ได้โพสต์อะไรเลย มาตรฐานของโพสต์ devlog คือความซื่อสัตย์ ไม่ใช่ความขัดเกลา "ยังพังอยู่ นี่คือทฤษฎีปัจจุบันของฉันว่าทำไม" เป็นโพสต์ที่โอเคอยู่แล้ว แยกสองมาตรฐานนี้ออกจากกัน: กฎ "ต้องเสร็จพอจะยืนได้เอง" จากหัวข้อ 3 ใช้กับ portfolio piece ไม่ใช่กับอัปเดต devlog

13. แผน Portfolio แรกที่ทำได้จริงสำหรับคนที่เรียนหลักสูตรนี้จบ

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

แผนนี้ตั้งใจ scope เล็กในทุกขั้นตอน มือใหม่ที่พยายามสร้างโปรเจกต์ทะเยอทะยานหนึ่งชิ้นให้เป็น portfolio ทั้งหมดกำลังรับความเสี่ยงแบบเดียวกับที่หัวข้อ 3 เตือนไว้พอดี: โปรเจกต์ทะเยอทะยานที่ไม่เสร็จหนึ่งชิ้นมีค่าน้อยกว่าโปรเจกต์เล็กที่เสร็จสามชิ้น ต่อให้ไอเดียของโปรเจกต์ทะเยอทะยานฟังดูดีกว่าก็ตาม เล็กและเสร็จ สามรอบ ด้วยสูตร presentation เดียวกันทุกครั้ง ทั้งเป็นแผนที่ทำได้จริงตามตารางเวลาของมือใหม่ และตามเหตุผลตลอดทั้งหัวข้อนี้ เป็น portfolio ที่แข็งแรงกว่าด้วย

14. Glossary

15. แบบฝึกหัด

แบบฝึกหัดที่ 1 — เขียน Write-up ที่อ่อนแอใหม่ นี่คือคำอธิบายโปรเจกต์ที่อ่อนแอสำหรับ tool level-editor: "I made a tool that lets you edit levels faster. It's written in C# for Unity. It saves time. Try it out!" ใช้โครงสร้างสี่ส่วนจากหัวข้อ 9 (Problem, Approach, What was hard, What you would do differently) เขียนใหม่ให้เป็น write-up ที่แข็งแรง คุณคิดรายละเอียดเจาะจงที่สมเหตุสมผลเองได้ (tool ทำอะไรจริง ๆ, อะไรที่ทำให้มันยาก, ตัวเลขที่ฟังดูจริง) ตราบใดที่มันสอดคล้องกับ tool level-editor
Show answer

ไม่มีคำตอบที่ถูกต้องเพียงหนึ่งเดียว — แบบฝึกหัดนี้เช็คว่าสี่ส่วนปรากฏครบตามลำดับ แต่ละส่วนมีเนื้อหาเจาะจงและจับต้องได้แทนคำกล่าวอ้างคลุมเครือ นี่คือหนึ่งเวอร์ชันที่สมเหตุสมผล:

Problem
Our level designer was spending about fifteen minutes per level manually
renaming and re-numbering exported level files so they would sort
correctly inside the engine, a pure copy-and-rename task with no
creative work in it at all.

Approach
I built an editor window in Unity that scans a folder of level files,
detects their current order from a data file, and renames and
re-numbers them all in one pass with a single button press. I chose
to read the intended order from a small JSON file instead of the
filenames themselves, so the designer could reorder levels without
ever touching a filename by hand.

What was hard
My first version renamed files in place one at a time, which
occasionally caused a naming collision partway through the batch --
for example, renaming file 3 to file 4 before file 4 had been moved
out of the way yet, silently overwriting it. I fixed it by renaming
every file to a temporary name first, then renaming all of them to
their final names in a second pass, so no two files ever collide.

What I would do differently
I would add a confirmation preview showing the old and new names
side by side before applying any rename, since the current version
has no undo and a mistake requires restoring from version control.

เทียบกับคำอธิบายต้นฉบับประโยคเดียว: เวอร์ชันเขียนใหม่ให้ผู้พิจารณามีปัญหาจริงพร้อมตัวเลข (สิบห้านาทีต่อ level), การตัดสินใจออกแบบจริงพร้อมเหตุผล (ไฟล์ JSON กำหนดลำดับแทนชื่อไฟล์), บัคจริงพร้อมสาเหตุจริงและ fix จริง (บัค rename ชนกัน) และความตระหนักรู้ในตัวเองจริงหนึ่งอย่าง (ยังไม่มี undo) เวอร์ชันเขียนใหม่ไหนก็ตามที่มีเนื้อหาสี่แบบนี้ครบ ต่อให้รายละเอียดที่คิดขึ้นเองต่างกัน ก็ผ่านแบบฝึกหัดนี้

แบบฝึกหัดที่ 2 — คัดเลือก Portfolio คุณสร้างโปรเจกต์มาแปดชิ้นในปีที่ผ่านมา ใช้เหตุผลจากหัวข้อ 3 ถึง 10 เลือกมาสามชิ้นเพื่อใส่ใน portfolio และอธิบายหนึ่งหรือสองประโยคต่อชิ้นว่าทำไมถึงเก็บหรือตัดชิ้นนั้นออก
1. Platformer tutorial follow-along, exact copy, unfinished
   (stuck on enemy AI).
2. A dash mechanic with proper cancel windows, fully polished,
   video recorded, code readable.
3. A Tetris clone, fully finished and bug-free, but no README,
   no video, no screenshots -- just raw source code.
4. A shader experiment that compiles but looks identical to a
   flat unlit material -- no visible technique to point to.
5. A level-loading tool, finished, with a 40-second demo video
   showing the manual workflow next to the tool's workflow.
6. A multiplayer lobby system, about 70 percent done, still has
   netcode bugs that must be fixed before it is usable.
7. A rim-light shader, finished, with before/after screenshots
   and a written explanation of the technique.
8. A racing game clone, fully finished, but nearly identical to
   its tutorial with only one small feature (a boost pad) added.
Show answer

เก็บ #2 (dash mechanic), #5 (level-loading tool), และ #7 (rim-light shader)

ทั้งสามชิ้นมีคุณสมบัติที่หัวข้อ 3 ต้องการ: เสร็จแล้ว และเสร็จพร้อมสูตร presentation เต็มจากหัวข้อ 8 ที่ใช้ไปแล้วหรือใช้ได้ชัดเจน (วิดีโอ, before/after, คำอธิบายเป็นลายลักษณ์อักษร) รวมกันแล้วทั้งสามชิ้นยังครอบคลุมสามสายจากหัวข้อ 4 ถึง 7 ซึ่งโชว์ความหลากหลายได้โดยไม่เจือจาง quality ตรงไหนเลย

อีกห้าชิ้นถูกตัด แต่ละชิ้นมีเหตุผลเจาะจงที่ระบุได้ ไม่ใช่แค่ "ไม่ดีเท่า":

  • #1 กับ #6 ยังไม่เสร็จตามกฎหลักของหัวข้อ 3 — ควรอยู่ในร่องรอย devlog (หัวข้อ 12) ไม่ใช่ในสามชิ้นที่คัดมา
  • #3 เสร็จแล้วแต่ไม่มี presentation เลย (หัวข้อ 8 กับหัวข้อ 10) — repository ดิบ ๆ ที่ไม่มี README ขอให้ผู้พิจารณาทำงานที่เขาจะไม่ทำ คุ้มค่าที่จะแก้ทีหลังแล้วพิจารณาใหม่ แต่ยังไม่พร้อมตอนนี้
  • #4 เสร็จแล้วและ compile ได้ทางเทคนิค แต่ไม่มีอะไรให้สาธิต — หัวข้อ 5 บอกชัดว่าชิ้นงาน graphics ต้องมี before/after ที่มองเห็นได้และเทคนิคที่อธิบายได้ ชิ้นนี้ไม่มีทั้งสองอย่าง
  • #8 เสร็จแล้วและนำเสนอได้ด้วยซ้ำ แต่คำเตือนของหัวข้อ 2 ใช้ได้เกือบเป๊ะ: มันคือ tutorial ที่เพิ่มฟีเจอร์หนึ่งอย่าง ซึ่งส่วนใหญ่พิสูจน์แค่ว่าคุณทำตามคำสั่งได้ ไม่ใช่ว่าคุณตัดสินใจออกแบบเองได้

คำตอบอีกแบบที่สมเหตุสมผลคือสลับเอา #3 มาแทนหนึ่งในสามชิ้น ถ้าคุณยอมเสียเวลาสักบ่ายเขียน README กับอัดวิดีโอสั้น ๆ ก่อน — คุณภาพของโปรเจกต์เบื้องหลังมีอยู่แล้ว แค่ presentation ยังขาดไปเท่านั้น

แบบฝึกหัดที่ 3 — เขียน README คุณสร้างระบบ inventory เล็ก ๆ สำหรับ RPG prototype ใน Unity: เพิ่มและลบไอเทมได้, รวมไอเทมซ้ำเป็น count เดียวอัตโนมัติแทนที่จะแยก slot, และแสดงทุกอย่างใน grid UI ง่าย ๆ ใช้ template README จากหัวข้อ 10 เขียน README สำหรับโปรเจกต์นี้
Show answer
# Inventory System

A small inventory system for an RPG prototype: add and remove items,
automatically stack duplicate items into one slot with a count, and
display everything in a grid UI. Built with Unity 2022 (C#).

[ GIF of picking up items and seeing them stack goes here ]

## Play it
- Browser build: https://username.itch.io/inventory-demo
- Video walkthrough: https://youtube.com/watch?v=yyyyyyy

## What this project is
- add/remove items through a simple ItemDatabase, see
  Assets/Scripts/Inventory.cs
- automatic stacking for duplicate item types, up to a max
  stack size defined per item
- a grid UI that updates live as the inventory changes, see
  Assets/Scripts/InventoryUI.cs

## How to run it from source
1. Clone the repo
2. Open the project with Unity 2022.3 LTS
3. Open Scenes/Demo.unity and press Play
4. Walk over the colored cubes to pick up sample items

## What was hard
Keeping the UI in sync with the data without rebuilding the whole
grid every frame. See the "What was hard" section of the itch.io
writeup for how I moved to an event-based update instead of a
per-frame refresh.

## What I would change
Item stacking currently has no per-item maximum stack size in the
data -- every item stacks to 99. I would move max stack size into
the ItemDatabase so different item types could have different limits.

สิ่งที่คำตอบนี้เช็ค นอกเหนือจากแค่กรอก template ให้ครบ: คำอธิบายหนึ่งบรรทัดบนสุดบอกจริง ๆ ว่าระบบทำอะไร (เพิ่ม/ลบ, การ stack, grid UI) แทนที่จะแค่บอกชื่อ ส่วน "how to run it" เจาะจงพอที่ใครสักคนจะทำตามได้จริงโดยไม่ต้องเดาว่าต้องเปิด scene ไหน และ "what I would change" เรียกชื่อข้อจำกัดจริงเจาะจง (ไม่มี max stack size ต่อไอเทม) แทนคำว่า "น่าจะดีกว่านี้ได้" ที่คลุมเครือ — ความซื่อสัตย์แบบเดียวกับที่หัวข้อ 9 ต้องการใน write-up เต็มก็ตกทอดมาสู่ README ด้วย

← กลับไปหน้ารวมบท