第五回 人物攻击动画

说说今天的总结。

首先呢,是一如既往的先组合帧动画。

第五回 人物攻击动画

拖上去,取名为attack_down并保存在animation里面。

之后把控制器和上方的东西删掉,只保留动画。

第五回 人物攻击动画

动画注意取消loop,因为攻击动画不会一直存在并循环播放。

新建AttackLayer的图层,并且复制walk的行为树。增加一个bool的parameters,取名为attack

第五回 人物攻击动画

新增一个空白格,取名为attacks。将初始设为行为树,然后行为树与attacks对接。

来时设attack为true,反之亦然

第五回 人物攻击动画

接下来就是敲代码的事情了。设置space键攻击,动画持续5秒。并且移动时停止攻击。

player的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class player : character {
   
    [SerializeField]
    private stat health;


    [SerializeField]
    private stat mana;
 
    [SerializeField]
    private float initHealth = 100;


    private float initMana = 50;
    protected override void Start()
    {
        health.Initialize(initHealth,initHealth);
        mana.Initialize(initMana, initMana);
        base.Start();
    }
    // Use this for initialization


        // Update is called once per frame
    protected override void Update()
    {
        GetInput();
        base.Update();
    }


    private void GetInput()
    {
        direction = Vector2.zero;
        //for debug
        if(Input.GetKeyDown(KeyCode.I))
        {
            health.MyCurrentValue -= 10;
            mana.MyCurrentValue -= 10;
        }
        if(Input.GetKeyDown(KeyCode.O))
        {
            health.MyCurrentValue += 10;
            mana.MyCurrentValue += 10;
        }
        //here


        if(Input.GetKey(KeyCode.W))
        {
            direction += Vector2.up;
        }
        if (Input.GetKey(KeyCode.A))
        {
            direction += Vector2.left;
        }
        if (Input.GetKey(KeyCode.S))
        {
            direction += Vector2.down;
        }
        if (Input.GetKey(KeyCode.D))
        {
            direction += Vector2.right;
        }
        if(Input.GetKeyDown(KeyCode.Space))
        {
            attackRoutine =  StartCoroutine(Attack());
        }
    }
    private IEnumerator Attack()
    {
        if (!isAttacking && !IsMoving)
        {
            isAttacking = true;
            myAnimator.SetBool("attack", isAttacking);


            yield return new WaitForSeconds(5);
            StopAttack();
            Debug.Log("Attack done");
            StopAttack();
        }
    }
}

character的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public abstract class character : MonoBehaviour {
    [SerializeField]
    private float speed;


    protected Animator myAnimator;
    // Use this for initialization
    protected Vector2 direction;


    private Rigidbody2D myRigidbody;
    protected bool isAttacking = false;


    protected Coroutine attackRoutine;


    public bool IsMoving
    {
        get
        {
            return direction.x != 0 || direction.y != 0;
        }
    }


   protected virtual void Start() {
        myRigidbody = GetComponent<Rigidbody2D>();
        myAnimator = GetComponent<Animator>();
}

// Update is called once per frame
protected virtual void Update () {
       HandleLayers();
    }


    private void FixedUpdate()
    {
        Move();
    }
    public void Move()
    {
        myRigidbody.velocity = direction.normalized * speed;
        //x=20,y=2//Normalize =1,1
    }
    public void HandleLayers()
    {
        if (IsMoving)
        {
       
            ActivateLayer("WalkLayer");
            myAnimator.SetLayerWeight(1, 1);
            myAnimator.SetFloat("x", direction.x);
            myAnimator.SetFloat("y", direction.y);


            StopAttack();
        }
        else if(isAttacking)
        {
            ActivateLayer("AttackLayer");
        }
        else
        {
            ActivateLayer("IdleLayer");
        }


    }




    public void ActivateLayer(string layerName)
    {
        for(int i = 0;i <myAnimator.layerCount;i++)
        {
            myAnimator.SetLayerWeight(i, 0);
        }
        myAnimator.SetLayerWeight(myAnimator.GetLayerIndex(layerName), 1);


    }
    public void StopAttack()
    {
        if (attackRoutine != null)
        {
            StopCoroutine(attackRoutine);
            isAttacking = false;
            myAnimator.SetBool("attack", isAttacking);
        }
    }
}

有些小细节,例如按攻击会稍微移动,还有一些其他Bug,将会在之后修复