目录

1、新建项目

2、导入资源

复习一下前两篇笔记:

3、搭建场景

4、控制角色移动 

 5、制作角色动画

发现问题:

解决问题:


1、新建项目

unity2d怎么控制动画的播放 unity2d动画 位置改变_ci

2、导入资源

Sunny Land | 2D Characters | Unity Asset Store

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_02

复习一下前两篇笔记:

3、搭建场景


unity2d怎么控制动画的播放 unity2d动画 位置改变_System_03

4、控制角色移动 


unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_04

 5、制作角色动画

打开animation组件

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_05

新建动画文件

unity2d怎么控制动画的播放 unity2d动画 位置改变_ci_06

 选择idle连帧图片批量拖拽进动画编译器中

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_07

调节适当的频率

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_08

 接下来,点击动画组件创建更多动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_09

如下:

unity2d怎么控制动画的播放 unity2d动画 位置改变_游戏引擎_10

打开动画控制器

unity2d怎么控制动画的播放 unity2d动画 位置改变_ci_11

 如下,可以看到我们所创建的所有动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_12

 目前可以看到动画控制器中,进入动画默认指向Player_idle,打开进入游戏,发现无论如何移动角色,都只执行,play_idle动画,因此,我们需要动画控制器设置不同动画之间的转换。

右键选择make Transition添加转换箭头 

unity2d怎么控制动画的播放 unity2d动画 位置改变_ci_13

点击箭头可以查看转换条件

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_14

 点击左侧栏Parameter添加可控制动画转换的变量:

这里添加float类型的speed变量,通过速度来控制idle和run动画之间的转换。

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_15

 点击箭头右侧栏设置转换条件:速度大于0.01时为run状态 

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_16

 取消动画的过渡时间,实现迅速转换

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_17

反过来设置run到idle的转换和条件

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_18

 执行游戏,当参数变化时,动画也会变化

unity2d怎么控制动画的播放 unity2d动画 位置改变_游戏引擎_19

接下来,我们通过脚本,用代码实现如何控制动画的speed变量。

我们知道实现角色移动的两个脚本中

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_20

第一个是实现角色移动的基础,也就是常用的套路代码。有这个脚本才能实现角色移动。

第二个是我们自己写的角色移动逻辑,通过这个脚本调用基础脚本中的方法,实现角色移动。

接下来,我们要修改第二个脚本中的代码实现动画转换的逻辑。

添加动画控制器组件:

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_21

将动画器组件拖入栏中

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_22

将玩家当前速度传给动画器中的速度,从而进行动画转换的判断 

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_23

 为了保证动画任何位置都能工作,我们要给移动速度加上绝对值

animator.SetFloat("Speed", Mathf.Abs(move));

设置跳跃动画

无论是跑还是站立,角色都可以转换成跳跃动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_游戏引擎_24

也就是任何状态都可以跳跃, 那么unity的Animator提供了一个很好的状态,就是any state

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_25

再设置转换条件

设置布尔类型的jumping参数,当jumping为真时,开始播放跳跃动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_26

 但是这样还不行,因为播放完跳跃后无法回到其他状态,所以还要增加两个转换

jump->idle

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity2d怎么控制动画的播放_27

 jump->run

unity2d怎么控制动画的播放 unity2d动画 位置改变_游戏引擎_28

然后修改代码:

普通写法:

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

public class PlayerMovement : MonoBehaviour
{
    public CharacterController2D cc;//角色控制器组件

    public Animator animator;//动画控制器组件

    public float speed = 5f;//速度

    float move;//水平移动方向

    bool jump;//是否跳跃

    // Update is called once per frame
    void Update()
    {
        move = Input.GetAxis("Horizontal")*speed;//获取角色水平移动速度
        animator.SetFloat("Speed", Mathf.Abs(move));//将玩家当前速度传给动画器的speed参数
        jump = Input.GetButton("Jump");
        animator.SetBool("Jumping", jump);
    }

    void FixedUpdate()
    {
        cc.Move(move, jump);
    }
}

 高级写法:

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

public class PlayerMovement : MonoBehaviour
{
    public CharacterController2D cc;//角色控制器组件

    public Animator animator;//动画控制器组件

    public float speed = 5f;//速度

    float move;//水平移动方向

    bool jump;//是否跳跃

    // Update is called once per frame
    void Update()
    {
        move = Input.GetAxis("Horizontal")*speed;//获取角色水平移动速度
        animator.SetFloat("Speed", Mathf.Abs(move));//将玩家当前速度传给动画器的speed参数
        if (Input.GetButtonDown("Jump"))//判断什么时候播放跳跃动画
        {
            jump = true;
            animator.SetBool("Jumping", true);
        }
    }
    //结合CharacterController2D脚本,检测是否在地面
    public void OnLanding()
    {
        jump = false;
        animator.SetBool("Jumping", false);//判断何时停止跳跃
    }

    void FixedUpdate()
    {
        cc.Move(move, jump);
    }
}

结合CharacterController2D组件写一个Onlanding函数判断停止跳跃动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_29

发现问题:

动画只能播放一半

解决问题:

取消下面勾选,播放完整跳跃动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_30

同理添加Crouch动画

unity2d怎么控制动画的播放 unity2d动画 位置改变_unity_31

注意:

在crouch动画转回run或者idle时,不能取消时间的勾选,因为crouch时间太短了,需要勾选并自己手动增加动画时间。

unity2d怎么控制动画的播放 unity2d动画 位置改变_游戏引擎_32

 

unity2d怎么控制动画的播放 unity2d动画 位置改变_System_33

角色爬行代码:

if (Input.GetKey(KeyCode.S))//判断什么时候播放爬行动画
        {
            crouch = true;
        }else
        {
            crouch = false;
        }
        animator.SetBool("Crouching", crouch);

最后放上完整的代码:

CharacterController2D :

using UnityEngine;
using UnityEngine.Events;

public class CharacterController2D : MonoBehaviour
{
    public float jumpForce = 400f;                          // 弹跳力
    public bool canAirControl = false;                      // 在空中时,是否能控制
    public LayerMask groundMask;                            // 定义哪一个Layer是地面
    public Transform m_GroundCheck;                         // 用于判定地面的空物体

    const float k_GroundedRadius = .1f; // 用于检测地面的小圆形的半径
    private bool m_Grounded;            // 当前是否在地面上
    private bool m_FacingRight = true;  // 玩家是否面朝右边
    private Vector3 m_Velocity = Vector3.zero;

    const float m_NextGroundCheckLag = 0.1f;    // 起跳后的一小段时间,不能再次起跳。防止连跳的一种解决方案
    float m_NextGroundCheckTime;            // 过了这个时间才可能落地、才能再次起跳

    // 这个角色控制器,是依靠刚体驱动的
    private Rigidbody2D m_Rigidbody2D;

    [Header("Events")]
    [Space]

    public UnityEvent OnLandEvent;
    public UnityEvent OnAirEvent;

    [System.Serializable]
    public class BoolEvent : UnityEvent<bool> { }

    private void Awake()
    {
        m_Rigidbody2D = GetComponent<Rigidbody2D>();

        if (OnLandEvent == null)
            OnLandEvent = new UnityEvent();
        if (OnAirEvent == null)
            OnAirEvent = new UnityEvent();
    }

    private void FixedUpdate()
    {
        bool wasGrounded = m_Grounded;
        m_Grounded = false;

        // 检测与地面的碰撞
        if (Time.time > m_NextGroundCheckTime)
        {
            Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, groundMask);
            for (int i = 0; i < colliders.Length; i++)
            {
                if (colliders[i].gameObject != gameObject)
                {
                    m_Grounded = true;
                    if (!wasGrounded)
                        OnLandEvent.Invoke();
                }
            }
        }

        if (wasGrounded && !m_Grounded)
        {
            OnAirEvent.Invoke();
        }
    }


    public void Move(float move, bool jump)
    {
        // 玩家在地面时,或者可以空中控制时,才能移动
        if (m_Grounded || canAirControl)
        {
            // 输入变量move决定横向速度
            m_Rigidbody2D.velocity = new Vector2(move, m_Rigidbody2D.velocity.y);

            // 面朝右时按左键,或面朝左时按右键,都会让角色水平翻转
            if (move > 0 && !m_FacingRight)
            {
                Flip();
            }
            else if (move < 0 && m_FacingRight)
            {
                Flip();
            }
        }

        // 在地面时按下跳跃键,就会跳跃
        if (m_Grounded && jump)
        {
            OnAirEvent.Invoke();
            m_Grounded = false;
            // 施加弹跳力
            m_Rigidbody2D.AddForce(new Vector2(0f, jumpForce));
            m_NextGroundCheckTime = Time.time + m_NextGroundCheckLag;
        }
    }


    private void Flip()
    {
        // true变false,false变true
        m_FacingRight = !m_FacingRight;

        // 缩放的x轴乘以-1,图片就水平翻转了
        transform.localScale = Vector3.Scale(transform.localScale, new Vector3(-1, 1, 1));
    }
}

 PlayerMovement :

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

public class PlayerMovement : MonoBehaviour
{
    public CharacterController2D cc;//角色控制器组件

    public Animator animator;//动画控制器组件

    public float speed = 5f;//速度

    float move;//水平移动方向

    bool jump;//是否跳跃

    bool crouch;//是否爬行

    // Update is called once per frame
    void Update()
    {
        move = Input.GetAxis("Horizontal")*speed;//获取角色水平移动速度
        animator.SetFloat("Speed", Mathf.Abs(move));//将玩家当前速度传给动画器的speed参数
        if (Input.GetButtonDown("Jump"))//判断什么时候播放跳跃动画
        {
            jump = true;
            animator.SetBool("Jumping", true);
        }
        if (Input.GetKey(KeyCode.S))//判断什么时候播放爬行动画
        {
            crouch = true;
        }else
        {
            crouch = false;
        }
        animator.SetBool("Crouching", crouch);
    }
    //结合CharacterController2D脚本,检测是否在地面
    public void OnLanding()
    {
        jump = false;
        animator.SetBool("Jumping", false);//判断何时停止跳跃
    }

    void FixedUpdate()
    {
        cc.Move(move, jump);
    }
}

参考视频链接:

https://youtu.be/hkaysu1Z-N8