Ở 2 bài viết trước mình đã thực hiện xong các tính năng thanh máu (Hp) và chức năng đuổi theo người chơi của Enemy (Enemy AI). Bài viết này mình sẽ tạo tính năng chiến đấu cận chiến cho người chơi và enemy. Người chơi có thể tấn công enemy và khiến Hp của enemy giảm dần nếu khoảng cách tấn công đủ gần hay đúng góc độ để khiến enemy bị trúng đòn. Thời gian ra đòn người chơi / enemy có thể nhanh hoặc chậm tùy thuộc vào thời gian cooldown (hồi chiêu) của bản thân. Khi thời gian cooldown chưa kết thúc thì không được tấn công. Tương tự với khoảng cách tấn công cũng vậy, người chơi phải đứng ở vị trí đủ gần để có thể đánh trúng enemy. Bài viết này mình sẽ tạo những chức năng như đã nêu ở trên.
B1. Nhấp phải vào thư mục Script trong thẻ Project và chọn Creat | C# Script và đặt tên file vừa tạo là PlayerAttack.
B2. Double click vào file PlayerAttack và nhập đoạn code sau vào:
using UnityEngine;
using System.Collections;
public class PlayerAttack : MonoBehaviour
{
public GameObject target;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start(){
attackTimer = 0;
coolDown = 2.0f;
}
// Update is called once per frame
void Update(){
if (attackTimer > 0)
attackTimer -= Time.deltaTime;
if (attackTimer < 0)
attackTimer = 0;
if (Input.GetKeyUp (KeyCode.F)) {
if (attackTimer == 0){
Attack();
attackTimer = coolDown;
}
}
}
private void Attack(){
float distance = Vector3.Distance(target.transform.position, transform.position);
Vector3 dir = (target.transform.position - transform.position).normalized;
float direction = Vector3.Dot(dir, transform.forward);
Debug.Log(direction);
if (distance < 2.5f) {
if(direction > 0){
EnemyHealth eh = (EnemyHealth)target.GetComponent("EnemyHealth");
eh.AddjustCurrentHealth(-10);
}
}
}
}
B3. Tại thẻ Project, kéo thả file PlayerAttack vào Player trong thẻ Hierarchy.
B5.Vẫn trong PlayerAttack (Script) ở thẻ Inspector, điều chỉnh AttackTimer = 0 và Cool Down = 2.
using UnityEngine;
using System.Collections;
public class EnemyAttack : MonoBehaviour
{
public GameObject target;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start(){
attackTimer = 0;
coolDown = 2.0f;
}
// Update is called once per frame
void Update(){
if (attackTimer > 0)
attackTimer -= Time.deltaTime;
if (attackTimer < 0)
attackTimer = 0;
if (attackTimer == 0){
Attack();
attackTimer = coolDown;
}
}
private void Attack(){
float distance = Vector3.Distance(target.transform.position, transform.position);
Vector3 dir = (target.transform.position - transform.position).normalized;
float direction = Vector3.Dot(dir, transform.forward);
Debug.Log (direction);
if (distance < 2.5f) {
if(direction > 0){
PlayerHealth eh = (PlayerHealth)target.GetComponent("PlayerHealth");
eh.AddjustCurrentHealth(-10);
}
}
}
}
B8. Kéo thả file C# EnemyAttack vào Evil Cube ở thẻ Hierarchy. Nhấp chọn Evil Cube trong thẻ Hierarchy, kéo thả Player trong thẻ Hierarchy vào Target của EnemyAttack (Script) như hình sau:
B9. Tại thẻ Project, Double click vào file EnemyAI, xóa những dòng code cũ đi và chèn lại code sau vào:
using UnityEngine;
using System.Collections;
public class EnemyAI : MonoBehaviour{
public Transform target;
public int moveSpeed;
public int rotationSpeed;
public int maxDistance;
private Transform myTransform;
void Awake(){
myTransform = transform;
}
// Use this for initialization
void Start(){
maxDistance = 2;
GameObject go = GameObject.FindGameObjectWithTag("Player");
target = go.transform;
}
// Update is called once per frame
void Update(){
Debug.DrawLine (target.position, myTransform.position, Color.yellow);
//Look at the target
myTransform.rotation = Quaternion.Slerp (myTransform.rotation, Quaternion.LookRotation (target.position - myTransform.position), rotationSpeed * Time.deltaTime);
if(Vector3.Distance(target.position, myTransform.position) > maxDistance){
// Move towards target
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
}
B10. Nhấp chuột chọn Evil Cube ở thẻ Project, qua thẻ Inspector, thay đổi giá trị Max Distance = 3, Attack Timer = 0 và Cool Down = 1.5 như hình sau:
hi anh , ở đây em thấy 1 điểm là cả player vẫn có thể di chuyển bình thường sau khi hết máu
ReplyDeleteKhông thể làm hết mọi thứ trong 1 bài viết chỉ có vài bước vậy đâu bạn à :D
DeleteBạn theo dõi từ từ các bài viết sau sẽ có thêm nhiều chức năng hơn :D
EnemyHealth eh + PlayerHealth eh <--- không khai báo ? lỗi , đâu ra vậy bạn ? , bạn cho bản demo cho từng bài đi , như vậy mọi ng dễ theo dõi :D , thanks bạn
ReplyDeleteBạn đã thực hiện B1 và B2 chưa? Nếu chưa thì bạn phải bắt đâu làm từ đầu nhé.
DeleteMình đã test lại và thấy ổn mà
Vector3 dir = (target.transform.position - transform.position).normalized;
ReplyDeletefloat direction = Vector3.Dot(dir, transform.forward);
2 dòng này có nghĩa gì vậy anh?
Dòng đầu để giữ khoảng cách enemy k tiến quá xác mục tiêu mà đứng ở vị trí xa mục tiêu một đoạn.
DeleteDòng 2 để huong enemy vào muc tiêu và tiến về phía trc
Project này như của ông " BurgZerg Arcade " .... chẳng khác gì.....
ReplyDelete