Player's Dash abilty not isnt working correctly - c#

I don't know how to make my character dash without it keeps ignoring the cooldown and the dash distance is small. I have been stumped on this for a long time and i want to continue with other things in my game but this has been stopping me. I use Unity and C#.
Here's my code:
public class PlayerMove : MonoBehaviour
{
private Rigidbody2D rb;
private BoxCollider2D bc;
private static bool isRunning;
private static bool isMoving;
private static bool isDashing;
private static bool isOnWall;
private static bool cooldown;
private static bool jumpCooldown;
private float time = 4f;
private float dashingspeed = 14f;
private float timewhiledashing = 2f;
private Vector2 dashingDir;
// Start is called before the first frame update
private void Start()
{
rb = GetComponent<Rigidbody2D>();
bc = GetComponent<BoxCollider2D>();
cooldown = false;
}
// Update is called once per frame
private void Update()
{
bool IsGrounded()
{
float extraHeightText = .01f;
RaycastHit2D raycastHit = Physics2D.Raycast(bc.bounds.center, Vector2.down, bc.bounds.extents.y + extraHeightText);
Color rayColor;
if (raycastHit.collider != null)
{
rayColor = Color.green;
}
else
{
rayColor = Color.red;
}
Debug.DrawRay(bc.bounds.center, Vector2.down * (bc.bounds.extents.y + extraHeightText));
return raycastHit.collider != null;
}
float dirX = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(dirX * 4f, rb.velocity.y);
isMoving = true;
float dirY = Input.GetAxisRaw("Vertical");
if (Input.GetKey("left ctrl"))
isRunning = true;
else
{
isRunning = false;
}
if (Input.GetKeyDown("left shift") && cooldown == false)
isDashing = true;
else
{
isDashing = false;
}
if (IsGrounded() && Input.GetButtonDown("Jump"))
{
rb.velocity = new Vector2(rb.velocity.x, 8f);
}
if (isRunning == true && isMoving == true)
{
rb.velocity = new Vector2(dirX * 6f, rb.velocity.y);
}
if (isDashing == true && cooldown == false)
{
dashingDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
if (dashingDir == new Vector2(0f,0f))
{
dashingDir = new Vector2(transform.localScale.x, 0f);
}
}
if (isDashing == true)
{
rb.velocity = dashingDir.normalized * dashingspeed;
return;
}
if (isDashing == true)
{
timewhiledashing -= 1 * Time.deltaTime;
}
if (timewhiledashing == 0f)
{
cooldown = true;
}
if (IsGrounded())
{
cooldown = false;
}
if (cooldown == true)
{
isDashing = false;
time -= 1 * Time.deltaTime;
}
if (time == 0f)
{
cooldown = false;
time = 4f;
timewhiledashing = 2f;
}
}
}
Please help me with this.

The reason your code is not dashing is because it detects if you get the key down, and if not it will be true again. So if you press the key, it will be true, then next frame it will be false.
This way, time while dashing will only go down for one frame.
Instead, you should use
if (Input.GetKey(KeyCode.LeftShift))

Related

I have a blank Unity object nested under the player. It's supposed to be tied to the front of the sprite but does not flip with the sprite

I've got my player sprite that has a blank "Front Check" object nested underneath it. The nested item is used to check if the front of the sprite is touching a wall. the problem I'm having is the Front Check object does not flip with the sprite when I move in the opposite direction. it was working fine earlier today and then out of the blue just quit. This is my first unity project and I'm just not quite sure what's missing. Any help is much appreciated. here is an image of the project and my movement script.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private Rigidbody2D rb;
private BoxCollider2D coll;
private SpriteRenderer sprite;
private Animator anim;
[SerializeField] private LayerMask jumpableGround;
public float checkRadius;
bool isTouchingFront;
public Transform frontCheck;
public float wallSlidingSpeed;
bool wallSliding;
bool wallJumping;
public float xWallForce;
public float yWallForce;
public float wallJumpTime;
private float dirX = 0f;
[SerializeField] private float moveSpeed = 7f;
[SerializeField] private float jumpForce = 14f;
[SerializeField] private float airControl;
private enum MovementState { idle, running, jumping, falling }
[SerializeField] private AudioSource JumpSoundEffect;
// Start is called before the first frame update
private void Start()
{
rb = GetComponent<Rigidbody2D>();
coll = GetComponent<BoxCollider2D>();
sprite = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
private void Update()
{
dirX = Input.GetAxisRaw("Horizontal");
if (dirX < 0 && IsGrounded())
{
rb.velocity = new Vector2(moveSpeed * -1, rb.velocity.y);
}
else if (dirX > 0 && IsGrounded())
{
rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
}
else if (dirX == 0 && IsGrounded())
{
rb.velocity = new Vector2(0, rb.velocity.y);
}
if (Input.GetButtonDown("Jump") && IsGrounded())
{
JumpSoundEffect.Play();
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
UpdateAnimationState();
}
private void UpdateAnimationState()
{
MovementState state;
if (dirX > 0f && IsGrounded())
{
state = MovementState.running;
}
else if (dirX < 0f && IsGrounded())
{
state = MovementState.running;
}
else
{
state = MovementState.idle;
}
if (rb.velocity.y > .1f)
{
state = MovementState.jumping;
}
else if (rb.velocity.y < -.1f)
{
state = MovementState.falling;
}
//Wall Jump
isTouchingFront = Physics2D.OverlapCircle(frontCheck.position, checkRadius, jumpableGround);
if (isTouchingFront == true && IsGrounded() == false && dirX != 0)
{
wallSliding = true;
}
else
{
wallSliding = false;
}
if (wallSliding)
{
rb.velocity = new Vector2(rb.velocity.x, Mathf.Clamp(rb.velocity.y, -wallSlidingSpeed, float.MaxValue));
}
if (Input.GetButtonDown("Jump") && wallSliding == true)
{
wallJumping = true;
Invoke("SetWallJumpingToFalse", wallJumpTime);
}
if (wallJumping == true)
{
rb.velocity = new Vector2(xWallForce * -Input.GetAxisRaw("Horizontal"), yWallForce);
}
anim.SetInteger("state", (int)state);
}
void SetWallJumpingToFalse()
{
wallJumping = false;
}
public bool IsGrounded()
{
return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, .1f, jumpableGround);
}
public void FixedUpdate()
{
if (dirX > 0f)
{
sprite.flipX = false;
}
else if (dirX < 0f)
{
sprite.flipX = true;
}
}
}
sprite.flipX only flips the rendering not the actual object scaling.
You rather want to use e.g.
var scale = transform.localScale;
scale.x = Mathf.Sign(dirX);
transform.localScale = scale;
Note that it needs to be UnityEngine.Mathf.Sign and not System.Math.Sign since the latter returns 0 for parameter 0 which would totally break your colliders etc. while Mathf.Sign returns only -1 or 1.

Unity2D - Verify if isGround is correctly

I have a script that detect when player is touching a layer named "Ground", and it works pretty well, but my problem is when I use the "Platform Effector 2D" that allows me jump through the plataform. So, when my character is passsing through the plataform, my bool "isGrounded" gets true, but he is actually not in ground, what happens is that the point that I use to check is "colliding" with the object that countains the layer Ground.
I don't think I can explain it very well, so I upload a not listed video on Youtube to show
www.youtube.com/watch?v=EQpF4iSNC0Yt
here's the code
[Header("Components")]
[HideInInspector]public Rigidbody2D _rb;
[Header("Layer Masks")]
[SerializeField] private LayerMask groundLayer;
[Header("Movement Variables")]
[SerializeField] private float _movementAcceleration;
[SerializeField] private float _maxMoveSpeed;
[SerializeField] private float _linearDrag;
[SerializeField] private float dashPower;
private float horizontalDirection;
private bool changingDirection => (_rb.velocity.x > 0f && horizontalDirection < 0f) || (_rb.velocity.x < 0f && horizontalDirection > 0f);
public bool isFalling => _rb.velocity.y < 0.0f;
private bool isRunning => horizontalDirection != 0;
[Header("Jump Variables")]
[SerializeField] private float jumpForce = 12f;
[SerializeField] private float airLinearDrag = 2.5f;
[SerializeField] private float fallMultiplier = 8f;
[SerializeField] private float lowJumpFallMultiplier = 5f;
private bool canJump => Input.GetButtonDown("Jump") && isGround;
[Header("Ground Colission Variables")]
[SerializeField] private float groundRayCastLenght;
private bool isGround;
private bool jumped;
private bool facinRight = true;
private Animator animator;
private SpriteRenderer sprite;
GameController controller;
public Transform groundCheck ;
public bool canPassThrough = false;
void Start()
{
sprite = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
_rb = GetComponent<Rigidbody2D>();
controller = FindObjectOfType<GameController>();
}
// Update is called once per frame
void Update()
{
Debug.Log(_rb.velocity.y);
isGround = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
horizontalDirection = GetInput().x;
if(canJump && !controller.gamePaused){
Jump();
}
if(Input.GetKeyDown(KeyCode.LeftShift)){
ApplyDash();
}
setAnimations();
}
void FixedUpdate()
{
//CheckCollisions();
if(!controller.gamePaused){
//checkDirection();
MoveCharacter();
}
if(isGround){
jumped = false;
ApplyLinearDrag();
}else{
ApplyAirLinearDrag();
FallMultiplier();
}
}
private Vector2 GetInput()
{
return new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
}
private void MoveCharacter(){
if(horizontalDirection < 0 && facinRight || horizontalDirection > 0 && !facinRight){
checkDirection();
}
Vector3 v = _rb.velocity;
_rb.AddForce(new Vector2(horizontalDirection* _movementAcceleration, 0f) );
if(Mathf.Abs(_rb.velocity.x) > _maxMoveSpeed){
v.x = Mathf.Sign(_rb.velocity.x) * _maxMoveSpeed;
_rb.velocity = v;
//_rb.velocity = new Vector2(Mathf.Sign(_rb.velocity.x) * _maxMoveSpeed, _rb.velocity.y );
}
}
private void CheckCollisions(){
isGround = Physics2D.Raycast(transform.position * groundRayCastLenght, Vector2.down, groundRayCastLenght, groundLayer);
}
private void ApplyLinearDrag(){
if(Mathf.Abs(horizontalDirection) < 0.4f || changingDirection){
_rb.drag = _linearDrag;
}else{
_rb.drag = 0f;
}
}
private void ApplyDash(){
_rb.AddForce(new Vector2(horizontalDirection * dashPower, _rb.velocity.y));
}
void ApplyAirLinearDrag(){
_rb.drag = airLinearDrag;
}
void Jump(){
jumped = true;
if(horizontalDirection != 0){
_rb.velocity = new Vector2(_rb.velocity.x, 0f);
_rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}else{
_rb.velocity = new Vector2(_rb.velocity.x, 0f);
_rb.AddForce(Vector2.up * jumpForce * 2f, ForceMode2D.Impulse);
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, transform.position + Vector3.down * groundRayCastLenght);
}
void FallMultiplier(){
if(_rb.velocity.y < 0){
_rb.gravityScale = fallMultiplier;
}else if(_rb.velocity.y > 0 && !Input.GetButtonDown("Jump")){
_rb.gravityScale = lowJumpFallMultiplier;
}else{
_rb.gravityScale = 1f;
}
}
void setAnimations(){
animator.SetBool("Run", isRunning && isGround);
animator.SetBool("isGround", isGround);
animator.SetBool("Jump", jumped);
animator.SetBool("isFalling", isFalling);
animator.SetFloat("eixoY", Mathf.Abs(_rb.velocity.y));
}
void checkDirection(){
facinRight = !facinRight;
transform.localScale = new Vector3( - transform.localScale.x, transform.localScale.y, transform.localScale.z);
}
void OnCollisionEnter2D(Collision2D other)
{
if(LayerMask.LayerToName(other.gameObject.layer) == "Ground") //check layer is ground
{
if (gameObject.GetComponent<Rigidbody2D>().velocity.y <= 0) //check velocity.y is 0
{
Debug.Log("in ground"); //debug console
canPassThrough = false;
}else{
Debug.Log("Not in ground");
canPassThrough = true;
}
}
}
If we want to perform the debug operation when we touch it, we can perform the operation successfully by checking that the velocity.y is 0 at the moment it touches.
like this:
private void OnCollisionEnter2D(Collision2D collision)
{
if(LayerMask.LayerToName(collision.gameObject.layer) == "Ground") //check layer is ground
{
if (gameObject.GetComponent<Rigidbody2D>().velocity.y <= 0) //check velocity.y is 0
{
Debug.Log("in ground"); //debug console
}
}
}

How can I fix my dash not working properly when jumping and how can I add a cooldown?

Recently I have been Frankensteining code I've found online together and I am struggling to implement the dash correctly. In its current state, whenever my character jumps and then uses his dash, he gets caught in the air as if the dash didn't move him. Obviously this inst intended and I was wondering how I could fix this. Also, how could I include a cool down system to my dash ability. I've tried using various sources for cool down scripts but they always seem to have a downside.
Thanks in advance!
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
//Player Movement
public float speed;
public float jumpForce;
public Transform feetPos;
public float checkRadius;
public LayerMask whatIsGround;
public float dashSpeed;
public float startDashTime;
private float timeStamp = 0;
public Animator animator;
private Rigidbody2D rb;
private float moveInput;
private bool isGrounded;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private float dashTime;
public int direction;
void Start()
{
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
}
void FixedUpdate()
{
moveInput = Input.GetAxisRaw("Horizontal");
if (direction < 1)
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
}
void Update()
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
// Dashing
if (direction == 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
else
{
if (dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
rb.velocity = Vector2.zero;
}
else
{
dashTime -= Time.deltaTime;
}
}
void Dashleft()
{
direction = 1;
rb.velocity = Vector2.left * dashSpeed;
}
void DashRight()
{
direction = 1;
rb.velocity = Vector2.right * dashSpeed;
}
}
}

How to deactivate bool var if nothing is pressed

I have a problem in my code. I have a sprite and when I click on it I rotate another object. That object i can move it left, right with the keyboard. The problem is that if you keep pressing LeftArrow and at the same time click to rotate it then the object continues to move to the left even if you do not click on anything.
private KeyboardEventSystem kBoard;
private Dictionary<KeyCode, bool> pressed = new Dictionary<KeyCode, bool>();
[ReadOnly] public bool moving;
[ReadOnly] public bool grounded = false;
void Start()
{
degeticaRb = GetComponent<Rigidbody2D>();
kBoard = gameObject.AddComponent<KeyboardEventSystem>();
kBoard.addKey(KeyCode.LeftArrow);
kBoard.addKey(KeyCode.RightArrow);
kBoard.addMap(KeyCode.A, KeyCode.LeftArrow);
kBoard.addMap(KeyCode.D, KeyCode.RightArrow);
pressed.Add(KeyCode.LeftArrow, false);
pressed.Add(KeyCode.RightArrow, false);
kBoard.KeyBoardEvent += KBoard_KeyBoardEvent;
}
private void KBoard_KeyBoardEvent(KeyboardEventType keyboardEventType, KeyCode keyCode)
{
if (!grounded)
return;
if (keyboardEventType == KeyboardEventType.DOWN)
pressed[keyCode] = true;
if (keyboardEventType == KeyboardEventType.UP)
{
moving = false;
pressed[keyCode] = false;
degeticaRb.angularVelocity = 0f;
degeticaRb.velocity = Vector3.zero;
}
}
public void DoRotation(int tIndex)
{
Vector3 rotAngle = transform.rotation.eulerAngles;
if (tIndex == 1)
{
rotAngle.z -= 90f;
transform.position = new Vector3(transform.position.x - 0.65f, transform.position.y);
}
else
{
rotAngle.z += 90f;
transform.position = new Vector3(transform.position.x + 0.65f, transform.position.y);
}
transform.eulerAngles = rotAngle;
}
private void FixedUpdate()
{
Collider2D[] colliders = Physics2D.OverlapCircleAll(Feet.position, 0.1f);
grounded = false;
foreach (Collider2D coll in colliders)
{
if (coll.tag == "wall")
{
grounded = true;
break;
}
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow))
{
moving = (pressed[KeyCode.LeftArrow] ^ pressed[KeyCode.RightArrow]);
if (moving && grounded)
{
moveAxis += pressed[KeyCode.RightArrow] ? accelaration : (accelaration * -1f);
moveAxis = Mathf.Clamp(moveAxis, -1, 1);
degeticaRb.velocity = new Vector2(moveAxis * moveSpeed, degeticaRb.velocity.y);
}
else
moveAxis = 0f;
}
else
moving = false;
DoMoveAnim();
}
So the bool variable moving remains active even if I do not press on anything. Help!
You need to manage your key states even if the object isn't grounded. The only things that care if it's grounded is setting moving = false and setting the velocities to zero:
private void KBoard_KeyBoardEvent(KeyboardEventType keyboardEventType, KeyCode keyCode)
{
if (keyboardEventType == KeyboardEventType.DOWN)
pressed[keyCode] = true;
if (keyboardEventType == KeyboardEventType.UP)
{
pressed[keyCode] = false;
if (grounded)
{
moving = false;
degeticaRb.angularVelocity = 0f;
degeticaRb.velocity = Vector3.zero;
}
}
}
Practically speaking, you may want to simply use Input.GetKey, Input.GetKeyUp and Input.GetKeyDown instead of managing the key state yourself.

Crouching issues in Unity

So I've created crouching in Unity 2D game, everything goes well except when there is something above the character after exiting crouching, what it does is that it returns to idle animation and decreases Y-axis position, I know that is normal but how can I keep the character crouched when there is something above him or when I hold the ctrl button? Check the script down below if necessary. Thanks!
private Rigidbody2D rb2d;
private float h = 0.0f;
public float Speed, Jump;
private bool canJump;
private Animator anim;
private BoxCollider2D bc2d;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
bc2d = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
transform.Translate(Vector3.right * h * Speed * Time.deltaTime);
if (h != 0.0f)
{
transform.localScale = new Vector2(h, transform.localScale.y);
}
if (Input.GetKeyDown(KeyCode.Space) && canJump == true)
{
rb2d.AddForce(new Vector2(rb2d.velocity.x, Jump));
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
bc2d.enabled = false;
Speed = Speed / 2;
anim.SetBool("Crouch", true);
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
bc2d.enabled = true;
Speed = Speed * 2;
anim.SetBool("Crouch", false);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = true;
anim.SetBool("Jump", false);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = false;
anim.SetBool("Jump", true);
}
}
Use RaycastHit2D. Basically before "standing" cast a ray Vector2.up from the character and if it hits, check to make sure there's enough room to stand. Something like:
private Rigidbody2D rb2d;
private Transform t;
private float h = 0.0f;
public float Speed, Jump;
private bool canJump;
private Animator anim;
private BoxCollider2D bc2d;
// Variable to check if character is attempting to stand
private bool tryingToStand = false;
// Keep crouching state
private bool isCrouching = false;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
bc2d = GetComponent<BoxCollider2D>();
t = GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxisRaw("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(h));
transform.Translate(Vector3.right * h * Speed * Time.deltaTime);
if (h != 0.0f)
{
transform.localScale = new Vector2(h, transform.localScale.y);
}
// Make sure we can jump and we're not crouching before jumping
if (Input.GetKeyDown(KeyCode.Space) && canJump == true && !isCrouching)
{
rb2d.AddForce(new Vector2(rb2d.velocity.x, Jump));
}
if (Input.GetKeyDown(KeyCode.LeftControl))
{
bc2d.enabled = false;
anim.SetBool("Crouch", true);
// Make sure we haven't already halved the speed
if (!tryingToStand)
{
Speed = Speed / 2;
}
// Set tryingToStand to false in case player holds ctrl before character has stood up
tryingToStand = false;
// Set crouching state to true
isCrouching = true;
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
tryingToStand = true;
}
if (tryingToStand && CanStand())
{
tryingToStand = false;
// Set crouching state to false;
isCrouching = false;
bc2d.enabled = true;
Speed = Speed * 2;
anim.SetBool("Crouch", false);
}
}
bool CanStand()
{
RaycastHit2D hit = Physics2D.Raycast(t.position, Vector2.up);
if (hit.collider != null)
{
// Check the distance to make sure the character has clearance, you'll have to change the 1.0f to what makes sense in your situation.
if (hit.distance <= 1.0f)
{
return false;
}
}
return true;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = true;
anim.SetBool("Jump", false);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.name == "Ground")
{
canJump = false;
anim.SetBool("Jump", true);
}
}

Categories

Resources