
บทเรียนสำหรับควบคุมตัวละครของเราด้วย Unity 3D เขียนเกม 3 มิติให้ ตัวละครของเราเดินไปมาผ่านการ Input ด้วย Keyboard และ Mouse ไปจนถึงการโจมตีด้วย JavaScript
ก่อนจะศึกษาบทเรียนนี้ไปทบทวนบทเรียนเก่าๆ ก่อนที่
- เริ่มต้นเขียนเกม 3D ด้วย Unity
- เขียนเกม 3D ด้วย Unity การจัดการ Game Object ในเกม
- เขียนเกม 3D ด้วย Unity เรียกใช้งาน Physics กับ Rigidbody
- เขียนเกม 3D ด้วย Unity ศึกษา Basic Collision Detection
- เขียนเกม Unity3D การใช้ Asset Store และการสร้าง Terrain
- การควบคุมมุมกล้องของเกมด้วย Mouse Movement บน Unity3D
เราจะหยิบงานจากบทเรียนก่อนหน้านี้คือ การควบคุมมุมกล้องของเกมด้วย Mouse Movement บน Unity3D บทนี้มาปรับใช้เพิ่มเติมเล็กน้อยครับ เปิด Project เดิมขึ้นมา

เราจะ Control ตัวละครของเราให้เดินไปมาในฉากได้อิสระบน Terrain ที่สร้างขึ้นด้วยการกดปุ่ม Keyboard ครับ อย่างที่เคยบอกไว้ว่า คำสั่ง GetAxis คือ รับค่าการกดปุ่มลูกศร โดยการรับค่า Left & Right หรือ ซ้ายและขวา จะอ้างอิงผ่าน Input.GetAxis(“Horizontal”) และ บน ล่าง Up & Down คือ Input.GetAxis(“Vertical”) เราจะใช้แป้น Keyboard ของเรามาควบคุมคือปุ่มสำหรับควบคุมคือ W,A,S,D ครับ
เปิดไฟล์ Players.js ผ่าน Monodevelop ขึ้นมาครับ ใส่คำสั่งต่อไปนี้
ประกาศส่วน Header ก่อน
#pragma strict var rotationSpeed : float = 10; var walkspeed : float= 7; var gravity : float = 50; private var yRot : float; var body : Transform;
เราจะตั้งค่า walkspeed ความเร็วของการเดินหรือวิ่งไว้ที่ 7 เป็นตัวเลข Interval ครับ สร้างตัวแปร Body สำหรับ Transform การเคลื่อนไหวกรณีกระโดด และเขียนคำสั่งต่อไปนี้เพิ่มเข้าไปที่ update()
if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")){ animation.CrossFade("Run",0.2); animation["Run"].speed = walkspeed/10; Controller.Move((vertical *(walkspeed * Input.GetAxis("Vertical"))) * Time.deltaTime); Controller.Move((horizontal *(walkspeed * Input.GetAxis("Horizontal"))) * Time.deltaTime); }else{ animation.CrossFade("idle",0.2); }
เป็นคำสั่งที่เรารับค่าการเดินหน้า ถอยหลัง หรือซ้ายขวาผ่าน Keyboard แล้วตัวละครของเราจะเลือก Animation ที่ชื่อว่า Run มาทำงาน และเมื่อเอามือออกจากแป้น ตัวละครของเราก็จะกลับสู่สถานะ idle

หมายเหตุ: Asset Store ที่เราโหลดมาบางตัวไม่มี Animation มาให้ครับ ต้องไปสร้างเอง
สร้างฟังก์ชันมาใหม่ชื่อ LateUpdate ให้ตัวละครของเราหมุนหรือหันหน้าไปที่ ทิศที่เราจะมุ่งหน้าไปตามทิศของ Mouse
function LateUpdate(){ if(Input.GetAxis("Vertical") == 0){ if(Input.GetAxis("Horizontal") > 0){ body.localEulerAngles.y = 180; }else if(Input.GetAxis("Horizontal") < 0){ body.localEulerAngles.y = 0; } }else if(Input.GetAxis("Vertical") > 0){ if(Input.GetAxis("Horizontal") > 0){ body.localEulerAngles.y = 135; }else if(Input.GetAxis("Horizontal") < 0){ body.localEulerAngles.y = 45; } }else if(Input.GetAxis("Vertical") < 0){ if(Input.GetAxis("Horizontal") == 0){ body.localEulerAngles.y = -90; }else if(Input.GetAxis("Horizontal") > 0){ body.localEulerAngles.y = -135; }else if(Input.GetAxis("Horizontal") < 0){ body.localEulerAngles.y = -45; } } }
เพิ่มการกระโดดของตัวละครให้ไปที่ update() ครับใส่คำสั่งนี้ลงไป
if(Input.GetKeyDown("space")){ PlayerJump(); }
และไปสร้างฟังก์ชัน PlayerJump() มาใหม่ แล้วใส่คำสั่งตามนี้
function PlayerJump (){ gravity = 10; yield WaitForSeconds(0.5); gravity = -50; }
แก้ไข คำสั่งของเก่าส่วนของ gravity จากเดิมคือ
transform.rotation = Quaternion.Euler(0, yRot, 0); Controller.Move(height * -gravity * Time.deltaTime);
แก้ไขเป็น
transform.rotation = Quaternion.Euler(0, yRot, 0); //Controller.Move(height * -gravity * Time.deltaTime); Controller.Move(height * gravity * Time.deltaTime);
ลอง Run ตัวเกมของเราครับ แล้ววิ่งเล่นดู

ถ้าสังเกตแล้วจะเห็นว่า Main camera ไม่ได้วิ่งตามตัวละครของเราเลย เพราะว่าโหมดของมันเป็น Global ครับ ให้ใช้วิธีทำให้มันเป็น Local ให้เลื่อนเจ้า Main Camera ที่ Hierarchy จากส่วนนอกสุดไปไว้ใต้ ตัวละครของเราครับ

วีดีโอ ตอน Run นะครับ
การใส่ค่าโจมตี เราต้องตรวจจให้แน่ชัดว่า ตัวละครใน asset Store ที่เราโหลดมามี Animation ของการโจมตีอยู่หรือเปล่า ถ้ามีใส่คำสั่งนี้ครับ
// Detects clicks from the mouse and prints a message // depending on the click detected. function Update() { if(Input.GetMouseButtonDown(0)) Debug.Log("Pressed left click."); if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click."); if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click."); }
เป็นการรับค่าของ การคลิก Mouse นั่นเอง เราก็เอามาเขียนร่วมกับ Animation ดังนี้ครับ ให้คลิก Mouse ซ้ายแล้วจะโจมตีก็แล้วกัน เพิ่มใน update()
if(Input.GetMouseButtonDown(0)) animation.Play("Attack"); if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click."); if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click.");
ทำการ Run เกมของเราครับ แล้วคลิก Mouse ยิกๆ ไปเลย

วีดีโอของการ attack นะครับ
ภาพรวมของคำสั่งใน Players.js ก็จะเป็นดังนี้ ตรวจสอบกันดู
#pragma strict var rotationSpeed : float = 10; var walkspeed : float= 7; var gravity : float = 50; private var yRot : float; var body : Transform; function Update () { var Controller : CharacterController = GetComponent(CharacterController); var vertical : Vector3 = transform.TransformDirection(Vector3.forward); var horizontal : Vector3 = transform.TransformDirection(Vector3.right); var height : Vector3 = transform.TransformDirection(Vector3.up); if(Input.GetKeyDown("space")){ PlayerJump(); } if(Input.GetMouseButtonDown(0)) animation.Play("Attack"); if(Input.GetMouseButtonDown(1)) Debug.Log("Pressed right click."); if(Input.GetMouseButtonDown(2)) Debug.Log("Pressed middle click."); if(Input.GetAxis("Vertical") || Input.GetAxis("Horizontal")){ animation.CrossFade("Run",0.2); animation["Run"].speed = walkspeed/10; Controller.Move((vertical *(walkspeed * Input.GetAxis("Vertical"))) * Time.deltaTime); Controller.Move((horizontal *(walkspeed * Input.GetAxis("Horizontal"))) * Time.deltaTime); }else{ animation.CrossFade("idle",0.2); } if(Input.GetAxis("Mouse X")){ yRot += 10 * Input.GetAxis("Mouse X"); } transform.rotation = Quaternion.Euler(0, yRot, 0); //Controller.Move(height * -gravity * Time.deltaTime); Controller.Move(height * gravity * Time.deltaTime); } function LateUpdate(){ if(Input.GetAxis("Vertical") == 0){ if(Input.GetAxis("Horizontal") > 0){ body.localEulerAngles.y = 180; }else if(Input.GetAxis("Horizontal") < 0){ body.localEulerAngles.y = 0; } }else if(Input.GetAxis("Vertical") > 0){ if(Input.GetAxis("Horizontal") > 0){ body.localEulerAngles.y = 135; }else if(Input.GetAxis("Horizontal") < 0){ body.localEulerAngles.y = 45; } }else if(Input.GetAxis("Vertical") < 0){ if(Input.GetAxis("Horizontal") == 0){ body.localEulerAngles.y = -90; }else if(Input.GetAxis("Horizontal") > 0){ body.localEulerAngles.y = -135; }else if(Input.GetAxis("Horizontal") < 0){ body.localEulerAngles.y = -45; } } } function PlayerJump (){ gravity = 10; yield WaitForSeconds(0.5); gravity = -50; }
จบแล้วครับการ Movement ตัวละคร ของเราผ่าน Input
One Comment