天天看點

【Unity exam02】怎樣制作一個回旋斧 2D篇

怎樣制作一個回旋斧 2D篇

【Unity exam02】怎樣制作一個回旋斧 2D篇

【參考視訊】

url:bilibili - 【中文字幕】在2D中重制:戰神4奎爺投擲和召回寒冰之斧的攻擊方式

這個視訊中不僅實作了回旋斧的制作,還實作了相機震動、以及一些特效效果豐富體驗。有興趣的小夥伴可以觀看這個視訊,這裡我隻實作普通的回旋斧制作。

【PS:我實作的方式與這位UP有些不同,若是有錯誤請指正】

一、打開初始資源

下載下傳位址 https://pan.baidu.com/s/1L5APoVJundN1IUDphSNUBg

提取碼:v4m2

  1. 打開Scenes檔案夾下的第一個場景,這個場景已經實作了部分功能(玩家移動,敵人攻擊,按空格敵人血量會減少)。
【Unity exam02】怎樣制作一個回旋斧 2D篇
  1. 打開Sprites檔案夾,找到weapon斧頭,将其拖拽到Player的子物體中,并調整Position和Sorting Layer以顯示在正确的位置
    【Unity exam02】怎樣制作一個回旋斧 2D篇

    二、在Scripts/01檔案夾下建立C#腳本 Weapon

    (1)首先來實作物體的旋轉,在點選斧頭物體按E進行旋轉可知斧頭是圍繞Z軸進行旋轉的。簡單的旋轉隻需以下代碼即可:

public class Weapon: MonoBehaviour
{
	[Header("旋轉參數")]
    [SerializeField]
    float rotateSpeed = 1000f;  // 旋轉速度

    private void Update()
    {
        SelfRotate();
    }

    void SelfRotate()
    {
        // 斧頭圍繞Z軸順時針旋轉
        transform.Rotate(-Vector3.forward * rotateSpeed * Time.deltaTime);
    }
}
           
【Unity exam02】怎樣制作一個回旋斧 2D篇

(2)接下來實作滑鼠點選某個位置,斧頭會旋轉并移動到該位置。

建立兩個變量 移動速度moveSpeed , 目标位置 targetPos

[Header("移動參數")]
    [SerializeField]
    float moveSpeed = 10f;  // 移動速度
    Vector2 targetPos;  // 滑鼠點選位置
    
    private void Update()
    {
        SelfRotate();
        Movement(); 

        // 點選滑鼠左鍵
        if (Input.GetMouseButtonDown(0))
        {
            targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }
    }
    
    void Movement()
    {
        // 斧頭以一定速度移動到目标位置
        transform.position = Vector2.MoveTowards(transform.position, targetPos, moveSpeed * Time.fixedDeltaTime);
    }
           
【Unity exam02】怎樣制作一個回旋斧 2D篇

(3)接下來實作武器到達目标點位置後,傳回人物手中。

首先聲明幾個變量, 玩家位置 playerPos, 三個bool值 isRotating 旋轉狀态, isGo 前進狀态, isBack 傳回狀态。

邏輯:

·點選滑鼠時,武器開始旋轉,斧頭移動到滑鼠點選位置(即 isGo = true)。·

·斧頭到達目标位置後,開始傳回到玩家位置playerPos(即 isGo = false,isBack = true)

Vector2 playerPos;  // 玩家位置

    [Header("bool參數")]
    [SerializeField]
    bool isRotating;  // 旋轉狀态

    [SerializeField]
    bool isGo;        // 前進狀态

    [SerializeField]
    bool isBack;      // 傳回狀态

	private void Update()
    {
        playerPos = transform.parent.position;

        // 點選滑鼠左鍵 && 斧頭是靜止狀态
        if (Input.GetMouseButtonDown(0) && !isGo && !isBack)
        {
            isRotating = true;  // 開始旋轉
            isGo = true;    // 開始前進
            targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }

        if (isRotating)
        {
            SelfRotate();
            Movement();
        }
    }
void Movement()
    {
        // 如果武器到達了目标點
        if (Vector2.Distance(transform.position, targetPos) < 0.01f)
        {
            isBack = true;
            isGo = false;
        }

		// 如果武器傳回玩家手中
        if(Vector2.Distance(transform.position, playerPos) < 0.01f)
        {
            isBack = false;
        }

        // 武器處于前進狀态 且 不是傳回狀态
        if (isGo && !isBack)
        {
            // 斧頭以一定速度移動到目标位置
            transform.position = Vector2.MoveTowards(transform.position, targetPos, moveSpeed * Time.fixedDeltaTime);
        }

        // 武器處于傳回狀态 且 不是前進狀态
        if (isBack && !isGo)
        {
            // 斧頭以一定速度移動到目标位置
            transform.position = Vector2.MoveTowards(transform.position, playerPos, moveSpeed * Time.fixedDeltaTime);
        }
    }


           
【Unity exam02】怎樣制作一個回旋斧 2D篇

(4)這時候斧頭傳回玩家手中時并不會停止旋轉,但是,如果用Vector2.Distance()的方法判斷斧頭是否回到玩家的位置,然後指派isRotating = false。就會出現錯誤了!因為武器一直在玩家的位置,是以isRotating會一直會false,根本不會旋轉和移動了。

// 錯誤的方法
		if (Vector2.Distance(transform.position, playerPos) < 0.01f)
        {
            isRotating = false;
            isBack = false;
        }
           

是以我們要添加另外的條件,因為斧頭傳回狀态中isBack是為true的,是以我們可以判斷 isBack為true 且 斧頭回到玩家位置時, 斧頭停止旋轉,傳回狀态為假,這樣這個方法就隻在 武器回到玩家手中 的時候調用了一次,而不是無限調用

// 正确的方法
		if (isBack && Vector2.Distance(transform.position, playerPos) < 0.01f)
        {
            isRotating = false;
            isBack = false;

            // 傳回初始的旋轉角度
            transform.rotation = Quaternion.Euler(0, 0, 0);
        }
           
【Unity exam02】怎樣制作一個回旋斧 2D篇

(5)兩個缺陷:

1.我們注意到,武器回到的位置是玩家中心的位置,而不是回到玩家手上

2.因為武器是玩家的子物體,是以武器會跟随玩家的移動而移動(也就是說玩家的速度會影響到武器的速度),武器和玩家同時運動就會會顯得别扭,如果玩家移動速度過快,武器甚至會反向運動。 .

【Unity exam02】怎樣制作一個回旋斧 2D篇

有一種方法可以同時解決這兩個缺陷,就是将武器的位置替代為一個空物體,然後将武器移出Player作為一個單獨的物體,然後改變腳本中的一些參數即可

1.在Player下建立一個空物體weapon_point,并将斧頭移動到Player外作為獨立的物體

【Unity exam02】怎樣制作一個回旋斧 2D篇

2.進入腳本修改一些代碼

删掉變量 playerPos,聲明一個公共變量Transform point,删掉Update()中對 playerPos 的指派,然後将所有的playerPos改為point.position即可

不要忘記在unity中對point進行指派

【Unity exam02】怎樣制作一個回旋斧 2D篇

3.這樣武器确實不會跟随玩家進行移動了,但是産生了新bug,武器在玩家手中的時候也不會跟随玩家移動了。是以我定義了一個bool值,onHand,預設為true,用來判斷武器是否回到玩家手中。

在Update()方法中,當點選滑鼠左鍵時,物體會進行移動,是以此時onHand應為false

在Update()方法中,當onHand = true時,讓武器的位置一直為點的位置

在Movement()方法中,當武器回到手中時,onHand應為true

[SerializeField]
    bool onHand = true;      // 在手中

	// 在Update中添加
	private void Update()
    {
    	// 點選滑鼠左鍵 && 斧頭是靜止狀态
        if (Input.GetMouseButtonDown(0) && !isGo && !isBack)
        {
            onHand = false;
        }
        
        if (onHand)
            transform.position = point.position;
    }
	void Movement()
    {
        // 如果武器傳回玩家手中
        if (isBack && Vector2.Distance(transform.position, point.position) < 0.01f)
        {
            onHand = true;
        }
    }
           

【PS:這種方法隻是相對減少了一些違和感,并不能完全阻止,比如當玩家的移動速度快于斧頭的移動速度,如果斧頭傳回圖中玩家也一起移動的話,斧頭就會“追”不上玩家,是以還需合理的限制玩家和斧頭的速度】

(6)實作攻擊

隻需給敵人添加collider 2D元件,給斧頭添加collider 2D(勾選is trigger),rigidbody 2D(關掉重力)元件,然後用OntriggerEnter2D方法即可

1.在Weapon腳本中新增方法

注意:任何判斷碰撞的方法都需要雙方物體都有collider元件,且其中一個物體帶有rigidbody元件

private void OnTriggerEnter2D(Collider2D collision)
    {
    	// 調用Enemy的腳本中的Hurt方法,參數為25
        if (collision.CompareTag("Enemy"))
            collision.gameObject.SendMessage("Hurt", 25);
    }
           

别忘記給Enemy添加tag Enemy,如果沒有請點選Add Tag新增

【Unity exam02】怎樣制作一個回旋斧 2D篇

2.打開Enemy腳本,根據寫好的參數直接定義Hurt方法

【Unity exam02】怎樣制作一個回旋斧 2D篇
public void Hurt(int damage)
    {
        GetComponentInChildren<HealthBar>().hp -= damage;
    }
           

實作效果

【Unity exam02】怎樣制作一個回旋斧 2D篇

·完整項目百度雲

https://pan.baidu.com/s/1Kkrx8v5MRfHWNPz0RVKFtQ

提取碼:zfet

Unity版本:2019.4.3及以上

日期:2020-10-24