第五回 人物攻击动画
说说今天的总结。
首先呢,是一如既往的先组合帧动画。
拖上去,取名为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,将会在之后修复