I am trying to do a simple object movement but when I use two arrow keys at the same time, I get a problem after I release one key and press it again.
Example Assume that I am pressing UpArrow and RightArrow at the same time. Object moves in that ways. However, if I release one of them, the object stops.
Here is the code. Btw I know what causes the error but if I delete that part, I don't know how else do I stop the object when I release a button.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class objectControl : MonoBehaviour
{
[SerializeField] float obecjtSpeed = 500f;
void Update()
{
movementFunction();
movementStopFunction();
}
void movementFunction()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (obecjtSpeed*Time.deltaTime,0) GetComponent<Rigidbody2D>().velocity;
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (-obecjtSpeed*Time.deltaTime,0) GetComponent<Rigidbody2D>().velocity;
}
if (Input.GetKeyDown(KeyCode.UpArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (0,obecjtSpeed*Time.deltaTime) GetComponent<Rigidbody2D>().velocity;
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (0,-obecjtSpeed*Time.deltaTime) GetComponent<Rigidbody2D>().velocity;
}
}
void movementStopFunction()
{
if (Input.GetKeyUp(KeyCode.RightArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (0, 0);
}
if (Input.GetKeyUp(KeyCode.LeftArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (0, 0);
}
if (Input.GetKeyUp(KeyCode.UpArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (0, 0);
}
if (Input.GetKeyUp(KeyCode.DownArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (0, 0);
}
}
}
CodePudding user response:
First of all, there is no need to multiply by deltaTime when assigning a velocity. Velocity is the speed of the object, not the distance it will move this frame. So you should drop the multiplication by Time.deltaTime inside movementFunction
, like this:
if (Input.GetKeyDown(KeyCode.RightArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (obecjtSpeed,0) GetComponent<Rigidbody2D>().velocity;
}
Repeat for the other directions. Now, movementStopFunction
assigns the velocity to 0 on both axes, so there's no wonder it stops objects completely. You want it to only undo the effect of the buttons that have been lifted. In other words, it should be the reverse of movementFunction
. So all you need to do is take movementFunction
and flip every positive into a negative, and vice versa. For example:
if (Input.GetKeyUp(KeyCode.RightArrow))
{
GetComponent<Rigidbody2D>().velocity = new Vector2 (-obecjtSpeed,0) GetComponent<Rigidbody2D>().velocity;
}
Note that obecjtSpeed
turned into -obecjtSpeed
. Repeat this process for the other buttons.
That solves your immediate problem, but there's still much to improve here. I don't want to overwhelm you, so I'll just leave you with some points without elaborating too much:
- Now that
movementFunction
andmovementStopFunction
are so similar, consider generalizing them into a single function to avoid code repetition - Consider caching the Rigidbody on Start instead of calling GetComponent so much
- Even with my suggestions, this code breaks if there is anything other than this script which can change the object's velocity, like collisions or friction
- Usually, you'd want acceleration to be part of your movement script rather than instantly assigning the maximum speed
- The object's speed can exceed
obecjtSpeed
if the player presses two arrows at once (like up and right, not up and down). Some games consider that a feature, it's up to you