วิธีการสร้างและเขียน Script การให้คะแนน แบบ 2 มิติ

โดยการแยกโค้ดออกเป็นหลาย Class เพื่อให้การจัดการโปรเจกต์ให้เป็นระเบียบและง่ายต่อการบำรุงรักษา (Modular Design)


โครงสร้าง Class

แยกโค้ดออกเป็น 3 Class หลักๆ ดังนี้:

  1. ScoreManager: ทำหน้าที่จัดการและแสดงผลคะแนนบน UI.
  2. ScoreUpObject: ทำหน้าที่เพิ่มคะแนนเมื่อผู้เล่นชน.
  3. ScoreDownObject: ทำหน้าที่ลดคะแนนเมื่อผู้เล่นชน.

การเตรียมการใน Unity (ปรับปรุง)

การเตรียม GameObjects จะคล้ายเดิม แต่มีบางจุดที่ต้องปรับเปลี่ยนเล็กน้อย:

  1. วัตถุผู้เล่น (Player GameObject):
    • เหมือนเดิมคือมี Rigidbody2D (Dynamic), Collider2D (Is Trigger).
    • สิ่งสำคัญ: ผู้เล่นจะ ไม่จำเป็นต้องมี Script ใดๆ ที่เกี่ยวกับการชนคะแนนโดยตรง อีกต่อไป แต่ผู้เล่นจะต้องมี Collider2D ที่เป็น Is Trigger เพื่อให้วัตถุอื่นสามารถตรวจจับการชนได้.
  2. วัตถุที่ทำให้คะแนนเพิ่ม (ScoreUp GameObject):
    • มี Collider2D (Is Trigger), Rigidbody2D (Kinematic).
    • ไม่ต้องตั้ง Tag เป็น ScoreUp อีกแล้ว.
    • ลาก C# Script ชื่อ ScoreUpObject ไปใส่ที่ GameObject นี้.
  3. วัตถุที่ทำให้คะแนนลด (ScoreDown GameObject):
    • มี Collider2D (Is Trigger), Rigidbody2D (Kinematic).
    • ไม่ต้องตั้ง Tag เป็น ScoreDown อีกแล้ว.
    • ลาก C# Script ชื่อ ScoreDownObject ไปใส่ที่ GameObject นี้.
  4. UI สำหรับแสดงคะแนน (Score Text UI):
    • สร้าง Text - TextMeshPro เหมือนเดิม ตั้งชื่อเป็น ScoreText.
  5. GameObject สำหรับจัดการคะแนน (ScoreManager GameObject):
    • สร้าง GameObject เปล่าๆ หนึ่งอัน (คลิกขวาที่ Hierarchy -> Create Empty) ตั้งชื่อว่า ScoreManager.
    • ลาก C# Script ชื่อ ScoreManager ไปใส่ที่ GameObject นี้.

โค้ด C# (แยก Class)

1. ScoreManager.cs (Class สำหรับจัดการและแสดงผลคะแนน)

สร้าง C# Script ชื่อ ScoreManager แล้วคัดลอกโค้ดนี้ลงไป:

C#

using UnityEngine;
using TMPro; // จำเป็นต้องใช้สำหรับ TextMeshProUGUI

public class ScoreManager : MonoBehaviour
{
    // Instance (singleton pattern) เพื่อให้ Class อื่นเรียกใช้ได้ง่าย
    public static ScoreManager Instance { get; private set; }

    // ตัวแปรสำหรับเก็บคะแนนปัจจุบัน
    private int score = 0;

    // อ้างอิงถึง TextMeshProUGUI UI ที่จะแสดงคะแนน
    [SerializeField] private TextMeshProUGUI scoreText; // [SerializeField] ทำให้เห็นใน Inspector แม้จะเป็น private

    // Property สำหรับเข้าถึงคะแนนจากภายนอก (อ่านได้อย่างเดียว)
    public int CurrentScore
    {
        get { return score; }
    }

    private void Awake()
    {
        // ตรวจสอบว่ามี Instance อื่นอยู่แล้วหรือไม่
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject); // ทำลายตัวเองถ้ามี Instance อื่นอยู่แล้ว
        }
        else
        {
            Instance = this; // กำหนด Instance เป็นตัวเอง
        }
    }

    void Start()
    {
        // ตรวจสอบว่าได้กำหนด TextMeshProUGUI ใน Inspector แล้วหรือไม่
        if (scoreText == null)
        {
            Debug.LogError("Score Text UI is not assigned in ScoreManager! Please assign it in the Inspector.");
        }
        // อัปเดตคะแนนเริ่มต้นบนหน้าจอ
        UpdateScoreText();
    }

    /// <summary>
    /// เพิ่มคะแนน
    /// </summary>
    /// <param name="amount">จำนวนคะแนนที่จะเพิ่ม</param>
    public void AddScore(int amount)
    {
        score += amount;
        UpdateScoreText();
        Debug.Log("Score Increased! Current Score: " + score);
    }

    /// <summary>
    /// ลดคะแนน
    /// </summary>
    /// <param name="amount">จำนวนคะแนนที่จะลด</param>
    public void DecreaseScore(int amount)
    {
        score -= amount;
        // ตรวจสอบไม่ให้คะแนนติดลบ (ถ้าต้องการ)
        if (score < 0)
        {
            score = 0;
        }
        UpdateScoreText();
        Debug.Log("Score Decreased! Current Score: " + score);
    }

    /// <summary>
    /// ฟังก์ชันสำหรับอัปเดตข้อความคะแนนบน UI
    /// </summary>
    private void UpdateScoreText()
    {
        if (scoreText != null)
        {
            scoreText.text = "Score: " + score.ToString();
        }
    }
}

คำอธิบาย ScoreManager.cs:

  • public static ScoreManager Instance { get; private set; }: นี่คือการใช้ Singleton Pattern ซึ่งทำให้เราสามารถเข้าถึง ScoreManager ได้จากที่ไหนก็ได้ในโค้ด โดยไม่ต้องอ้างอิง GameObject โดยตรง. มีแค่ Instance เดียวเท่านั้นที่สามารถมีอยู่ได้ใน Scene.
  • [SerializeField] private TextMeshProUGUI scoreText;: เรายังคงเก็บ reference ของ Text UI ไว้ที่นี่ แต่เปลี่ยนจาก public เป็น private และใช้ [SerializeField] เพื่อให้ยังสามารถลาก ScoreText GameObject ไปใส่ใน Inspector ได้.
  • Awake(): ฟังก์ชันนี้จะถูกเรียกก่อน Start(). เราใช้มันเพื่อตั้งค่า Instance ของ ScoreManager. ถ้ามี ScoreManager ตัวอื่นอยู่แล้ว จะทำลายตัวเองทิ้ง เพื่อให้มั่นใจว่ามีแค่ตัวเดียวในเกม.
  • AddScore(int amount) และ DecreaseScore(int amount): เป็น public method ที่คลาสอื่นจะเรียกใช้เพื่อเพิ่มหรือลดคะแนน.
  • UpdateScoreText(): อัปเดต UI ข้อความคะแนน.

2. ScoreUpObject.cs (Class สำหรับวัตถุที่ชนแล้วคะแนนเพิ่ม)

สร้าง C# Script ชื่อ ScoreUpObject แล้วคัดลอกโค้ดนี้ลงไป:

C#

using UnityEngine;

public class ScoreUpObject : MonoBehaviour
{
    // จำนวนคะแนนที่จะเพิ่มเมื่อผู้เล่นชนวัตถุนี้
    public int scoreIncreaseAmount = 10;

    // ฟังก์ชันนี้จะถูกเรียกเมื่อ Collider 2D ของวัตถุนี้ (ScoreUpObject) ไปชนกับ Collider 2D อื่น
    // โดยที่ Collider อื่นนั้นต้องทำเครื่องหมาย Is Trigger ไว้
    private void OnTriggerEnter2D(Collider2D other)
    {
        // ตรวจสอบว่าวัตถุที่ชนเข้ามาคือผู้เล่น (หรือมี Component ที่เราสนใจ)
        // ในที่นี้ เราแค่ต้องการให้วัตถุชนกับอะไรก็ตามที่มี Collider2D (เช่นผู้เล่น) ก็ให้คะแนนเพิ่ม
        // คุณอาจเพิ่มการตรวจสอบ Tag ของผู้เล่นได้ เช่น if (other.CompareTag("Player"))
        if (other.GetComponent<Collider2D>() != null) // ตรวจสอบว่าชนกับวัตถุที่มี Collider2D
        {
            // เรียกใช้ AddScore() ของ ScoreManager ผ่าน Instance
            ScoreManager.Instance.AddScore(scoreIncreaseAmount);

            // ทำลายวัตถุนี้หลังจากถูกชน
            Destroy(gameObject);
        }
    }
}

คำอธิบาย ScoreUpObject.cs:

  • public int scoreIncreaseAmount = 10;: กำหนดค่าคะแนนที่จะเพิ่มเมื่อวัตถุนี้ถูกชน. คุณสามารถปรับค่านี้ได้ใน Inspector สำหรับแต่ละวัตถุ ScoreUpObject.
  • OnTriggerEnter2D(Collider2D other): ฟังก์ชันนี้จะถูกเรียกเมื่อมีวัตถุอื่นที่มี Collider2D และเป็น Is Trigger มาชนวัตถุนี้.
  • ScoreManager.Instance.AddScore(scoreIncreaseAmount);: นี่คือส่วนสำคัญ เราเรียกใช้ AddScore method ของ ScoreManager ผ่าน Instance เพื่อเพิ่มคะแนน.

3. ScoreDownObject.cs (Class สำหรับวัตถุที่ชนแล้วคะแนนลด)

สร้าง C# Script ชื่อ ScoreDownObject แล้วคัดลอกโค้ดนี้ลงไป:

C#

using UnityEngine;

public class ScoreDownObject : MonoBehaviour
{
    // จำนวนคะแนนที่จะลดเมื่อผู้เล่นชนวัตถุนี้
    public int scoreDecreaseAmount = 5;

    // ฟังก์ชันนี้จะถูกเรียกเมื่อ Collider 2D ของวัตถุนี้ (ScoreDownObject) ไปชนกับ Collider 2D อื่น
    // โดยที่ Collider อื่นนั้นต้องทำเครื่องหมาย Is Trigger ไว้
    private void OnTriggerEnter2D(Collider2D other)
    {
        // ตรวจสอบว่าวัตถุที่ชนเข้ามาคือผู้เล่น (หรือมี Component ที่เราสนใจ)
        if (other.GetComponent<Collider2D>() != null) // ตรวจสอบว่าชนกับวัตถุที่มี Collider2D
        {
            // เรียกใช้ DecreaseScore() ของ ScoreManager ผ่าน Instance
            ScoreManager.Instance.DecreaseScore(scoreDecreaseAmount);

            // ทำลายวัตถุนี้หลังจากถูกชน
            Destroy(gameObject);
        }
    }
}

คำอธิบาย ScoreDownObject.cs:

  • public int scoreDecreaseAmount = 5;: กำหนดค่าคะแนนที่จะลดเมื่อวัตถุนี้ถูกชน.
  • OnTriggerEnter2D(Collider2D other): ทำงานคล้ายกับ ScoreUpObject
  • ScoreManager.Instance.DecreaseScore(scoreDecreaseAmount);: เรียกใช้ DecreaseScore method ของ ScoreManager ผ่าน Instance เพื่อลดคะแนน.

ขั้นตอนการตั้งค่าใน Unity Editor (สรุป)

  1. สร้าง Script ทั้ง 3 ตัว: ScoreManager.cs, ScoreUpObject.cs, ScoreDownObject.cs.
  2. ScoreManager Setup:
    • สร้าง Empty GameObject ชื่อ ScoreManager ใน Hierarchy.
    • ลาก Script ScoreManager.cs ไปใส่ที่ GameObject นี้.
    • ใน Inspector ของ ScoreManager GameObject ให้ลาก ScoreText UI ที่คุณสร้างไว้ใน Hierarchy ไปใส่ในช่อง Score Text.
  3. ScoreUpObject Setup:
    • ไปที่ GameObject ที่เป็นวัตถุเพิ่มคะแนนของคุณ (เช่น เหรียญ).
    • ลาก Script ScoreUpObject.cs ไปใส่ที่ GameObject นี้.
    • ตั้งค่า Score Increase Amount ใน Inspector (เช่น 10).
    • ตรวจสอบว่ามี Collider2D (Is Trigger) และ Rigidbody2D (Kinematic).
  4. ScoreDownObject Setup:
    • ไปที่ GameObject ที่เป็นวัตถุลดคะแนนของคุณ (เช่น ระเบิด).
    • ลาก Script ScoreDownObject.cs ไปใส่ที่ GameObject นี้.
    • ตั้งค่า Score Decrease Amount ใน Inspector (เช่น 5).
    • ตรวจสอบว่ามี Collider2D (Is Trigger) และ Rigidbody2D (Kinematic).
  5. Player GameObject:
    • ตรวจสอบว่ามี Collider2D (Is Trigger) และ Rigidbody2D (Dynamic).
    • ไม่ต้องมี Script ที่เกี่ยวข้องกับการชนคะแนน.

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

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

ตั้งค่าความเป็นส่วนตัว

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

ยอมรับทั้งหมด
จัดการความเป็นส่วนตัว
  • เปิดใช้งานตลอด

บันทึกการตั้งค่า