How to deactivate bool var if nothing is pressed - c#

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.

Related

Player's Dash abilty not isnt working correctly

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))

checking if grounded without using oncollision enter/exit?

so I have a script that rotates a cube (by 90 degrees when a direction is pressed) currently im using the oncollision enter to detect walls and when I try to use it to also check if grounded then it will just completely stop everything when i leave one collision and enter another, or it won't fully check when im in mid air and will allow me to move when i don't want to be able to. Any and all help is greatly appreciated.
{
bool isGrounded = true;
private Rigidbody2D rb;
bool leftInput = true;
bool rightInput = true;
public float RollingDuration = 0.2f;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// fixed update is for physics
void FixedUpdate()
{
var dir = Vector3.zero;
if (Input.GetKey(KeyCode.LeftArrow) && leftInput && isGrounded)
{
dir = Vector3.left;
}
if (Input.GetKey(KeyCode.RightArrow) && rightInput && isGrounded)
{
dir = Vector3.right;
}
if (dir !=Vector3.zero && !isRolling)
{
StartCoroutine(Roll(dir));
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
//check to see if our player is grounded
if (collision.gameObject.tag == "Grounded")
{
isGrounded = true;
}
if (collision.gameObject.tag == "LeftWall" || collision.gameObject.tag == "RightWall")
{
StopCoroutine("Roll");
if (collision.gameObject.tag == "LeftWall")
{
leftInput = false;
// we are grounded when touching walls
isGrounded = true;
}
if (collision.gameObject.tag == "RightWall")
{
rightInput = false;
// we are grounded when touching walls
isGrounded = true;
}
if (collision.gameObject.tag == null)
{
isGrounded = false;
}
else
{
isRolling = false;
rb.velocity = Vector2.zero;
rb.velocity = new Vector2(0.0f, 0.0f);
rb.angularVelocity = 0.0f;
rb.transform.rotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
rb.rotation = 0.0f;
}
}
}
bool isRolling = false;
IEnumerator Roll(Vector3 direction)
{
if (direction == Vector3.right && isGrounded)
{
leftInput = true;
}
else if (direction == Vector3.left && isGrounded)
{
rightInput = true;
}
isRolling = true;
var rotAxis = Vector3.Cross(Vector3.up, direction);
var pivot = (rb.transform.position + Vector3.down * 0.5f) + direction * 0.5f;
var startRotation = rb.transform.rotation;
var endRotation = Quaternion.AngleAxis(90.0f, rotAxis) * startRotation;
var startPosition = rb.transform.position;
var endPosition = rb.transform.position + direction;
var rotSpeed = 90.0f / RollingDuration;
var t = 0.0f;
while (t < RollingDuration && isGrounded)
{
t += Time.deltaTime;
if (t < RollingDuration && isGrounded)
{
rb.transform.RotateAround(pivot, rotAxis, rotSpeed * Time.deltaTime);
yield return null;
}
else
{
rb.transform.rotation = endRotation;
rb.transform.position = endPosition;
}
}
isRolling = false;
}
}
I think the most simple and common way to do ground checks is with casting a ray. So just cast a ray into the direction you want to check or try Overlap functions.
Example:
if(Physics.OverlapCircle(point, radius, layerMask)) {
//do stuff
}
So just cast a ray in all direction you want to check or add a overlap function to each side of the cube.

How to prevent any player Input if the object is moving

I am creating a clone of Billiards and I cannot work out how to stop the player from interacting with and launching the ball while it is still moving; below is my attempt. I have placed an if statement that checks whether the ball is moving on both the mouseDrag and mouseUp functions. I have also tried using isSleeping() but this caused the ball to not move at all.
If possible I would like to apply this method to all of the balls and not just the cue ball; so that all balls have to have stopped before any actions may happen. This is currently in my "player" script, if I should move it a GameManager script please let me know.
private void Update()
{
speed = rb.velocity.magnitude;
if (speed < 0.5)
{
rb.velocity = new Vector3(0, 0, 0);
}
}
void OnMouseDrag()
{
if (speed == 0)
{
mousePointB.GetComponent<SpriteRenderer>().enabled = true;
currDistance = Vector3.Distance(mousePointA.transform.position, transform.position);
if (currDistance <= 3f)
{
spaceLimit = currDistance;
}
else
{
spaceLimit = maxDistance;
}
shootPower = Mathf.Abs(spaceLimit) * shootPowervar;
Vector3 dimxy = mousePointA.transform.position - transform.position;
float difference = dimxy.magnitude;
mousePointB.transform.position = transform.position + ((dimxy / difference) * currDistance * -1);
mousePointB.transform.position = new Vector3(mousePointB.transform.position.x, mousePointB.transform.position.y, -0.8f);
shootDirection = Vector3.Normalize(mousePointA.transform.position - transform.position);
}
else
{
}
}
void OnMouseUp()
{
if (speed == 0)
{
mousePointB.GetComponent<SpriteRenderer>().enabled = false;
arrow.GetComponent<SpriteRenderer>().enabled = false;
circle.GetComponent<SpriteRenderer>().enabled = false;
Vector3 push = shootDirection * shootPower * -1;
GetComponent<Rigidbody2D>().AddForce(push, ForceMode2D.Impulse);
}
else
{
}
}
if your test speed == 0 is not functional, you could record the last position of the ball, and set a boolean isMoving = true, if actual position of ball is different thant the last, then record the lastposition and so on
Vector3 LastPosition;
bool isMoving;
void Update()
{
isMoving = BallPosition == LastPosition;
:
:
}
void OnMOuseDrag()
{
if(!isMoving) return;
}
void OnMOuseUp()
{
if(!isMoving) return;
}

How do I stop the player partly going through ground

I made a controller for a 2d character, I fixed the issue of the player jittering through the wall but I cant fix the player jittering through the ground. Got this code from multiple tutorials and tweaking stuff. If you have any tips that would be greatly appreciated I'm new to this stuff and working on my first game (had to ramble cuz I put too much code) thanks.
{
public float speed, height;
Rigidbody2D rb;
private bool horizontalRight = false;
private bool horizontalLeft = false;
private bool verticalMove = false;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetAxisRaw("Horizontal") > 0)
{
horizontalRight = true;
}
else if (Input.GetAxisRaw("Horizontal") < 0)
{
horizontalLeft = true;
}
if (Input.GetButton("Jump") && rb.velocity.y == 0)
{
verticalMove = true;
}
}
private void FixedUpdate()
{
if (horizontalRight == true)
{
transform.Translate(Vector2.right * Time.deltaTime * speed);
horizontalRight = false;
}
else if (horizontalLeft == true)
{
transform.Translate(Vector2.left * Time.deltaTime * speed);
horizontalLeft = false;
}
if (verticalMove == true)
{
rb.velocity = new Vector2(0, height);
verticalMove = false;
}
}
}
Activate continuous collision detection on your rigid bodies, it'll keep them from phasing through things so long as they're being moved via their velocity.
A typical jump in unity would look like:
void Jump()
{
if (_isGrounded == true)
{
rb.AddForce(Vector2.up * _jumpSpeed);
_isGrounded = false;
}
}
and in collision event
void OnCollisionEnter (Collision hit)
{
_isGrounded = true;
}
this would limit when you can use a jump.

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