【Unity】My First Game_05

2020-10-05 22:00:02

敵人移動

  1. 在」Frog「的」Inspector視窗「中新增」New script「,命名為」Enemy_Frog.cs「。

  2. 在」Frog「中」Create Empty「,分別命名為」left「和」right「,調整位置(如果看不見點,在」Scene視窗「中點選」Gizmos「即可顯示)。

  3. 開啟」Enemy_Frog.cs「,新增程式碼:

    private Rigidbody2D rb;
    public Transform leftPoint, rightPoint;
    
  4. 將」Frog「的」left「和」right「選進「Script視窗」的「leftPoint」和「rightPoint」中。、

  5. 新增程式碼:

    public float speed;
    private float leftx, rightx;//記錄leftPoint, rightPoint的位置
    private bool faceLeft = true;//預設瓜娃子面向左
    
  6. 新增Start方法:

    void Start()   
    {
        rb = GetComponent<Rigidbody2D>();//獲得剛體
      
        transform.DetachChildren();
      	//注意這句,當敵人轉向時,其孩子leftPoint, rightPoint也隨之轉向,導致Frog抽搐
      	//DetachChildren所有子物體解除父子關係
      	//當遊戲開始後,leftPoint, rightPoint不在是Frog的孩子,就不會隨之反轉
      
        leftx = leftPoint.position.x;//記錄leftPoint, rightPoint的位置
        rightx = rightPoint.position.x;
        Destroy(leftPoint.gameObject);//記錄完位置後就銷燬兩點
        Destroy(rightPoint.gameObject);
    }
    
  7. 新增Movement方法:

    void Update()
    {
        Movement();
    }
    
    void Movement()
    {
    		if (faceLeft)
    		{
    		    rb.velocity = new Vector2(-speed,rb.velocity.y);//向左移動為-speed
    		    if (transform.position.x < leftx)//Frog到達leftPoint
    		    {
    		        transform.localScale=new Vector3(-1,1,1);//令x==-1使其朝向右
    		        faceLeft = false;
    		    }
    		}
    		else
    		{
    		    rb.velocity = new Vector2(speed, rb.velocity.y);
    		    if (transform.position.x > rightx)
    		    {
    		        transform.localScale=new Vector3(1,1,1);
    		        faceLeft = true;
    		    }
    		}
    }
    
  8. 儲存,瓜娃子就動起來了,將「Frog」移動到「Prefabs資料夾」中,就可重複使用。

敵人動畫

  1. 點選Prefabs資料夾中的「Frog」,在Animation視窗中分別新增」idle「、」jump「、」fall「三個動畫,並設定好Samples

  2. Animator視窗「中分別連線「idle -> jump」、「jump -> fall」、「fall -> idle」,並設定好條件與相關引數

  3. idle動畫中結束點」Add event「,並在inspector視窗中在」function「中新增」Enemy_Frog.cs「中的Movement()方法,此舉實現當idle動畫結束後才進行jump動畫

  4. 開啟Enemy_Frog.cs,新增程式碼:

    private Animator anim;
    private Collider2D coll;
    public LayerMask ground;
    
    public float speed, jumpForce;
    
  5. 在Frog的inspector視窗中的Script選項的Ground選擇已經建立好的」Ground「

  6. 在Start方法中新增程式碼:

    anim = GetComponent<Animator>();
    coll = GetComponent<Collider2D>();
    
  7. 刪除Update方法中呼叫Movement方法語句,並呼叫SwitchAnim方法

  8. 修改Movement方法

    void Movement()
    {
        if (faceLeft)
        {
            if (coll.IsTouchingLayers(ground))//判斷是否觸碰到地面
            {
                if (transform.position.x < leftx)
                {
                    transform.localScale=new Vector3(-1,1,1);
                    faceLeft = false;
                }
                anim.SetBool("jumping",true);
                rb.velocity = new Vector2(-speed,jumpForce);
            }
        }
        else
        {
            if (coll.IsTouchingLayers(ground))
            {
                if (transform.position.x > rightx)
                {
                    transform.localScale=new Vector3(1,1,1);
                    faceLeft = true;
                }
                anim.SetBool("jumping",true);
                rb.velocity = new Vector2(speed, jumpForce);
            }
        }
    }
    
  9. 新增SwitchAnim方法:

    void SwitchAnim()
    {
        if (anim.GetBool("jumping"))
        {
            if (rb.velocity.y < 0.1)
            {
                anim.SetBool("jumping",false);
                anim.SetBool("falling",true);
            }
        }
    
        if (coll.IsTouchingLayers(ground) && anim.GetBool("falling"))
        {
            anim.SetBool("falling",false);
        }
    }
    
  10. 以下是死亡動畫的步驟:先正常在Frog的Animation中新增「die」動畫,並「Any State -> die」,在Parameters中新增一個「Trigger」為「death」,並將條件設定為「death」,調整相關引數

  11. 在」Enemy_Frog.cs「中新增程式碼:

    void Death()
    {
        Destroy(gameObject);//在die動畫後新增event呼叫Death()
    }
    
    public void JumpOn()
    {		
      	//在PlayerController中呼叫該方法
        anim.SetTrigger("death");//開啟die的條件
    }
    
  12. 修改」Player Controler.cs「的「OnCollisionEnter2D(Collision2D collision)」方法中的程式碼:

    if (collision.gameObject.tag == "Enemy")
    {
        Enemy_Frog frog = collision.gameObject.GetComponent<Enemy_Frog>();
        //建立Enemy_Frog類的範例
        
        if(anim.GetBool("falling"))
        {
         		frog.JumpOn();呼叫frog的死亡動畫
         		rb.velocity = new Vector2(rb.velocity.x, jumpForce * Time.deltaTime);
            anim.SetBool("jumping", true);
        }
        else if (transform.position.x < collision.gameObject.transform.position.x)
        {
            rb.velocity = new Vector2(-10,rb.velocity.y);
            isHurt = true;
        }
        else if (transform.position.x > collision.gameObject.transform.position.x)
        {
            rb.velocity=new Vector2(10,rb.velocity.y);
            isHurt = true;
        }
    }
    
  13. 以下是有關父子級的知識點,建立一個新類「Enemy」,修改」Enemy_Frog.cs「中程式碼:

    public class Enemy_Frog : Enemy//繼承自Enemy類,而不是MonoBehavior
    {
    		……
    }
    
  14. 在「Enemy」中新增程式碼:

    protected Animator anim;
    
    // Start is called before the first frame update
    protected virtual void Start()//注意使用protected virtual,使子級能夠重寫該方法
    {
        anim = GetComponent<Animator>();
    }
    
    public void Death()//注意使用public
    {
        Destroy(gameObject);//在die動畫後新增event呼叫Death()
    }
    
    public void JumpOn()//注意使用public
    {
        anim.SetTrigger("death");
    }
    

    在「Enemy_Frog」中修改程式碼:

    protected override void Start()//注意使用protected override   
    {
        base.Start();//獲得父級的Start()
        rb = GetComponent<Rigidbody2D>();
        coll = GetComponent<Collider2D>();
    
        transform.DetachChildren();
        leftx = leftPoint.position.x;
        rightx = rightPoint.position.x;
        Destroy(leftPoint.gameObject);
        Destroy(rightPoint.gameObject);
    }
    
  15. 修改」Player Controler.cs「的「OnCollisionEnter2D(Collision2D collision)」方法中的程式碼:

    /*Enemy_Frog frog = collision.gameObject.GetComponent<Enemy_Frog>();//呼叫frog的死亡動畫*/
    Enemy enemy = collision.gameObject.GetComponent<Enemy>();
    ……
    /*frog.JumpOn();*/
    enemy.JumpOn();