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

คุณเคยสงสัยไหมว่า เอฟเฟกต์เส้นแสงวิ่งวนในเกม bullet hell ที่ดูราวกับมีชีวิต ถูกสร้างขึ้นมาได้อย่างไร? คำตอบไม่ใช่การวาดเส้นด้วยมือ แต่เป็นสมการคณิตศาสตร์ที่มีชีวิต นั่นคือเส้นโค้งพาราเมตริก
ในบทความนี้ เราจะเปิดมุมมองใหม่ที่เชื่อมโยงคณิตศาสตร์ประยุกต์เข้ากับการพัฒนาเกมจริงใน Unity เพื่อให้คุณเห็นว่าสูตรที่เคยเรียนในห้องเรียนสามารถกลายเป็นเครื่องมือสร้างสรรค์ได้อย่างน่าทึ่ง
ทบทวนสูตรสั้น ๆ: Lissajous และ Hypocycloid
ก่อนกระโดดเข้าสู่โค้ด เรามาทบทวนสองเส้นโค้งที่จะใช้เป็นดาราในบทความนี้
เส้นโค้ง Lissajous
เส้นโค้ง Lissajous เกิดจากการผสมสองสมการตรีโกณมิติเข้าด้วยกัน โดยใช้พารามิเตอร์ t เป็นตัวกำหนดตำแหน่ง
x(t) = A * sin(a * t + delta)
y(t) = B * sin(b * t)
ค่า A และ B คือขนาดของเส้นโค้งในแกน x และ y ส่วน a และ b เป็นอัตราส่วนความถี่ ถ้า a และ b เป็นจำนวนเต็มที่ไม่มีตัวประกอดร่วม เส้นโค้งจะปิดสนิท ส่วน delta เป็นเฟสต่างกัน ทำให้รูปร่างเปลี่ยนได้ไม่รู้จบ
ในเกม Lissajous เหมาะกับการสร้างเส้นทางที่ดูเหมือนวงโคจรหรือลายเส้นที่ไหวเป็นจังหวะ
เส้นโค้ง Hypocycloid
Hypocycloid เกิดจากจุดบนเส้นรอบวงของวงกลมเล็กที่กลิ้งไปตามด้านในของวงกลมใหญ่ สูตรคือ
x(t) = (R - r) * cos(t) + r * cos((R - r) / r * t)
y(t) = (R - r) * sin(t) - r * sin((R - r) / r * t)
R คือรัศมีวงใหญ่ ส่วน r คือรัศมีวงเล็ก เมื่ออัตราส่วน R/r เป็นจำนวนตรรกยะ เส้นโค้งจะกลับมาจุดเริ่มต้นและปิดสนิท รูปทรงที่ได้มีตั้งแต่ดาวสามแฉก ดาวสี่แฉก ไปจนถึงลายซับซ้อนที่ดูคล้ายกลีบดอกไม้
ทั้งสองเส้นโค้งนี้เป็นหัวใจของการสร้างเอฟเฟกต์ภาพและเส้นทางการเคลื่อนที่สวยงามในเกม
เขียนโค้ดสร้างเส้นโค้งใน Unity ด้วย LineRenderer
ตอนนี้เรามาลงมือกัน ใน Unity เครื่องมือที่เหมาะกับการวาดเส้นโค้งคือ LineRenderer มันรับจุด (Vector3) หลายจุดแล้วเชื่อมเป็นเส้นได้ทันที
สร้าง C# Script ชื่อ ParametricCurveRenderer.cs แล้ววางโค้ดนี้ลงไป
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class ParametricCurveRenderer : MonoBehaviour
{
public enum CurveType { Lissajous, Hypocycloid }
public CurveType type = CurveType.Lissajous;
public int resolution = 500;
public float scale = 2f;
[Header("Lissajous Params")]
public float a = 3f;
public float b = 2f;
public float delta = 0f;
[Header("Hypocycloid Params")]
public float R = 3f;
public float r = 1f;
private LineRenderer lr;
void Start()
{
lr = GetComponent<LineRenderer>();
lr.useWorldSpace = false;
DrawCurve();
}
public void DrawCurve()
{
lr.positionCount = resolution;
for (int i = 0; i < resolution; i++)
{
float t = (float)i / resolution * Mathf.PI * 2f;
Vector3 pos = type == CurveType.Lissajous
? Lissajous(t)
: Hypocycloid(t);
lr.SetPosition(i, pos);
}
}
Vector3 Lissajous(float t)
{
float x = scale * Mathf.Sin(a * t + delta);
float y = scale * Mathf.Sin(b * t);
return new Vector3(x, y, 0f);
}
Vector3 Hypocycloid(float t)
{
float x = (R - r) * Mathf.Cos(t) + r * Mathf.Cos((R - r) / r * t);
float y = (R - r) * Mathf.Sin(t) - r * Mathf.Sin((R - r) / r * t);
return new Vector3(x * scale * 0.3f, y * scale * 0.3f, 0f);
}
}
วิธีใช้คือ สร้าง GameObject เปล่า แล้วเพิ่ม Component นี้เข้าไป Unity จะเติม LineRenderer ให้อัตโนมัติเพราะมี RequireComponent กำกับไว้ กด Play แล้วคุณจะเห็นเส้นโค้งปรากฏใน Scene View
ลองปรับค่า a, b, delta ใน Inspector แล้วกด Play ใหม่ คุณจะพบว่ารูปทรงเปลี่ยนไปอย่างสิ้นเชิง นี่คือพลังของพาราเมตริก เกม unity ที่ทำให้คณิตศาสตร์กลายเป็นภาพ
ปรับพารามิเตอร์แบบเรียลไทม์เพื่อสร้างเอฟเฟกต์ภาพ
การวาดเส้นโค้งครั้งเดียวตอน Start ก็สวย แต่ถ้าเราปรับพารามิเตอร์ทุกเฟรม เส้นโค้งจะเริ่มมีชีวิต ยกตัวอย่างเช่น การเปลี่ยนค่า delta ของ Lissajous อย่างต่อเนื่อง จะทำให้เส้นโค้งบิดเบี้ยวเหมือนคลื่นเสียง
เพิ่มโค้ดนี้ใน ParametricCurveRenderer.cs
void Update()
{
if (type == CurveType.Lissajous)
{
delta += Time.deltaTime * 0.5f;
DrawCurve();
}
}
เมื่อกด Play เส้นโค้งจะค่อย ๆ เปลี่ยนรูปร่างตลอดเวลา ลองนึกถึงการใช้เป็นเอฟเฟกต์โล่พลังงาน หรือเส้นแสงที่หมุนรอบตัวละคร คุณสามารถผูกค่า a และ b กับระดับพลังของผู้เล่น เพื่อให้เส้นโค้งซับซ้อนขึ้นเมื่อเลเวลสูงขึ้น
อีกไอเดียคือ ใช้ Hypocycloid สร้างลายเส้นที่หมุนช้า ๆ บนพื้นหลังของด่านบอส ให้ความรู้สึกลึกลับและมีพลัง แค่เปลี่ยนค่า r ไปเรื่อย ๆ ดาวแฉกจะค่อย ๆ กลายเป็นกลีบดอกไม้ แล้วกลับคืนรูปเดิม
void Update()
{
if (type == CurveType.Hypocycloid)
{
r = 1f + Mathf.Sin(Time.time * 0.3f) * 0.5f;
DrawCurve();
}
}
เทคนิคนี้ทำได้ง่ายแต่ให้ผลลัพธ์ที่น่าทึ่ง เหมาะกับเกมอินดี้ที่ต้องการสร้างจุดเด่นทางภาพโดยไม่ต้องพึ่งแอสเซตราคาแพง
ใช้เส้นโค้งสร้างเส้นทางเคลื่อนที่ของศัตรูในเกม
นอกจากเอฟเฟกต์ภาพ เส้นโค้งพาราเมตริกยังใช้กำหนดเส้นทางการเคลื่อนที่ของศัตรูได้ ทำให้ศัตรูเคลื่อนที่ในรูปแบบที่คาดเดายาก ไม่ใช่แค่เดินเป็นเส้นตรงหรือวงกลมธรรมดา
สร้าง Script ใหม่ชื่อ EnemyPathFollower.cs
using UnityEngine;
public class EnemyPathFollower : MonoBehaviour
{
public float speed = 1f;
public float scale = 3f;
public float a = 3f;
public float b = 4f;
public float delta = 0f;
private float t = 0f;
void Update()
{
t += Time.deltaTime * speed;
float x = scale * Mathf.Sin(a * t + delta);
float y = scale * Mathf.Sin(b * t);
transform.position = new Vector3(x, y, 0f);
}
}
ติด Script นี้ให้กับศัตรูในเกม แล้วลองปรับค่า a และ b ดู ศัตรูจะเคลื่อนที่เป็นลาย Lissajous ที่ดูเหมือนเต้นระบำ ผู้เล่นจะต้องสังเกตและหาจังหวะยิง ทำให้เกมมีความท้าทายทางการรับรู้
ถ้าต้องการให้ศัตรูหลายตัวเคลื่อนที่ในรูปแบบใกล้เคียงกันแต่ไม่ซ้ำกันเป๊ะ ให้ตั้งค่า delta ต่างกันเล็กน้อย ผลลัพธ์คือฝูงศัตรูที่เคลื่อนที่เป็นกลุ่มอย่างมีจังหวะ ดูสวยงามและน่าตื่นเต้น
กรณีศึกษาจริงจากเกม bullet hell หลายเกม เช่น Touhou Project ใช้เส้นโค้งพาราเมตริกควบคุมกระสุนและศัตรู ทำให้ลายกระสุนดูเป็นระบบและมีความสวยงามทางคณิตศาสตร์ นี่คือเหตุผลที่เกมประเภทนี้มีเสน่ห์ไม่มีตกยุค
ทิปเพิ่มประสิทธิภาพเมื่อวาดเส้นโค้งจำนวนมาก
เมื่อเกมมีศัตรูหรือเอฟเฟกต์จำนวนมาก การเรียก DrawCurve ทุกเฟรมอาจทำให้เฟรมเรตตก นี่คือทิปที่ช่วยให้เกมลื่นไหล
ลด resolution เมื่อเส้นโค้งเล็ก
เส้นโค้งที่เล็กบนหน้าจอไม่จำเป็นต้องมีจุดเยอะ ลดค่า resolution จาก 500 เหลือ 100 ก็ยังดูเรียบ ประหยัด CPU ได้มาก
public int resolution = 100;
ใช้ Coroutine แทน Update
ถ้าเส้นโค้งเปลี่ยนช้า ไม่จำเป็นต้องอัปเดตทุกเฟรม ใช้ Coroutine อัปเดตทุก 0.1 วินาทีก็พอ
IEnumerator SlowUpdate()
{
while (true)
{
delta += 0.05f;
DrawCurve();
yield return new WaitForSeconds(0.1f);
}
}
ใช้ Object Pooling สำหรับ LineRenderer
ถ้าเส้นโค้งถูกสร้างและทำลายบ่อย เช่นเอฟเฟกต์กระสุน ให้ใช้ Object Pooling นำ LineRenderer กลับมาใช้ใหม่แทนการ Instantiate และ Destroy ซ้ำ ๆ จะลดภาระ Garbage Collector
พิจารณาใช้ Mesh แทน LineRenderer สำหรับเส้นจำนวนมาก
LineRenderer สะดวกแต่มีข้อจำกัดด้านประสิทธิภาพเมื่อใช้จำนวนมาก ถ้าเกมต้องวาดเส้นนับร้อยพร้อมกัน ลองสร้าง Mesh เองโดยใช้ MeshFilter และ MeshRenderer จะควบคุมได้ละเอียดกว่าและเร็วกว่า
ใช้ Shader สำหรับเอฟเฟกต์เส้นโค้งแบบซับซ้อน
ถ้าต้องการเอฟเฟกต์เรืองแสงหรือเบลอ การวาดเส้นใน CPU แล้วโพสต์โพรเซสใน Shader จะให้ผลลัพธ์สวยกว่าและไม่กิน CPU
สรุป
เส้นโค้งพาราเมตริกเป็นสะพานเชื่อมระหว่างคณิตศาสตร์และศิลปะในเกม ด้วยสูตรง่าย ๆ อย่าง Lissajous และ Hypocycloid คุณสามารถสร้างเอฟเฟกต์ภาพและเส้นทางการเคลื่อนที่ทำให้เกมโดดเด่น โดยไม่ต้องพึ่งแอสเซตราคาแพง
สิ่งสำคัญคือการทดลอง ลองปรับพารามิเตอร์ต่าง ๆ ดู บางครั้งค่าที่ไม่คาดฝันก็ให้ผลลัพธ์ที่สวยที่สุด และอย่าลืมคำนึงถึงประสิทธิภาพเมื่อใช้ในเกมจริง
ถ้าคุณอยากลองเลย ให้เปิด Unity สร้าง Scene เปล่า แล้ววางโค้ดในบทความนี้ลงไป ภายใน 10 นาทีคุณจะเห็นเส้นโค้งแรกของคุณปรากฏขึ้น
คุณมีไอเดียอะไรที่อยากนำเส้นโค้งพาราเมตริกไปใช้ในเกมของคุณบ้าง? แชร์มาคุยกันได้ในคอมเมนต์ เราอยากรู้ว่าคุณจะสร้างอะไรจากสูตรเหล่านี้
เนื้อหาที่จัดทำโดยมี AI ช่วยจะมีป้ายกำกับ "เรียบเรียงโดยมี AI ช่วย" เพื่อให้คุณทราบอย่างชัดเจน เราถือว่าความโปร่งใสเรื่องการใช้ AI เป็นสิ่งสำคัญต่อความไว้วางใจของผู้อ่าน
ความคิดเห็น (0)
ยังไม่มีความคิดเห็น — มาเป็นคนแรกกันเถอะ!