DeveloperFeaturedGame DevelopmentUnity 3D

เขียนเกมด้วย Unity3D ระบบ AI Enemy ของศัตรูวิ่งตามเรา

บทเรียนการพัฒนาเกม 3D ด้วย Unity3D กับตัวอย่างการเขียนระบบ AI ของศัตรูหรือ Enemy ให้วิ่งตามตัวละครเพื่อดำเนินการทำ Collision Detect ต่อยอดไป พร้อมตัวอย่าง

ก่อนที่เราจะศึกษาบทเรียนนี้แนะนำให้ไปศึกษาบทเรียนก่อนหน้าสำหรับ Unity 3D ก่อนที่นี่

https://www.daydev.com/category/developer/s11-game-development/%E0%B9%8Aunity-3d

รวมบทเรียนก่อนหน้านี้

ตัวอย่างนี้เราจะสร้าง Project ใหม่และเป็นการทบทวน การควบคุมตัวละครไปด้วยดังนั้นเราจะอ้างอิงบทเรียนเรื่อง Movement character มาใช้ในตัวอย่างนี้

โดยตัวอย่างนี้ผมจะดาวน์โหลด Asset Store น่ารักๆ มาใช้คือเจ้านี่ครับ (ภาพด้านล่าง)ระหว่างที่เรากำลังวางแผนนั้นให้ไปออกแบบ Terrain และ Skybox ให้สวยงามก่อนก็ยังได้

โหลดมาทำดู
โหลดมาทำดู

นำตัวละครของเราวางลงไปยัง Scene View สร้าง Character Control ให้เรียบร้อย และทำ Character Controller ให้เสร็จครับตามบทเรียนที่แล้ว

วาง model ตั้ง แสงดีๆ
วาง model ตั้ง แสงดีๆ
ตั้งค่า animation ให้เรียบร้อย
ตั้งค่า animation ให้เรียบร้อย
อ่าพร้อม
อ่าพร้อม

คำสั่งของ 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");
			Debug.Log("Pressed Left click.");
		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("Walk",0.2);
		animation["Walk"].speed = walkspeed/10;
		Controller.Move((vertical *(walkspeed * Input.GetAxis("Vertical"))) * Time.deltaTime);
		Controller.Move((horizontal *(walkspeed * Input.GetAxis("Horizontal"))) * Time.deltaTime);
	}else{
		animation.CrossFade("Wait",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;
}

ต่อมานำ Models ของเจ้า Slime ไปวางบน SceneView ครับ

เอา Slime ไปวางไว้
เอา Slime ไปวางไว้

กำหนด Animation มันให้เรียบร้อย

ตั้งค่า animation
ตั้งค่า animation

ใส่ Character Controller ลงไปในตัว Slime เช่นกันครับ

กำหนด Character Controller ลงไป
กำหนด Character Controller ลงไป
ตั้งค่าลงไปสำหรับ Character Controller
ตั้งค่าลงไปสำหรับ Character Controller

การทำงานของ Enemy AI คือให้ระบบประมวลผลว่าถ้า ตัวละครของเราเข้าใกล้ ระยะที่มันเห็น มันจะวิ่งไล่ตัวละครของเราแบบเอาเป็นเอาตายครับ แต่ถ้าตัวละครวิ่งหนีเกินระยะการมองเห็นของมันมันก็จะหยุดนิ่งเข้าสู่ภาวะ Idle อยู่กับที่ ซึ่งการเขียน Javascript นั้นต้องเขียนไฟล์ EnemyAi.js ใหม่ขึ้นมาตามนี้ครับ

สร้าง JS ขึ้นมาใหม่ใน character controller ของ Slime
สร้าง JS ขึ้นมาใหม่ใน character controller ของ Slime
#pragma strict
var Distance : float;
var Target : Transform;
var lookAtDistance = 25.0;
var attackRange = 15.0;
var moveSpeed = 2.0;
var Damping = 6.0;

function Update () {
	Distance = Vector3.Distance(Target.position, transform.position);
	if(Distance < lookAtDistance){
		lookAt();
	}
	if(Distance > lookAtDistance){
		//Idle
	}
	if(Distance < attackRange){
		attack();
	}
}

function lookAt()
{
	var rotation = Quaternion.LookRotation(Target.position - transform.position);
	transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Damping);
}

function attack()
{
	transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
	animation.Play("Attack");
}

อธิบายแบบง่ายๆ เพราะไล่ code ก็ไม่น่ายาก นั่นก็คือ สร้าง Distance ขึ้นมาเป็นระยะแบบเปิดlookAtDistance เป็นค่าที่ตัว Enemy จะเห็นเราตั้งไว้ที่ 25.0 ระยะให้เทียบกับ Scene View ทีหลัง เงื่อนไขคือถ้า Distance ที่เรา Follow อยู่วิ่งเข้ามาแล้วค่าน้อยกว่า attackRange ที่สร้างไว้คือ 15.0 จะเข้าเงื่อนไข if(Distance < attackRange) วิ่งไปที่ฟังก์ชัน Attack(); เพื่อไล่งับตัวละครของเราทันทีครับ ในฟังก์ชัน lookAt(); นั้นเป็นการบังคับให้ตัวศัตรูคอยคำนวณระยะของมันนิ่งๆ รอตัวละครเราไปเข้าใกล้

ก่อนจะทดสอบ Run เกมต้องใส่ค่าบางอย่างที่ ตัว Character Controller ของ Enemy ก่อนครับนั่นคือ Target ให้เราลากตัว Player ของเราจาก Hierarchy ไปใส่ได้เลย

ลาก Player เราไปใส่ใน Target
ลาก Player เราไปใส่ใน Target
เรียบร้อย
เรียบร้อย

เป็นการกำหนดให้ศัตรูไล่งับอะไรบางอย่างถ้าในเกมเราคือตัวละคร แต่ถ้าเรามี Slime สีแดงอีกตัว แล้วใส่ Target เป็น Slime สีแดง เจ้า ศัตรูเราจะไปไล่ Slime สีแดงแทนครับ

ทดสอบ Run เกมดู

โดนไล่งับ
โดนไล่งับ

วีดีโอ Preview ดูการทำงานของมัน

คงไม่ยากใช่ไหมครับกับบทเรียนนี้

Asst. Prof. Banyapon Poolsawas

อาจารย์ประจำสาขาวิชาการออกแบบเชิงโต้ตอบ และการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ผู้ก่อตั้ง บริษัท Daydev Co., Ltd, (เดย์เดฟ จำกัด)

Related Articles

Back to top button

Adblock Detected

เราตรวจพบว่าคุณใช้ Adblock บนบราวเซอร์ของคุณ,กรุณาปิดระบบ Adblock ก่อนเข้าอ่าน Content ของเรานะครับ, ถือว่าช่วยเหลือกัน