11/25/2013

Project RPG BÀI 3. CHIẾN ĐẤU CẬN CHIẾN



Ở 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.


B4. Nhấp chọn Player trong thẻ Project và kéo thả Evil Cube cũng trong thẻ Project vào Target của PlayerAttack (Script) trong thẻ Inspector như sau:

 

B5.Vẫn trong PlayerAttack (Script) ở thẻ Inspector, điều chỉnh AttackTimer = 0 và Cool Down = 2.


B6. Nhấp phải vào thẻ Project và chọn Creat | C# Script và đặt tên là EnemyAttack.

 
B7. Double click vào file vừa tạo và chèn đoạn code sau vào:

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:

 

B11. Save và ấn nút Play để kiểm tra thành quả. Ấn nút F để có thể tấn công enemy.


7 comments:

  1. 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

    ReplyDelete
    Replies
    1. Khô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
      Bạ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

      Delete
  2. 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

    ReplyDelete
    Replies
    1. Bạ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é.
      Mình đã test lại và thấy ổn mà

      Delete
  3. Vector3 dir = (target.transform.position - transform.position).normalized;

    float direction = Vector3.Dot(dir, transform.forward);

    2 dòng này có nghĩa gì vậy anh?

    ReplyDelete
    Replies
    1. 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.
      Dòng 2 để huong enemy vào muc tiêu và tiến về phía trc

      Delete
  4. Project này như của ông " BurgZerg Arcade " .... chẳng khác gì.....

    ReplyDelete