C# Unity2D:Can';平衡壁面跳跃力
我的意图是让我的角色在墙壁上跳跃/攀爬/滑动,我让滑动部分工作得很好,但是如果他在墙壁滑动时跳跃,他应该“反弹”到墙壁上,问题是我无法平衡力量。在我看到的所有教程中,这只是一个简单的问题,即检测角色是否在滑动墙壁,如果他在滑动,并且他在跳跃,则向墙壁添加一个力 这对我不起作用,因为如果我增加足够的力量让他跳,他跳得太快了,玩家几乎看不到他跳了,他只是看到角色现在在墙上更高了。如果我再加上一点力,这还不足以做出一个相当大的跳跃,玩家必须打一千次空格才能让他在墙上上升几厘米 感谢您的帮助,我已经尝试了很多方法,甚至尝试冻结控件,将重力比例设置为0,并使用MoveToward将角色fo设置到正确的点,这就是我的绝望 我对Unity也很陌生,所以我可能错过了一些非常简单的东西 以下是显示角色行为的gif: 以下是我角色剧本的相关部分:C# Unity2D:Can';平衡壁面跳跃力,c#,unity3d,C#,Unity3d,我的意图是让我的角色在墙壁上跳跃/攀爬/滑动,我让滑动部分工作得很好,但是如果他在墙壁滑动时跳跃,他应该“反弹”到墙壁上,问题是我无法平衡力量。在我看到的所有教程中,这只是一个简单的问题,即检测角色是否在滑动墙壁,如果他在滑动,并且他在跳跃,则向墙壁添加一个力 这对我不起作用,因为如果我增加足够的力量让他跳,他跳得太快了,玩家几乎看不到他跳了,他只是看到角色现在在墙上更高了。如果我再加上一点力,这还不足以做出一个相当大的跳跃,玩家必须打一千次空格才能让他在墙上上升几厘米 感谢您的帮助,我已经尝试
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TheBot : MonoBehaviour {
public float speed;
public int jumpForce;
public Transform groundCheck;
public Transform meleeCheck;
public Transform bulletSpawner;
public LayerMask layerGround;
public float meleeCoolDown;
public float meleeDamage;
private Rigidbody2D body;
private Animator anim;
private Dash dashController;
private Shooter shotController;
private float unloadWaitingTime = 3;
private float idleGunTime = 0;
private bool facingRight = true;
private bool onGround = true;
private bool jumping = false;
private bool attacking = false;
private bool dead = false;
private bool isGunLoaded = false;
private bool isGunLoading = false;
private bool isGunUnloading = false;
private bool takingDamage = false;
private bool dashing = false;
private bool isWallSliding = false;
private float wallJumpTime = 0f;
private Vector3[] wallJumpControlPoint;
// Use this for initialization
void Start () {
body = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
dashController = GetComponent<Dash>();
shotController = GetComponent<Shooter>();
}
// Update is called once per frame
void Update () {
PlayAnimations();
CheckIfGrounded();
checkIfWallSliding();
dashing = dashController.IsDashing();
if (Input.GetButtonDown("Jump") && (onGround || isWallSliding) && !isGunLoading && !jumping && !takingDamage){
jumping = true;
wallJumpControlPoint = new Vector3[3];
wallJumpControlPoint[0] = body.position;
wallJumpControlPoint[1] = new Vector3(body.position.x +4, body.position.y + 2);
wallJumpControlPoint[2] = new Vector3(body.position.x, body.position.y + 4);
}
if (Input.GetButtonDown("Melee") && !attacking && !isGunLoading){
Attack();
}
if(Input.GetButtonDown("Ranged") && !attacking && !isGunLoading && onGround){
Shoot();
}
if(Input.GetButtonDown("Dash") && !attacking && !isGunLoading && onGround){
dashController.DashTo(facingRight? Dash.RIGHT : Dash.LEFT);
}
if(isGunLoaded){
idleGunTime += Time.deltaTime;
if (idleGunTime >= unloadWaitingTime){
UnloadGun();
}
}
}
void FixedUpdate(){
if(!takingDamage){
float move = Input.GetAxis("Horizontal");
//while charachter is wall sliding, slowly fall
if (isWallSliding){
body.velocity = new Vector2(body.velocity.x, -0.7f);
}
if(!dashing){
if(onGround){
//if not dashing on on ground, walk with normal speed
body.velocity = new Vector2(move * speed, body.velocity.y);
} else {
//if character is not on ground, reduce the speed so he doesn't jump too far away
body.velocity = new Vector2(move * (speed * 0.7f), body.velocity.y);
}
}
if((move < 0 && facingRight) || (move > 0 && !facingRight) ){
//control direction character is facing
Flip();
}
if (jumping){
if(isWallSliding){
body.velocity = new Vector2(30, 20);
} else {
body.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);
}
if(Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow)){
//if is moving while jumping, reduce jump height
body.velocity = new Vector2(body.velocity.x, body.velocity.y*0.8f);
}
onGround = false;
jumping = false;
}
}
}
void CheckIfGrounded(){
onGround = false;
Collider2D[] collisionResults = new Collider2D[2];
int objectsBeneath = Physics2D.OverlapBoxNonAlloc(groundCheck.position, new Vector2(0.9f, 0.3f), 0.0f, collisionResults, layerGround);
for (int i=0; i <objectsBeneath; i++ ){
if (!GameObject.ReferenceEquals(gameObject, collisionResults[i].gameObject)){
onGround = true;
}
}
}
void checkIfWallSliding(){
if (!onGround){
RaycastHit2D[] ray = new RaycastHit2D[1];
int totalRayHits = Physics2D.LinecastNonAlloc(bulletSpawner.position, body.position, ray, 1 << LayerMask.NameToLayer("SolidGround"));
bool wallFound = totalRayHits > 0 && ray[0].collider.gameObject.tag == "SolidGround";
isWallSliding = wallFound && ( (facingRight && Input.GetKey(KeyCode.RightArrow)) || (!facingRight && Input.GetKey(KeyCode.LeftArrow))) ;
} else {
isWallSliding = false;
if (body.velocity.y > 10){
body.velocity = new Vector2(body.velocity.x, 5);
}
}
}
public void Die(){
dead = true;
}
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
公共类TheBot:单一行为{
公众浮标速度;
公共安全部队;
公开审查;
公共交通检查;
公共产卵器;
公共层屏蔽层环绕;
公共浮球冷却;
公共交通混乱;
私人刚体2D机构;
私人动画师;
专用仪表盘控制器;
私人射击控制器;
私有浮动unloadWaitingTime=3;
私有float idleGunTime=0;
私有bool-facingRight=true;
private bool onGround=真;
私人布尔跳跃=假;
私有布尔攻击=假;
二等兵布尔死=假;
private bool isgunload=假;
私有bool isGunLoading=假;
私有bool=false;
私人楼宇损坏=错误;
private bool dashing=假;
private bool IswallSlideing=假;
私有浮动时间=0f;
专用矢量3[]控制点;
//用于初始化
无效开始(){
body=GetComponent();
anim=GetComponent();
dashController=GetComponent();
shotController=GetComponent();
}
//每帧调用一次更新
无效更新(){
播放动画();
checkifground();
checkIfWallSliding();
dashing=dashController.IsDashing();
如果(输入.GetButtonDown(“跳跃”)&&(onGround | | | IsWallSlideing)&&!isGunLoading&!跳跃和承受伤害){
跳跃=正确;
wallJumpControlPoint=新矢量3[3];
wallJumpControlPoint[0]=body.position;
wallJumpControlPoint[1]=新矢量3(body.position.x+4,body.position.y+2);
wallJumpControlPoint[2]=新矢量3(body.position.x,body.position.y+4);
}
if(Input.GetButtonDown(“近战”)&&!攻击&&!isGunLoading){
攻击();
}
if(Input.GetButtonDown(“Ranged”)&&&!攻击&&!isGunLoading&&onGround){
射击();
}
if(Input.GetButtonDown(“Dash”)&&&!攻击&&!isGunLoading&&onGround){
dashController.DashTo(朝向右侧?Dash.RIGHT:Dash.LEFT);
}
如果(带枪){
idleGunTime+=Time.deltaTime;
if(idleGunTime>=卸载等待时间){
解锁枪();
}
}
}
void FixedUpdate(){
如果(!承受损坏){
float move=Input.GetAxis(“水平”);
//当charachter在墙壁上滑动时,缓慢下降
如果(Iswall滑动){
body.velocity=新矢量2(body.velocity.x,-0.7f);
}
如果(!破折号){
如果(每轮){
//如果没有在地面上冲刺,则以正常速度行走
body.velocity=新矢量2(移动*速度,body.velocity.y);
}否则{
//如果角色不在地面上,降低速度,这样他就不会跳得太远
body.velocity=新矢量2(移动*(速度*0.7f),body.velocity.y);
}
}
if((移动<0&&朝向右侧)| |(移动>0&&朝向右侧)){
//控制方向字符所面对的方向
翻转();
}
如果(跳跃){
如果(Iswall滑动){
body.velocity=新矢量2(30,20);
}否则{
body.AddForce(新矢量2(0f,跳跃力),ForceMode2D.Pulse);
}
if(Input.GetKey(KeyCode.RightArrow)| | Input.GetKey(KeyCode.LeftArrow)){
//如果在跳跃时移动,降低跳跃高度
body.velocity=新矢量2(body.velocity.x,body.velocity.y*0.8f);
}
onGround=假;
跳跃=错误;
}
}
}
void CheckIfGrounded(){
onGround=假;
CollizedR2d[]碰撞结果=新的碰撞r2D[2];
int objectsBeneath=Physics2D.overlappeboxNonaloc(groundCheck.position,新矢量2(0.9f,0.3f),0.0f,碰撞结果,层轮);
对于(int i=0;i 10){
body.velocity=新矢量2(body.velocity.x,5);
}
}
}
公共空间(){
死=真;
}
}
正如您之前尝试的那样,您需要降低跳跃时的水平跳跃加速度/速度
当你跳墙的时候,你会朝着墙挤。当你在空中时,你的水平速度被设置为你按下的方向。这使得任何水平运动从
if(!dashing){
if(onGround){
//if not dashing on on ground, walk with normal speed
body.velocity = new Vector2(move * speed, body.velocity.y);
} else {
//if character is not on ground, reduce the speed so he doesn't jump too far away
float airControlAccelerationLimit = 0.5f; // Higher = more responsive air control
float airSpeedModifier = 0.7f; // the 0.7f in your code, affects max air speed
float targetHorizVelocity = move
* speed
* airSpeedModifier; // How fast we are trying to move horizontally
float targetHorizChange = targetHorizVelocity
- body.velocity.x; // How much we want to change the horizontal velocity
float horizChange = Mathf.Clamp(
targetHorizChange ,
-airControlAccelerationLimit ,
airControlAccelerationLimit ); // How much we are limiting ourselves
// to changing the horizontal velocity
body.velocity = new Vector2(body.velocity.x + horizChange, body.velocity.y);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TheBot : MonoBehaviour {
public float speed;
public int jumpForce;
public Transform groundCheck;
public Transform meleeCheck;
public Transform bulletSpawner;
public LayerMask layerGround;
public float meleeCoolDown;
public float meleeDamage;
private Rigidbody2D body;
private Animator anim;
private Dash dashController;
private Shooter shotController;
private float unloadWaitingTime = 3;
private float idleGunTime = 0;
private bool facingRight = true;
private bool onGround = true;
private bool jumping = false;
private bool attacking = false;
private bool dead = false;
private bool isGunLoaded = false;
private bool isGunLoading = false;
private bool isGunUnloading = false;
private bool takingDamage = false;
private bool dashing = false;
private bool isWallSliding = false;
private float wallJumpTime = 0f;
private Vector3[] wallJumpControlPoint;
// Use this for initialization
void Start () {
body = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
dashController = GetComponent<Dash>();
shotController = GetComponent<Shooter>();
}
// Update is called once per frame
void Update () {
PlayAnimations();
CheckIfGrounded();
checkIfWallSliding();
dashing = dashController.IsDashing();
if (Input.GetButtonDown("Jump") && (onGround || isWallSliding) && !isGunLoading && !jumping && !takingDamage){
jumping = true;
wallJumpControlPoint = new Vector3[3];
wallJumpControlPoint[0] = body.position;
wallJumpControlPoint[1] = new Vector3(body.position.x +4, body.position.y + 2);
wallJumpControlPoint[2] = new Vector3(body.position.x, body.position.y + 4);
}
if (Input.GetButtonDown("Melee") && !attacking && !isGunLoading){
Attack();
}
if(Input.GetButtonDown("Ranged") && !attacking && !isGunLoading && onGround){
Shoot();
}
if(Input.GetButtonDown("Dash") && !attacking && !isGunLoading && onGround){
dashController.DashTo(facingRight? Dash.RIGHT : Dash.LEFT);
}
if(isGunLoaded){
idleGunTime += Time.deltaTime;
if (idleGunTime >= unloadWaitingTime){
UnloadGun();
}
}
}
void FixedUpdate(){
if(!takingDamage){
float move = Input.GetAxis("Horizontal");
//while charachter is wall sliding, slowly fall
if (isWallSliding && !jumping && body.velocity.y < -0.7f){
body.velocity = new Vector2(body.velocity.x, -0.7f)
}
if(!dashing){
if(onGround){
//if not dashing on on ground, walk with normal speed
body.velocity = new Vector2(move * speed, body.velocity.y);
} else {
//if character is not on ground, reduce the speed so he doesn't jump too far away
float airControlAccelerationLimit = 0.5f; // Higher = more responsive air control
float airSpeedModifier = 0.7f; // the 0.7f in your code, affects max air speed
float targetHorizVelocity = move
* speed
* airSpeedModifier; // How fast we are trying to move horizontally
float targetHorizChange = targetHorizVelocity
- body.velocity.x; // How much we want to change the horizontal velocity
float horizChange = Mathf.Clamp(
targetHorizChange ,
-airControlAccelerationLimit ,
airControlAccelerationLimit ); // How much we are limiting ourselves
// to changing the horizontal velocity
body.velocity = new Vector2(body.velocity.x + horizChange, body.velocity.y);
}
}
if((move < 0 && facingRight) || (move > 0 && !facingRight) ){
//control direction character is facing
Flip();
}
if (jumping){
if(isWallSliding){
body.velocity = new Vector2(body.velocity.x + 0.25f * jumpForce, jumpForce);
} else {
body.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse);
}
if(Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow)){
//if is moving while jumping, reduce jump height
body.velocity = new Vector2(body.velocity.x, body.velocity.y*0.8f);
}
onGround = false;
jumping = false;
}
}
}
void CheckIfGrounded(){
onGround = false;
Collider2D[] collisionResults = new Collider2D[2];
int objectsBeneath = Physics2D.OverlapBoxNonAlloc(groundCheck.position, new Vector2(0.9f, 0.3f), 0.0f, collisionResults, layerGround);
for (int i=0; i <objectsBeneath; i++ ){
if (!GameObject.ReferenceEquals(gameObject, collisionResults[i].gameObject)){
onGround = true;
}
}
}
void checkIfWallSliding(){
if (!onGround){
RaycastHit2D[] ray = new RaycastHit2D[1];
int totalRayHits = Physics2D.LinecastNonAlloc(bulletSpawner.position, body.position, ray, 1 << LayerMask.NameToLayer("SolidGround"));
bool wallFound = totalRayHits > 0 && ray[0].collider.gameObject.tag == "SolidGround";
isWallSliding = wallFound && ( (facingRight && Input.GetKey(KeyCode.RightArrow)) || (!facingRight && Input.GetKey(KeyCode.LeftArrow))) ;
} else {
isWallSliding = false;
}
}
public void Die(){
dead = true;
}
}