วันอังคารที่ 27 ตุลาคม พ.ศ. 2558

[Unity 2D] สร้างเกมง่ายๆ Tappy Plane ตอนที่ 15 : นับคะแนน

UI แสดงคะแนน

สร้างเกมออบเจ็ค Canvas ขึ้นมาใหม่ ในที่นี้จะตั้งชื่อว่า CanvasScore เพื่อใช้แสดง UI สำหรับนับคะแนนเมื่อเครื่องบินได้ทำการบินผ่านสิ่งกีดขวางได้สำเร็จ

จากนั้นให้ปรับค่า Reference Resolution X เท่ากับ 1280 และ Y เท่ากับ 720
สร้างเกมออบเจ็ค Text ขึ้นมาให้เป็น Child ของ CanvasScore ในที่นี้จะตั้งชื่อว่า TxtScore
ที่หน้าต่าง Inspector เปลี่ยน Font เป็น kenvector_future จากนั้นตั้งค่าให้ Alignment เป็นกึ่งกลาง ติ๊กถูกที่ Best Fit และตั้งค่าให้ Min Size เท่ากับ 10 และ Max Size เท่ากับ 100 ที่ Color เปลี่ยนสีตัวอักษรให้เป็นสีขาว
ที่ตำแหน่ง Y เปลี่ยนค่าเป็น 179 และกำหนด Width เป็น 200 และ Height เป็น 300
ต่อไปเราจะมาเพิ่มมิติให้กับตัวอักษรด้วยการใส่เงา ดังนี้ Add Component -> UI ->Effects -> Shadow
โดยที่เราจะใส่ Shadow 2 ชั้นเพื่อความมีมิติมากขึ้น สีแรกจะเป็นโทนสีเหลืองโทนเดียวกับภาพ Get Ready บน UI Game Start
ใส่เงานอีกสีหนึ่งเป็นสีเทา
ในหน้าต่าง Inspector มี Component Shadow 2 ตัวดังภาพ
จะได้ผลลัพธ์ดังนี้
จากนั้นลบข้อความใน Text ออก เนื่องจากในส่วนแสดงผลคะแนนเราจะทำที่โค้ดในภายหลังกัน

การนับคะแนน

ไปที่เกมออบเจ็ค Rock1 สร้างเกมออบเจ็คขึ้นมาใหม่ให้เป็นลูกของ Rock1 โดยการคลิกขวาที่เกมออบเจ็ค Rock1 จากนั้นเลือก Create Empty ในที่นี้จะตั้งชื่อเกมออบเจ็คนี้ว่า Score
จากนั้นทำการเพิ่ม Component BoxCollider2D ให้กับเกมออบเจ็ค Score

ติ๊กถูกที่ IsTrigger เนื่องจากเมื่อเครื่องบินมีการบินผ่านเกมออบเจ็คเช็คคะแนนอันนี้แสดงว่าบินผ่านสิ่งกีดขวางสำเร็จ เราจะทำการบวกคะแนนให้และแสดง UI คะแนนในภายหลัง
ที่ขนาดของ BoxCollider2D ให้ X เป็น 1 และ Y เป็น 5 จากนั้นปรับตำแหน่ง X ให้เท่ากับ 1 จะได้ผลลัพธ์ ดังภาพ
สร้าง Layer ใหม่ชื่อว่า Score

สร้าง Tag ใหม่ชื่อว่า Score
ที่เกมออบเจ็ค Rock1 ไปที่เกมออบเจ็คลูกที่ชื่อ Score เลือก Tag และ Layer ให้เป็น Score ที่ได้ทำการสร้างไว้เมื่อสักครู่
คลิก Apply ที่ Prefab จากนั้นตรวจสอบดูที่เกมออบเจ็ค Rock ทุกๆตัวว่ามีเกมออบเจ็ค Score เรียบร้อยดีหรือไม่

ไปที่ Edit -> Project Settings -> Physics 2D
จากนั้นให้ทำการตั้งค่าการ Collision ของ Layer Score ให้เกิดขึ้นกับ Layer Plane เท่านั้น ดังภาพ
สร้าง C# Script ในที่นี้ให้ใช้ชื่อว่า Score

สร้างตัวแปรสำหรับนับคะแนน
private int _Score = 0;

จากนั้นสร้างฟังก์ชั่น OnTriggerEnter2D ขึ้นมา เมื่อเครื่องบินมีการบินผ่านเกมออบเจ็คที่ใช้สำหรับเช็คคะแนนจะทำการเพิ่มคะแนนให้กับตัวแปร _Score 1 คะแนน

public void OnTriggerEnter2D(Collider2D collider)
  {
    if (collider.gameObject.tag == "Score")
    {
      _Score++;
    }
  }

เพิ่ม Code ดังต่อไปนี้ที่ด้านบนสุด เนื่องจากเราจะทำการเรียกใช้คลาส Text ของ UnityEngine.UI
using UnityEngine.UI;

จากนั้นสร้างตัวแปร publish Text ขึ้นมา เพื่อใช้แสดงคะแนน
public Text _TxtScore;

กลับไปที่ Scene Game ที่เกมออบเจ็ค Plane ให้ทำการเพิ่ม Component Score Script ที่เราทำการสร้างเมื่อสักครู่นี้เข้าไป
ที่ Txt Score ให้ใส่เกมออบเจ็ค TxtScore ของ CanvasScore
จากนั้นให้กลับไปที่ Script Score ทำการเซ็ท _TxtScore ให้แสดง Text เท่ากับจำนวนคะแนนในปัจจุบัน ดังนี้
_TxtScore.text = _Score.ToString();

จะได้ Code ทั้งหมด ดังนี้
using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class Score : MonoBehaviour
{
  private int _Score = 0;

  public Text _TxtScore;

  public void OnTriggerEnter2D(Collider2D collider)
  {
    if (collider.gameObject.tag == "Score")
    {
      _Score++;
      _TxtScore.text = _Score.ToString(); //แปลง int เป็น string
    }
  }
}

ลองทดสอบโดยการรันเกมจะเห็นว่าเมื่อบินผ่านสิ่งกีดขวางจะมีคะแนนแสดงขึ้นมาเรียบร้อย
แต่เมื่อขึ้น UI Game Over คะแนนยังไม่แสดงผล ดังนั้นต่อไปเราจะมาทำให้ UI Game Over แสดงผลคะแนนให้ถูกต้อง
ใน Script Score ให้เพิ่มตัวแปร public Text _TxtScoreGameOver; เพื่อใช้อ้างอิงถึงเกมออบเจ็ค Text ที่จะใช้แสดงผลคะแนนใน UI Game Over

จากนั้นให้เพิ่ม _TxtScoreGameOver.text = "Score : " + _Score; ในฟังก์ชั่น OnTriggerEnter2D ดังนี้

public void OnTriggerEnter2D(Collider2D collider)
  {
    if (collider.gameObject.tag == "Score")
    {
      _Score++;
      _TxtScore.text = _Score.ToString();
      _TxtScoreGameOver.text = "Score : " + _Score;
    }
  }

กลับไปที่ Scene Game คลิกที่เกมออบเจ็ค Plane ไปที่ Component Score จากนั้นที่ Txt Score Game Over ให้เพิ่มเกมออบเจ็ค TxtScore ที่อยู่ใน CanvasGameOver เข้าไป
รันและทดสอบจะเห็นว่า UI Game Over แสดงผลคะแนนเรียบร้อยแล้ว

บันทึก Best Score ด้วย PlayerPrefs

PlayerPrefs ใช้สำหรับบันทึกค่าต่างๆของเกม โดยจะสามารบันทึกได้ในรูปแบบของ float int และ string

ไปที่ C# Script ที่ชื่อว่า Score จากนั้นให้เพิ่ม

public Text _TxtBestScoreGameOver;

เพื่อใช้สำหรับอ้างอิง text ใน Canvas Game Over ที่จะใช้แสดงผลคะแนนสูงสุดที่เคยทำได้

จากนั้นให้เพิ่มฟังก์ชั่น OnCollisionEnter2D ขึ้นมาเพื่อใช้สำหรับเช็คค่าการชน คือเมื่อเครื่องบินมีการชนจะมีการเช็คว่าคะแนนปัจจุบันที่ทำได้มากกว่าคะแนนสูงสุดที่เคยบันทึกไว้หรือไม่ ถ้าคะแนนของรอบนี้สูงกว่าก็ให้ทำการบันทึกคะแนนสูงสุดไว้ด้วย PlayerPrefs จะได้ code ดังนี้

public void OnCollisionEnter2D(Collision2D collision)
  {
    //อ่านค่าจาก PlayerPref ที่มีคีย์คือ BestScore
    //ในกรณีที่ยังไม่มีการบันทึกโดยใช้คีย์นี้เกิดขึ้น จะกำหนดให้ค่า default ที่อ่านได้เป็น 0

    int bestScore = PlayerPrefs.GetInt("BestScore", 0);
    if (_Score > bestScore)
    {
      PlayerPrefs.SetInt("BestScore", _Score); //บันทึกค่าเป็น int และใช้คีย์ชื่อว่า BestScore
    }

   //แสดงผลคะแนนที่ดีที่สุด
    _TxtBestScoreGameOver.text = "Best Score : " + PlayerPrefs.GetInt("BestScore", 0);
  }

จากนั้นกลับไปที่ Scene Game เลือกที่เกมออบเจ็ค Plane ที่ Component Score ให้เพิ่ม TxtBestScore ใน CanvasGameOver เข้าไป ดังภาพ
รันและทดสอบเกมจะเห็นว่าเกมได้ทำการบันทึกและแสดงผล Best Score เรียบร้อยแล้ว