• Unity笔记(5):Make Character Animation【2D】


    目录

    1、新建项目

    2、导入资源

    复习一下前两篇笔记:

    3、搭建场景

    4、控制角色移动 

     5、制作角色动画

    发现问题:

    解决问题:


    1、新建项目

    2、导入资源

    Sunny Land | 2D Characters | Unity Asset Store

    复习一下前两篇笔记:

    3、搭建场景

    传送门:

    Unity笔记(2):游戏场景搭建_代码骑士的博客-CSDN博客

    4、控制角色移动 

    传送门:

    Unity笔记(4):控制角色移动_代码骑士的博客-CSDN博客

     5、制作角色动画

    打开animation组件

    新建动画文件

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

    调节适当的频率

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

    如下:

    打开动画控制器

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    添加动画控制器组件:

    将动画器组件拖入栏中

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

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

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

    设置跳跃动画

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

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

    再设置转换条件

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

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

    jump->idle

     jump->run

    然后修改代码:

    普通写法:

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class PlayerMovement : MonoBehaviour
    5. {
    6. public CharacterController2D cc;//角色控制器组件
    7. public Animator animator;//动画控制器组件
    8. public float speed = 5f;//速度
    9. float move;//水平移动方向
    10. bool jump;//是否跳跃
    11. // Update is called once per frame
    12. void Update()
    13. {
    14. move = Input.GetAxis("Horizontal")*speed;//获取角色水平移动速度
    15. animator.SetFloat("Speed", Mathf.Abs(move));//将玩家当前速度传给动画器的speed参数
    16. jump = Input.GetButton("Jump");
    17. animator.SetBool("Jumping", jump);
    18. }
    19. void FixedUpdate()
    20. {
    21. cc.Move(move, jump);
    22. }
    23. }

     高级写法:

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class PlayerMovement : MonoBehaviour
    5. {
    6. public CharacterController2D cc;//角色控制器组件
    7. public Animator animator;//动画控制器组件
    8. public float speed = 5f;//速度
    9. float move;//水平移动方向
    10. bool jump;//是否跳跃
    11. // Update is called once per frame
    12. void Update()
    13. {
    14. move = Input.GetAxis("Horizontal")*speed;//获取角色水平移动速度
    15. animator.SetFloat("Speed", Mathf.Abs(move));//将玩家当前速度传给动画器的speed参数
    16. if (Input.GetButtonDown("Jump"))//判断什么时候播放跳跃动画
    17. {
    18. jump = true;
    19. animator.SetBool("Jumping", true);
    20. }
    21. }
    22. //结合CharacterController2D脚本,检测是否在地面
    23. public void OnLanding()
    24. {
    25. jump = false;
    26. animator.SetBool("Jumping", false);//判断何时停止跳跃
    27. }
    28. void FixedUpdate()
    29. {
    30. cc.Move(move, jump);
    31. }
    32. }

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

    发现问题:

    动画只能播放一半

    解决问题:

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

    同理添加Crouch动画

    注意:

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

     

    角色爬行代码:

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

    最后放上完整的代码:

    CharacterController2D :

    1. using UnityEngine;
    2. using UnityEngine.Events;
    3. public class CharacterController2D : MonoBehaviour
    4. {
    5. public float jumpForce = 400f; // 弹跳力
    6. public bool canAirControl = false; // 在空中时,是否能控制
    7. public LayerMask groundMask; // 定义哪一个Layer是地面
    8. public Transform m_GroundCheck; // 用于判定地面的空物体
    9. const float k_GroundedRadius = .1f; // 用于检测地面的小圆形的半径
    10. private bool m_Grounded; // 当前是否在地面上
    11. private bool m_FacingRight = true; // 玩家是否面朝右边
    12. private Vector3 m_Velocity = Vector3.zero;
    13. const float m_NextGroundCheckLag = 0.1f; // 起跳后的一小段时间,不能再次起跳。防止连跳的一种解决方案
    14. float m_NextGroundCheckTime; // 过了这个时间才可能落地、才能再次起跳
    15. // 这个角色控制器,是依靠刚体驱动的
    16. private Rigidbody2D m_Rigidbody2D;
    17. [Header("Events")]
    18. [Space]
    19. public UnityEvent OnLandEvent;
    20. public UnityEvent OnAirEvent;
    21. [System.Serializable]
    22. public class BoolEvent : UnityEvent<bool> { }
    23. private void Awake()
    24. {
    25. m_Rigidbody2D = GetComponent();
    26. if (OnLandEvent == null)
    27. OnLandEvent = new UnityEvent();
    28. if (OnAirEvent == null)
    29. OnAirEvent = new UnityEvent();
    30. }
    31. private void FixedUpdate()
    32. {
    33. bool wasGrounded = m_Grounded;
    34. m_Grounded = false;
    35. // 检测与地面的碰撞
    36. if (Time.time > m_NextGroundCheckTime)
    37. {
    38. Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, groundMask);
    39. for (int i = 0; i < colliders.Length; i++)
    40. {
    41. if (colliders[i].gameObject != gameObject)
    42. {
    43. m_Grounded = true;
    44. if (!wasGrounded)
    45. OnLandEvent.Invoke();
    46. }
    47. }
    48. }
    49. if (wasGrounded && !m_Grounded)
    50. {
    51. OnAirEvent.Invoke();
    52. }
    53. }
    54. public void Move(float move, bool jump)
    55. {
    56. // 玩家在地面时,或者可以空中控制时,才能移动
    57. if (m_Grounded || canAirControl)
    58. {
    59. // 输入变量move决定横向速度
    60. m_Rigidbody2D.velocity = new Vector2(move, m_Rigidbody2D.velocity.y);
    61. // 面朝右时按左键,或面朝左时按右键,都会让角色水平翻转
    62. if (move > 0 && !m_FacingRight)
    63. {
    64. Flip();
    65. }
    66. else if (move < 0 && m_FacingRight)
    67. {
    68. Flip();
    69. }
    70. }
    71. // 在地面时按下跳跃键,就会跳跃
    72. if (m_Grounded && jump)
    73. {
    74. OnAirEvent.Invoke();
    75. m_Grounded = false;
    76. // 施加弹跳力
    77. m_Rigidbody2D.AddForce(new Vector2(0f, jumpForce));
    78. m_NextGroundCheckTime = Time.time + m_NextGroundCheckLag;
    79. }
    80. }
    81. private void Flip()
    82. {
    83. // true变false,false变true
    84. m_FacingRight = !m_FacingRight;
    85. // 缩放的x轴乘以-1,图片就水平翻转了
    86. transform.localScale = Vector3.Scale(transform.localScale, new Vector3(-1, 1, 1));
    87. }
    88. }

     PlayerMovement :

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class PlayerMovement : MonoBehaviour
    5. {
    6. public CharacterController2D cc;//角色控制器组件
    7. public Animator animator;//动画控制器组件
    8. public float speed = 5f;//速度
    9. float move;//水平移动方向
    10. bool jump;//是否跳跃
    11. bool crouch;//是否爬行
    12. // Update is called once per frame
    13. void Update()
    14. {
    15. move = Input.GetAxis("Horizontal")*speed;//获取角色水平移动速度
    16. animator.SetFloat("Speed", Mathf.Abs(move));//将玩家当前速度传给动画器的speed参数
    17. if (Input.GetButtonDown("Jump"))//判断什么时候播放跳跃动画
    18. {
    19. jump = true;
    20. animator.SetBool("Jumping", true);
    21. }
    22. if (Input.GetKey(KeyCode.S))//判断什么时候播放爬行动画
    23. {
    24. crouch = true;
    25. }else
    26. {
    27. crouch = false;
    28. }
    29. animator.SetBool("Crouching", crouch);
    30. }
    31. //结合CharacterController2D脚本,检测是否在地面
    32. public void OnLanding()
    33. {
    34. jump = false;
    35. animator.SetBool("Jumping", false);//判断何时停止跳跃
    36. }
    37. void FixedUpdate()
    38. {
    39. cc.Move(move, jump);
    40. }
    41. }

    参考视频链接:

    https://youtu.be/hkaysu1Z-N8

  • 相关阅读:
    pyqt5学习-01 UI界面创建以及生成python代码
    什么是区块链节点提供商?为什么Web3开发者都需要它?
    定位内存溢出错误
    室内外无缝定位技术:连接虚拟与现实的新桥梁
    .netcore对传输类设置区分大小
    阿里云 ECS 挂载数据盘 重启后自动挂载
    C语言qsort()函数针对:整型、单个字符、字符串、结构体,超详细讲解(多维度分析举例,小白一看就懂!!!!!)
    蜂蜡/聚苯乙烯大孔树脂微球/硫酸盐修饰聚苯乙烯微球/草莓状银/聚苯乙烯-丙烯腈复合微球的研究
    Vue2.js:v-click-outside自定义指令和vue-click-outside监听鼠标点击元素外部区域事件
    Java Base64 加密与解密
  • 原文地址:https://blog.csdn.net/qq_51701007/article/details/126431030