Unity学习记录-2D角色移动跳跃

角色移动

角色移动是一个持久性的动作,放在FixedUpdate中处理

  • 获取输入
  • 设置刚体的速度
  • 根据需要调整角色贴图的朝向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
///<summary>
///角色左右移动
///</summary>
void PlayerMove()
{
if (!isHited) //如果角色不处于受击状态
{
//获取角色的移动方向 -1,0,1
float movement = Input.GetAxisRaw("Horizontal");

//对角色进行移动
playerRb.velocity = new Vector2(movement * moveSpeed * Time.fixedDeltaTime, playerRb.velocity.y);

//对角色进行转向
if (movement != 0)
{
this.gameObject.transform.localScale = new Vector3(movement, 1, 1);
}
}
}

角色跳跃

  • 如何解决多段跳中,跳跃次数刷新的问题?
    1. 多段跳中,跳跃次数的BUG主要原因是:角色在起跳的一瞬间,还是和地面层接触,在此瞬间跳跃次数会刷新
    2. 使用射线检测和Rigidbody的IsTouchingLayers方法来检测是否接触地面
    3. 在落地的一瞬间(y轴速度小于0且触地)恢复跳跃次数
  • 如何优化角色的跳跃手感?
    1. 在角色跳跃后下降的过程,将下落速度增大,让角色更快下落以优化手感
    2. 在角色向上跳跃时先将Rigidbody的y轴速度赋为0,再施加向上的力可以保证每次跳跃高度相同
    3. 角色向上跳跃时限制最大速度

整体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerMovement : MonoBehaviour
{
[Header("移动速度")]
public float moveSpeed;
[Header("跳跃力度")]
public float jumpForce;
[Header("跳跃次数")]
public int jumpCount = 2;
[Header("最大跳跃速度")]
public float maxJumpSpeed;

private Rigidbody2D playerRb;
private BoxCollider2D playerCollider;
private int jumpTime; //当前可用的跳跃次数
private bool isOnGround = false; //是否触地
private GameObject currentGround; //当前接触的地面

[SerializeField][Header("左侧检查点")]
private GameObject leftCheckPoint;
[SerializeField][Header("右侧检查点")]
private GameObject rightCheckPoint;

[SerializeField]private bool isHited = false;
[SerializeField] private LayerMask ground;

void Start()
{
playerRb = gameObject.GetComponent<Rigidbody2D>();
playerCollider = gameObject.GetComponent<BoxCollider2D>();
anim = GetComponent<Animator>();
//技能一,三段跳
if(GetComponent<PlayerInfo>().getSkillNum() == 1)
{
jumpCount = 3;
}
jumpTime = jumpCount;
//Physics2D.IgnoreLayerCollision(6, 6); //忽略玩家间的碰撞
}

void FixedUpdate()
{
PlayerMove();
}

void Update()
{
PlayerJump();
BetterFalling();
CheckIsGround();
}

///<summary>
///角色左右移动
///</summary>
void PlayerMove()
{
if (!isHited)
{
//获取角色的移动方向 -1,0,1
float movement = Input.GetAxisRaw("Horizontal");
//对角色进行移动
playerRb.velocity = new Vector2(movement * moveSpeed * Time.fixedDeltaTime, playerRb.velocity.y);
//对角色进行转向
if (movement != 0)
{
this.gameObject.transform.localScale = new Vector3(movement, 1, 1);
}
}
}

///<summary>
///角色跳跃
///</summary>
void PlayerJump()
{
if(jumpTime>0)
{
if(Input.GetButtonDown("Jump"))
{
jumpTime--;
//清除y轴方向的速度,保证每次跳跃高度相同
playerRb.velocity = new Vector2(playerRb.velocity.x, 0);
//AddForce添加向上的力
playerRb.AddForce(Vector2.up*jumpForce);
anim.SetBool("isJumping", true);//跳跃动画
isOnGround = false;
}
}
//限制向上的速度
if(playerRb.velocity.y>maxJumpSpeed)
{
playerRb.velocity = new Vector2(playerRb.velocity.x, maxJumpSpeed);
}
}

/// <summary>
/// 跳跃手感优化
/// </summary>
void BetterFalling()
{
if(playerRb.velocity.y<0)
{
//增加下落的速度
playerRb.velocity += Vector2.up * Physics2D.gravity.y * (3.0f)*Time.deltaTime;
}
}

/// <summary>
/// 检查是否触地面
/// </summary>
void CheckIsGround()
{
//射线检测,left和right对应角色的两脚
RaycastHit2D left = Physics2D.Raycast(leftCheckPoint.transform.position, Vector2.down*0.03f, 0.03f,ground);
RaycastHit2D right = Physics2D.Raycast(rightCheckPoint.transform.position, Vector2.down*0.03f, 0.03f,ground);
bool rayCheckResult = left||right;

//触地检测
if (playerRb.IsTouchingLayers(ground) || rayCheckResult)
{
isOnGround = true;
}
else
{
isOnGround = false;
}

//落地恢复跳跃次数
if (playerRb.velocity.y<0 && (playerRb.IsTouchingLayers(ground)||rayCheckResult))
{
jumpTime = jumpCount;
}
}
}

多段跳——跳跃次数bug解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/// <summary>
/// 检查是否触地面
/// </summary>
void CheckIsGround()
{
//射线检测,left和right对应角色的两脚
RaycastHit2D left = Physics2D.Raycast(leftCheckPoint.transform.position, Vector2.down*0.03f, 0.03f,ground);
RaycastHit2D right = Physics2D.Raycast(rightCheckPoint.transform.position, Vector2.down*0.03f, 0.03f,ground);
bool rayCheckResult = left||right;

//触地检测
if (playerRb.IsTouchingLayers(ground) || rayCheckResult)
{
isOnGround = true;
}
else
{
isOnGround = false;
}

//落地恢复跳跃次数
if (playerRb.velocity.y<0 && (playerRb.IsTouchingLayers(ground)||rayCheckResult))
{
jumpTime = jumpCount;
}
}

跳跃手感优化

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 跳跃手感优化
/// </summary>
void BetterFalling()
{
if(playerRb.velocity.y<0)
{
//增加下落的速度
playerRb.velocity += Vector2.up * Physics2D.gravity.y * (3.0f)*Time.deltaTime;
}
}

也可以通过增加角色的重力来实现更快的起跳和落地,优化手感