实现Unity2D游戏中跳跃功能和相关问题解决
Posted 超级开朗的网友
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现Unity2D游戏中跳跃功能和相关问题解决相关的知识,希望对你有一定的参考价值。
一、跳跃功能基本实现
二、跳跃bug解决
三、跳跃优化
一、跳跃功能基本实现
在unity中我们要实现跳跃功能基本依赖代码实现。在这里我们先构建场景,笔者在这里使用tilemap构建地面,创建正方形代表物体。如图所示
我们要为其添加代码,我在这创建名为Control.cs的C#脚本,用来控制正方形的行为,将其绑定到正方形组件上,同时为正方形添加rigidbody2d和boxcollider组件,将rigidbody2d中z轴锁定。并且也为tilemap添加组合碰撞体和tilemapcollider,将tilemapcollider中Use by Composite打钩,使用tilemap组合碰撞体,调整碰撞区域,锁定x,y,z轴。同时为了方便,引入Cinemachine跟随正方形,以便实时观察。
Control.cs的代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Control : MonoBehaviour
//声明刚体组件
Rigidbody2D rigidbody;
//力大小
float force = 300.0f;
void Start()
//获取刚体组件
rigidbody = GetComponent<Rigidbody2D>();
void Update()
//如果按下W,实现跳跃功能
if (Input.GetKeyDown(KeyCode.W))
Jump();
void Jump()
//对物体施加方向向上的力,也可以对rigidbody.velocity进行操作,但是不推荐
rigidbody.AddForce(Vector2.up * force);
这样基本的跳跃功能我们就实现了。
二、跳跃bug解决
在运行中,我们很快就能发现一个问题,只要我们多次按W键,它就能一直跳跃,这当然不符合实际情况。我们需要代码监测它是否在地面上。我们可以重载OnCollisionEnter2D和OnCollisionExit2D来监测它是否在地面上。
首先,我们要把tilemap的tag设置为Ground,没有的自行添加。
将代码修改为:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Control : MonoBehaviour
//声明刚体组件
Rigidbody2D rigidbody;
//力大小
float force = 300.0f;
//设置是否可以跳跃的bool值,初始值为true
bool jumpable = true;
void Start()
//获取刚体组件
rigidbody = GetComponent<Rigidbody2D>();
void Update()
//如果按下W,实现跳跃功能
if (Input.GetKeyDown(KeyCode.W))
Jump();
void Jump()
if (jumpable)
//对物体施加方向向上的力,也可以对rigidbody.velocity进行操作,但是不推荐
rigidbody.AddForce(Vector2.up * force);
//与地面碰撞,jumpable为true
private void OnCollisionEnter2D(Collision2D collision)
//如果碰撞体的tag为Ground,设置jumpable
if(collision.gameObject.tag == "Ground")
jumpable = true;
//离开地面,jumpable为false
private void OnCollisionExit2D(Collision2D collision)
if (collision.gameObject.tag == "Ground")
jumpable = false;
这样就可以解决这个问题了。
在很多游戏中,我们要设置多段跳功能。所以我们要设置一个int存放当前跳跃次数。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Control : MonoBehaviour
//声明刚体组件
Rigidbody2D rigidbody;
//力大小
float force = 300.0f;
//设置是否可以跳跃的bool值,初始值为true
bool jumpable = true;
//设置n段跳
int n;
void Start()
//获取刚体组件
rigidbody = GetComponent<Rigidbody2D>();
void Update()
//如果按下W,实现跳跃功能
if (Input.GetKeyDown(KeyCode.W))
Jump();
void Jump()
//二段跳 要放在update里面 因为没fixedDeltaTime
if (jumpable)
n = 1;//踩在地面上的时候,可以跳n+1次,想要设置三段跳只要改为2即可
if (Input.GetKeyDown(KeyCode.W) && n >= 0)
rigidbody.AddForce(Vector2.up * force);
n--;
//与地面碰撞,jumpable为true
private void OnCollisionEnter2D(Collision2D collision)
//如果碰撞体的tag为Ground,设置jumpable
if(collision.gameObject.tag == "Ground")
jumpable = true;
//离开地面,jumpable为false
private void OnCollisionExit2D(Collision2D collision)
if (collision.gameObject.tag == "Ground")
jumpable = false;
墙体是2d游戏中很常见的情景,我们当前的代码只能监测物体的碰撞,如果他碰撞到墙体,jumpable=true,那么它还能进行跳跃,这也不符合生活实际,解决这个问题有些困难,由于各种原因,以下的方法不一定能成功解决,请大家一一测试再应用。
第一种方法:可以通过射线监测,从中心点发射一条竖直向下,固定长度的射线,如果射线碰撞到地面设置jumpbable = true。
使用前检查sprite的中心点,射线从此处发射的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Control : MonoBehaviour
//声明刚体组件
Rigidbody2D rigidbody;
//力大小
float force = 300.0f;
//设置是否可以跳跃的bool值,初始值为true
bool jumpable = true;
//设置n段跳
int n;
//设置射线长度
float length = 1.0f;
void Start()
//获取刚体组件
rigidbody = GetComponent<Rigidbody2D>();
void Update()
//创建射线
RaycastHit2D info = Physics2D.Raycast(rigidbody.position, -Vector2.up, length);
if (info.collider != null)
//如果发生了碰撞
GameObject obj = info.collider.gameObject;
if (obj.CompareTag("Ground"))//用tag判断碰到了什么对象
jumpable = true;
//如果按下W,实现跳跃功能
if (Input.GetKeyDown(KeyCode.W))
Jump();
void Jump()
//二段跳 要放在update里面 因为没fixedDeltaTime
if (jumpable)
n = 1;//踩在地面上的时候,可以跳n+1次,想要设置三段跳只要改为2即可
if (Input.GetKeyDown(KeyCode.W) && n >= 0)
rigidbody.AddForce(Vector2.up * force);
n--;
但是这会使得射线长度难以确定,长度过长,还没有跳到地面上就就可以跳起了;长度过短,射线监测不到,就跳不起来。这个长度需要反复调试,并且改变参数可能还需要重新调试,所以我不太推荐这种方法。
第二种方法:在物体脚下设置触发器。再添加一个boxcollider,勾选Is Trigger,代表这个碰撞区域是触发器。如图所示
需要注意的是,触发器的宽度要比原本的碰撞体小,下方可以突出一点,以便代码更好的监测。
在代码中我们通过重载OnTriggerEnter2D和OnTriggerExit2D来监测是否在地面
代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Control : MonoBehaviour
//声明刚体组件
Rigidbody2D rigidbody;
//力大小
float force = 300.0f;
//设置是否可以跳跃的bool值,初始值为true
bool jumpable = true;
//设置n段跳
int n;
void Start()
//获取刚体组件
rigidbody = GetComponent<Rigidbody2D>();
void Update()
//如果按下W,实现跳跃功能
if (Input.GetKeyDown(KeyCode.W))
Jump();
void Jump()
//二段跳 要放在update里面 因为没fixedDeltaTime
if (jumpable)
n = 1;//踩在地面上的时候,可以跳n+1次,想要设置三段跳只要改为2即可
if (Input.GetKeyDown(KeyCode.W) && n >= 0)
rigidbody.AddForce(Vector2.up * force);
n--;
//重载函数来监测
private void OnTriggerEnter2D(Collider2D collision)
if(collision.gameObject.tag == "Ground")
jumpable = true;
private void OnTriggerExit2D(Collider2D collision)
if (collision.gameObject.tag == "Ground")
jumpable = false;
这种方法实现可能性较大。
在测试中,跳到墙面上,在添加了移动代码之后跳到墙面上,有可能出现按方向键,物体没有掉下来的情况。我们需要设置物理材料。
在Project视图中,添加物理材料。
打开物理材料,将摩擦力设置为0
将物理材料拖拽到rigidbody中。
就可以有效解决这个bug了。
三、跳跃优化
跳跃的功能完成了,但是运行时感觉距离现实情况仍有些距离。
事实上,如果你让物体从高处落下,你会发现在下落过程中,它的速度并没有增加,更像是匀速下降。所以我们要为其添加重力。
注:此处修改代码来自B站“更好的跳跃”
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Control : MonoBehaviour
//声明刚体组件
Rigidbody2D rigidbody;
//力大小
float force = 300.0f;
//设置是否可以跳跃的bool值,初始值为true
bool jumpable = true;
//设置n段跳
int n;
void Start()
//获取刚体组件
rigidbody = GetComponent<Rigidbody2D>();
void Update()
//如果按下W,实现跳跃功能
if (Input.GetKeyDown(KeyCode.W))
Jump();
//上升和下落过程中,手动改变速度
if(rigidbody.velocity.y < 0)
rigidbody.velocity -= Vector2.up * Physics2D.gravity.y * Time.deltaTime;
else if(rigidbody.velocity.y > 0)
rigidbody.velocity += Vector2.up * Physics2D.gravity.y * Time.deltaTime;
void Jump()
//二段跳 要放在update里面 因为没fixedDeltaTime
if (jumpable)
n = 1;//踩在地面上的时候,可以跳n+1次,想要设置三段跳只要改为2即可
if (Input.GetKeyDown(KeyCode.W) && n >= 0)
rigidbody.AddForce(Vector2.up * force);
n--;
//重载函数来监测
private void OnTriggerEnter2D(Collider2D collision)
if(collision.gameObject.tag == "Ground")
jumpable = true;
private void OnTriggerExit2D(Collider2D collision)
if (collision.gameObject.tag == "Ground")
jumpable = false;
运行后,会发现更加贴近生活生活实际了。
最后,感谢你看完我的文章。本人是大一学生,文章难免有不足之处,恳请专业人士批评指正。
以上是关于实现Unity2D游戏中跳跃功能和相关问题解决的主要内容,如果未能解决你的问题,请参考以下文章
(转)CocosCreator零基础制作游戏《极限跳跃》制作游戏障碍物实现碰撞检测