Unity Cant jump and move on the same time - c#

Hello and thanks for reading this.
I made a little game in Unity and I finally got the movement controls with touch input to work.
But right now I face a little problem with combining the movement and jumping part. I cant jump if I'm moving BUT I can move if I'm jumping.
Each of my arrow keys contain a script and then later calls the "RobotController" script to start the movement.
ArrowRight and ArrowLeft Script. They look very much alike so I'll only post 1:
private RobotController PlayermoveRight;
// Use this for initialization
void Start () {
PlayermoveRight = GameObject.Find("Player").GetComponent<RobotController>();
}
void OnMouseOver()
{
if(Input.touchCount >= 1)
{
var touchr = Input.touches[0];
if(touchr.phase != TouchPhase.Ended && touchr.phase != TouchPhase.Canceled)
{
PlayermoveRight.MoveRight();
}
else
{
}
}
}
The ArrowUp script:
void OnMouseOver()
{
GameObject Go = GameObject.Find("Player");
if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) || (Input.GetMouseButtonDown(0)))
{
Go.GetComponent<RobotController>().Jump();
}
}
And the RobotController script:
public double moveTime = 0.1;
public double moveTimeR = 0.1;
private double lastPressedTime = 0.0;
private double PressRight = 0.0;
public void MoveLeft() // If ArrowLeft is clicked or Pressed
{
lastPressedTime = Time.timeSinceLevelLoad;
}
public void MoveRight() // If ArrowRight is clicked or Pressed
{
PressRight = Time.timeSinceLevelLoad;
}
void FixedUpdate () {
if (PressRight + moveTimeR > Time.timeSinceLevelLoad)
{
rigidbody2D.velocity = new Vector2 (maxSpeed, rigidbody2D.velocity.y);
}
else if (lastPressedTime + moveTime > Time.timeSinceLevelLoad)
{
rigidbody2D.velocity = new Vector2 (maxSpeed - maxSpeed - maxSpeed, rigidbody2D.velocity.y);
}
else
{
rigidbody2D.velocity = new Vector2(0.0f, rigidbody2D.velocity.y);
}
}
public void Jump()
{
if (isOnGround == true) {
anim.SetBool("Ground",false);
rigidbody2D.AddForce (new Vector2 (0, jumpForce));
}
}
How can I do so I can jump and move on the same time.?

from the up arrow code:
(Input.GetTouch(0).phase == TouchPhase.Began) || (Input.GetMouseButtonDown(0))
you're checking if the first touch has just started, if you are holding down a move arrow and you tap up to jump the "jump touch" isn't the first touch and the first touch (for the movement) isn't in it's began phase.
The reason it works with hitting jump and then moving is because the first touch in that case is the jump touch (by coincidence rather than by code).
You don't want to check against the first touch here, you want to check against the touch that is over the up arrow.
(not sure how you'd actually do that, but I can't comment until I get 50 rep :( )

I am also a newbie and was facing this problem few hours ago but I fixed it as I was told to do in an video tutorial so the fix was: Add some drag to your player, in the inspector there is a "Linear Drag" option in your rigidBody component increase it by 0.3(0 is the default value) this really fixed my problem I hope it will also help you(I know it is really late but I just found your question while googling my problem).

Related

OverlapBox sometimes not working as expected, Unity 2d

I am using an overlap box to detect whether an arrow hits the ground or an enemy, the arrow hitting the enemy works, it's that often the arrow will just pass through the ground, not sure if I am missing something.
Heres my code for detecting the ground or enemy.
private void FixedUpdate()
{
damageHit = Physics2D.OverlapBox(damagePosition.position, damageSize, whatIsEnemy);
groundHit = Physics2D.OverlapBox(damagePosition.position, damageSize, whatIsGround);
if (!hasHitGround)
{
if (damageHit)
{
Collider2D[] detectedObjects = Physics2D.OverlapBoxAll(damagePosition.position, damageSize, whatIsEnemy);
foreach (Collider2D collider in detectedObjects)
{
IDamageable damageable = collider.GetComponent<IDamageable>();
if (damageable != null)
{
damageable.Damage(weaponData.attackDamage);
Destroy(gameObject);
}
IKnockbackable knockbackable = collider.GetComponent<IKnockbackable>();
if (knockbackable != null)
{
knockbackable.KnockBack(weaponData.knockbackAngle, weaponData.knockbackStrength, (int)Mathf.Sign(transform.rotation.y));
}
}
}
if (groundHit)
{
rb.gravityScale = 0f;
rb.velocity = Vector2.zero;
hasHitGround = true;
Destroy(gameObject, 10f);
}
else if (Mathf.Abs(xStartPos - transform.position.x) >= travelDistance && !isGravityOn)
{
isGravityOn = true;
rb.gravityScale = gravity;
}
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireCube(damagePosition.position, damageSize) ;
}
I thought that the hitbox may have been to small and it would just pass through wall due to not hitting it on any frame. After making the hitbox larger it still did not help, here you can see that even though the overlap box is overlaping the collider the arrow will continue on.

Make Character Able To Turn Back and Fourth in Unity

I was trying to code a system where a 2D character's sprite and collider turn to face the direction being input (i.e. pressing the left key makes the character face left, pressing the right key makes the character turn right). I had this script and it seemed to work for a while:
public bool turnedAround = false; //Says if you are facing to the left (true) or right (false)
[SerializeField]
private float xVelocityTolerance = .6f; //The slowest the player's X can move at to have the running animation show
[SerializeField]
private float groundDetectionOffset = .3f; //How far the raycast origin is offset
private Animator anim;
private Rigidbody2D rb;
private PlayerController playerController;
public float HalfPlayerHeight
{
get
{
return playerController.halfPlayerHeight;
}
}
private bool IsOnGround() //Checks if there is ground below the outside to the left, middle, and outside to the right
{
return Physics2D.Raycast(transform.position - new Vector3(groundDetectionOffset, 0f, 0f), -transform.up, HalfPlayerHeight) || Physics2D.Raycast(transform.position, -transform.up, HalfPlayerHeight) ||
Physics2D.Raycast(transform.position + new Vector3(groundDetectionOffset, 0f, 0f), -transform.up, HalfPlayerHeight); //Uses an artificial line break
}
void Start()
{
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
playerController = GetComponent<PlayerController>();
}
// Update is called once per frame
void Update()
{
//NOTE ABOUT WHOLE SECTION OF IS ELSE: The if checks if the player's facing right and moving left. If it is then it turns left and changes turnedAround to be true which means it is facing left. The else if is the opposite
if (rb.velocity.x < -xVelocityTolerance && !turnedAround)
{
transform.Rotate(0, 180, 0);
turnedAround = true;
}
else if (rb.velocity.x > xVelocityTolerance && turnedAround)
{
transform.Rotate(0, -180, 0);
turnedAround = false;
}
/*NOTE ABOUT WHOLE SECTION OF IS ELSE: The if checks if the player is moving either left and right fatser than the VelocityTolerance and if the player isn't jumping/falling.
If true it will tell the animator by setting IsRunningNotJumping to true. If it it false it will be set to false.*/
if ((rb.velocity.x > xVelocityTolerance || rb.velocity.x < -xVelocityTolerance) && IsOnGround() && !anim.GetBool("IsRunningNotJumping"))
{
anim.SetBool("IsRunningNotJumping", true);
}
else if (anim.GetBool("IsRunningNotJumping"))
{
anim.SetBool("IsRunningNotJumping", false);
}
//NOTE ABOUT WHOLE SECTION OF IS ELSE: The if statement checks if the player is jumping/falling. If they are than it will tell the animator by setting IsJumpingOrFallling to true and vice versa with the else.
if (!IsOnGround() && !anim.GetBool("IsJumpingOrFalling"))
{
anim.SetBool("IsJumpingOrFalling", true);
}
else if (IsOnGround() && anim.GetBool("IsJumpingOrFalling"))
{
anim.SetBool("IsJumpingOrFalling", false);
}
if (Fireballs.HasFireballs != anim.GetBool("HasFireballs"))
{
anim.SetBool("HasFireballs", Fireballs.HasFireballs); //Sets the HasFireballs bool in the animator equal to the HasFireball bool in the Fireballs script
}
if (BonusLife.hasBonusLife != anim.GetBool("HasBonusLife"))
{
anim.SetBool("HasBonusLife", BonusLife.hasBonusLife); //Sets the HasBonusLife bool in the animator equal to the HasBonusLife bool in the BonusLife script
}
if (SpawnFireballs.isThrowing != anim.GetBool("IsThrowing"))
{
anim.SetBool("IsThrowing", SpawnFireballs.isThrowing); //Sets the IsThrowing bool in the animator equal to the IsThrowing bool in the SpawnFireballs script
}
}
}
(rb = RigidBody2d)
However, for some reason now when I try to walk in one direction the TurnedAroud bool would constantly switch on and off and the player would be unable to move except in weird and unexpected ways. How can I fix this? I am open to different ways of making the Player face the correct direction.
I am coding in c# in Unity 2020.3.24f1 using visual studio. I am new to stack exchange so if I asked this question wrong I am sorry.

Touch screen, how to tweak my code to react to only one finger

I'm trying to add limited touch screen controls to my game for my android phone. I keep seeing all these tutorials but I'm just not getting one of the simple parts, at least i think it's simple. On my phone, when you tap it with your finger, I have a truck that goes left. When I tap it again, I want it to right. Every time you tap the screen, it's supposed to go in the other direction, alternating between left and right. It soooort of works now but not really. When you tap it the first time, it goes left. But in order to make it go right, you have to hold the screen down with one finger and then touch it with the second finger. I just want it to react to only one finger at a time so that you can play it with one hand. So here's my code. What am I doing wrong? How do I fix it? Thank you all in advance.
tried getting rid of the returns. Tried tweaking the existing code and adding other things in there based on other tutorials.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class playerController : MonoBehaviour {
private Rigidbody rb;
private Animator anim;
private bool left = false;
private bool right = false;
public static bool detect = false;
public float yspeed; //left or right from camera's vp
public float xSpeed = 55f; //down the road from camera's vp
[HideInInspector]
public bool crash = false;
public int slowSpeed;
private float respawnTimer = 3f;
void Start () {
rb = GetComponent<Rigidbody> ();
anim = GetComponent<Animator> ();
rb.velocity = new Vector3 (xSpeed, rb.velocity.y, rb.velocity.z);
}
void Update () {
Movement ();
Halt ();
}
public void Movement()
{
if (crash) {
left = false;
right = false;
scoreManager.scoreValue = 0;
}
detect = false;
if (Input.touchCount > 0 && !left) {
foreach (Touch touch in Input.touches) {
rb.velocity = new Vector3 (rb.velocity.x, yspeed, 0);
left = true;
right = false;
return;
}
}
if (Input.touchCount > 0 && !right) {
foreach (Touch touch in Input.touches) {
rb.velocity = new Vector3 (rb.velocity.x, -yspeed, 0);
right = true;
left = false;
return;
}
}
}
void OnTriggerEnter (Collider other)
{
if (!crash && other.gameObject.tag == ("wall")) {
crash = true;
anim.SetTrigger ("crash");
}
}
public void Halt()
{
if (crash && slowSpeed > 0) {
rb.velocity = new Vector3 (--slowSpeed, 0, 0);
Invoke ("Restart", respawnTimer);
}
}
public void Restart ()
{
Application.LoadLevel ("scene_01");
}
}
As you press and hold, you will notice that it will swap left & right every frame you're touching the screen. Consider using TouchPhase for more refined input. Try this:
...
if (Input.touchCount > 0 && Input.touches[0].phase == TouchPhase.Began) {
if(right) {
rb.velocity = new Vector3 (rb.velocity.x, yspeed, 0);
left = true;
right = false;
} else if (left) {
rb.velocity = new Vector3 (rb.velocity.x, -yspeed, 0);
right = true;
left = false;
}
}
...
See deployed code on an Android device:
I figured it out and it's so stupid. I just had to update my phone and use fire1 and fire2 as if it were mouse controls, which is what i originally had it as. When I updated my phone, the touchCount arguments didn't react AT ALL to my phone so I tried one of my earlier versions when I was still having it work just for PC. This is the code that works for me now.
if (Input.GetButtonDown ("Fire1") && !left){
rb.velocity = new Vector3 (rb.velocity.x, yspeed, 0);
left = true;
right = false;
return;
}
if (Input.GetButtonDown ("Fire1") && left){
rb.velocity = new Vector3 (rb.velocity.x, -yspeed, 0);
right = true;
left = false;
return;
}

Jump height in relation to timeheld of spacebar

This has been asked before, but none of the answers solved my problem because the problem was always slightly different.
I have a character that jumps on spacebar down. I want it to make higher jumps when the spacebar is pressed longer, with a maximum of twice the normal jump height.
Here's what I came up with so far:
void FixedUpdate () {
if (Input.GetKeyDown(KeyCode.Space) && myRB.velocity.y == 0)
{
timeHeld = 1;
}
if (Input.GetKey(KeyCode.Space) && myRB.velocity.y == 0)
{
myRB.AddForce(Vector3.up * 20,ForceMode2D.Impulse);
timeHeld += Time.deltaTime;
myRB.mass = myRB.mass - timeHeld/10;
}
if (Input.GetKeyUp(KeyCode.Space))
{
myRB.mass = 1;
}
}
Since the jump has to happen on keydown (not keyup), I can't increase the force added on jump, because the force is already applied on keydown. Therefore, I was thinking of lowering the mass of my rigidbody.
The above code "works" if I keep holding spacebar: the character jumps (minimum height), lands, jumps again but now a bit higher, etc. But that's not what I'm looking for, obviously.
This can easily be done by making a Time frame in which Jumping occurs;
Within this time frame u allow upward forces to be applied by holding space bar down. As soon as you reach either the end of the time frame or the end of the button press; you restrict upward velocity until the character has landed.
Let gravity take its own course after you end the jump.
As for the coding part i suggest you start a co routine when the jump happens.
here is some code to u help you get started;
IEnumerator Jumper()
{
if (maxjumpduration!=jumpduration)
{
jumpduration = jumpduration + 0.1f;
yield return new WaitForSeconds(0.1f);
}
else
{
jumpduration = 0;
StopCoroutine(Jumper());
}
}
As for the fact you want have a regular jump as well; make another time frame in which is decided if the press of space bar is considered either a regular jump or a controlled jump; During that initial time frame in which you are still deciding what kind of jump it is; you execute a short part of the jump until you reach a conclusion and then you send it to the correct method.
I added Some ground work for u but try to finish the code yourself;
{
private bool shortjump = false;
private bool checkphase = false;
private bool hitground = false;
private Rigidbody player = new Rigidbody();
private bool jumping = false;
Vector3 sharedjumpforce = new Vector3();
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Initialjump();
}
if (Input.GetKeyUp(KeyCode.Space))
{
if (jumping)
{
shortjump = true;
}
}
if (jumping)
{
if (hitground)
{
jumping = false;
}
}
}
void Initialjump()
{
if (jumping = false)
{
checkphase = true;
jumping = true;
player.AddForce(sharedjumpforce);
Invoke("Standardorcontrolledjump", 0.2f);
}
}
void Standardorcontrolledjump()
{
checkphase = false;
if (shortjump)
{
}
else
{
}
}
}
I don't understand why are you putting
&& myRB.velocity.y == 0
You want it to reduce its mass while in air don't you. Assuming that reducing the mass after the initial force has been applied does allow the Rigidbody to go higher, (force of gravity weakens, im not sure if that happens in Unity)
Why don't you try this
void FixedUpdate () {
// apply force the instant button is pressed. That is only once
if (Input.GetKeyDown(KeyCode.Space) && myRB.velocity.y == 0)
{
myRB.AddForce(Vector3.up * 20,ForceMode2D.Impulse);
timeHeld = 1;
}
// keep subtracting from mass while its held
if (Input.GetKey(KeyCode.Space))
{
timeHeld += Time.deltaTime;
myRB.mass = myRB.mass - timeHeld/10;
}
if (Input.GetKeyUp(KeyCode.Space))
{
myRB.mass = 1;
}
}

How to check if a touch in Unity is being moved back and forth within a range?

I am trying to figure out how to detect when a touch is being moved back and forth in Unity.
so as the image shows, I am looking for a way to detect when the touch moves from its starting position (1) to the second x (2), then back to somewhere near the starting position (3) all with a certain speed and within a time frame, essentially something like a shaking gesture. Im really stuck as to how to do this. Any help will be greatly appreciated.
an illustration of what I mean
so far I just know how to get the starting position with a touch.
Vector2 startingPos;
float shakeTime = 2f;
void Update()
{
foreach(Input.touch touch in Input.touches)
{
if(touch.phase == TouchPhase.Began)
{
startingPos = touch.position;
}
}
}
float touchTimer=0f;
float shakeTime = 2f;
float moveAwayLimit = 1f;
float moveBackLimit = .5f;
bool awayReached = false;
Vector2 startingPos;
void Update()
{
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
startingPos = touch.position;
touchTimer = 0;
awayReached = false;
}
if (Vector2.Distance(touch.position, startingPos) > moveAwayLimit && touchTimer < shakeTime && !awayReached)
{
awayReached = true;
}
else if (Vector2.Distance(touch.position, startingPos) < moveBackLimit && touchTimer < shakeTime && awayReached)
{
Shake();
}
touchTimer += Time.deltaTime;
}
}
Something like this should work, it checks if you move away further than moveAwayLimit from the start, and after that if you're within moveBackLimit from the startingPos.

Categories