1 基本准备

在前几篇里面,已经搞定了基本的角色控制,已经设置好了角色不同状态的动画效果。

但是会发现,在进行跳跃的时候也依旧是闲置状态下的动画,那么这一篇要解决的就是不同动作下的状态切换。

2 为不同动画状态切换设置参数

点击之前在Assets->Animation->Player里面创建的Player(Animator类型)的文件,就会看到下图中间这个Animatior面板。这里面会看到之前我们为Player设置的run、idle等动画状态。

unity 修改动画切片normalizedTime unity怎么切换动画_Time

每个状态可以通过右键点击Make Transition来创建一个箭头,连接其它的模块,这里也就是不同状态转移方向的设置。

unity 修改动画切片normalizedTime unity怎么切换动画_ide_02

unity 修改动画切片normalizedTime unity怎么切换动画_ide_03

然后结合之前写的代码,写了左右移动和跳的控制,那么我就连接好idle、jump和run的动画,来配合我们之前写的代码。

unity 修改动画切片normalizedTime unity怎么切换动画_ide_04

接下来,设置动画之间转移需要的控制参数,通过下图框选的地方就可以新建一个参数了。先点击Parameters-> + ->选择参数的类型。

unity 修改动画切片normalizedTime unity怎么切换动画_Time_05

新建了ground(bool)和speed(float)两种变量。ground用来判断角色是否在地上,speed用来记录角色左右移动速度。

然后点击之前创建的Transition,为每一个Transition添加参数控制。

点击Transition后,右边会出来一个面板,红色框框的地方:

Has Exit Time(是否有退出时间),这个不勾选的,勾选代表这个动画必须播完才能下一个动画,不勾选代表这个动画可以被打断;

Transition Duration(过渡的时间),设置为0,从A动画过渡到B动画需要的时间,如果设勾选了Fixed Duration,那么这个时间以秒为单位,否则的话以A的时间为基础(百分比时间);

Conditions,用来添加参数判断。

unity 修改动画切片normalizedTime unity怎么切换动画_ide_06

上图的参数ground要勾选,角色一开始是在地面上,ground初始值应该是true。

参数判断:

  • idle->run:speed速度大于0.001
  • run->idle:speed速度小于0.001
  • run->jump:ground等于false
  • jump->idle:ground等于true
  • idle->jump:ground等于false

3 代码控制参数实现动画状态切换

初始的代码思路:每次更新后,更新速度,通过y轴速度来判断是否处于跳跃状态。

遇到的问题:

  • 跳跃不能通过y轴速度不为零来判断,因为上下坡也会有y轴速度的变化。在按下跳跃键后就让jump动画转换,需要来判断是否碰到地面落地来结束jump动画,这也是为什么我要添加ground(前面动画状态切换的参数)。
  • 如果只判断是否碰到地面的时候需要二段跳的时候才会有动画转变,大概是因为按下跳跃按键后ground刚转换为false,又立马检测是否碰到地面,结果有修改为了true。

修改后的代码思路:每次更新后,更新速度,按下跳跃键后就转变动画,在下落状态的时候判断是否有没有触碰到地面。

介绍一下Layer:通常是逻辑用到的,用来判断碰撞,触发检测的掩盖用的。(需要用这个来判断是否碰到了地面)Layer只有32层,官方占了前8个(不可更改)。通常代码里面会用LayerMask来开启和关闭Layer,使用方式(LayerMask mask = 1 << 你需要开启的Layers层,LayerMask mask = 0 << 你需要关闭的Layers层)。

代码前期工作:为TileMap修改Layer,添加Ground的Layer,然后把TileMap的Layer修改为Ground。

unity 修改动画切片normalizedTime unity怎么切换动画_ide_07

unity 修改动画切片normalizedTime unity怎么切换动画_Time_08

代码:

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

public class PlayerController : MonoBehaviour {

    private float moveSpeed;//移动速度
    private float jumpForce;//跳跃力
    private Rigidbody2D rig;//刚体
    private Animator Anim;//角色的Animator
    private Collider2D coll;//角色的碰撞器
    public LayerMask ground;//用来开启layer
    private bool falling=false;//用来标记是否是下落状态

    //初始化
    void Start () {
        rig = GetComponent<Rigidbody2D>();//获取主角刚体组件
        Anim = GetComponent<Animator>();//获取主角动画组件
        coll = GetComponent<Collider2D>();//获取角色碰撞器
        ground = 1<<8;//开启Ground的layer层,Ground在layer8
        jumpForce = 575f;
        moveSpeed = 500f;
	}

    //固定的时间间隔执行,不受游戏帧率的影响
    void FixedUpdate()
    {
        Move();
        changeAnimator();
    }

    //控制移动
    void Move()
    {
        float moveMultiple = Input.GetAxis("Horizontal");
        float faceDirection = Input.GetAxisRaw("Horizontal");
        //角色左右移动
        if (moveMultiple!=0)
        {
            rig.velocity = new Vector2(moveMultiple * moveSpeed * Time.deltaTime, rig.velocity.y);//输入x,y向量,数值*方向
        }
        //角色朝向修改
        if(faceDirection!=0)
        {
            transform.localScale = new Vector2(faceDirection, 1);
        }
        //角色跳跃
        if (Input.GetButtonDown("Jump"))
        {
            rig.velocity = new Vector2(rig.velocity.x, jumpForce * Time.deltaTime);
            Anim.SetBool("ground", false);
        }
    }
    void changeAnimator()
    {
        Anim.SetFloat("speed", Mathf.Abs(rig.velocity.x));//速度是向量
        if (Anim.GetBool("ground")==false&&rig.velocity.y<0)
        {
            falling = true;
        }
        else if (coll.IsTouchingLayers(ground)&&falling)
        {
            Anim.SetBool("ground", true);
            falling = false;
        }
        /*if (coll.IsTouchingLayers(ground))
        {
            Anim.SetBool("ground", true);
            Debug.Log("你碰地了!");
        }
        //会有一个问题,只有第二次跳才会有动画,
        */
        /*if (Mathf.Abs(rig.velocity.y) > 0.001)
        {
            Anim.SetBool("ground",false);
        }
        else {
            Anim.SetBool("ground", true);
        }
        //会有问题,斜坡走的时候,y轴也会发生速度的变化
        */
    }
}

4 调整TileMap碰撞点

在进行爬坡测试的时候,出现了一个问题就是斜坡的瓦片碰撞点不能和瓦片重合,且凹凸不平,运行体验不佳。

不是正方形的瓦片的话,TileMap的碰撞点自动设置可能很奇怪,直接TileMap设置碰撞器的话,可能会有凹凸不平的情况,且凹凸不平的形状不能和瓦片完全重合。

出现这个问题可能需要回到一开始编辑图片,在Sprite Editor里面,左边的红框选择第三个Custom Physics Shape,然后点击需要修改碰撞点的方形块,然后点击Generate就可以修改碰撞点。

unity 修改动画切片normalizedTime unity怎么切换动画_Time_09