Physics2D.OverlapBox shows inconsistent behaviour - unity3d

Recently I started working with Unity, this is the first time I'm trying to build a 2d platformer.
For some reason, when I press the jump button, there is a random chance that it will actually make the player jump. Probably around 1 in 50 that it actually jumps.
I just can't figure out why its doing that. Do you know what I'm doing wrong here?
using UnityEngine;
public class Player : MonoBehaviour
{
public float movespeed = 5f;
public float jumpforce = 5f;
public Rigidbody2D player;
public LayerMask layerMaskPlatforms;
private float movementHorizontalInput;
private bool jumpInput;
private float lastTimeOnGroundInSeconds = 0f;
private float lastTimePressedJump = 0f;
void OnBecameInvisible()
{
// todo: restart game
}
void Update()
{
movementHorizontalInput = Input.GetAxisRaw("Horizontal");
jumpInput = Input.GetButtonDown("Jump");
}
void FixedUpdate()
{
if (jumpInput)
{
AttemptJump();
lastTimePressedJump = 0.2f;
}
else if (lastTimePressedJump > 0)
{
AttemptJump();
lastTimePressedJump -= Time.deltaTime;
}
if (IsOnGround())
{
lastTimeOnGroundInSeconds = 0.2f;
}
else if (lastTimeOnGroundInSeconds > 0)
{
lastTimeOnGroundInSeconds -= Time.deltaTime;
}
player.velocity = new Vector2(movementHorizontalInput * movespeed * Time.deltaTime * 50f, player.velocity.y);
}
private void AttemptJump()
{
if (lastTimeOnGroundInSeconds > 0)
{
player.AddForce(new Vector2(0, jumpforce), ForceMode2D.Impulse);
lastTimeOnGroundInSeconds = 0;
}
}
private bool IsOnGround()
{
Vector2 groundedCheckPosition = (Vector2)transform.position + new Vector2(0, -0.01f);
var overlapBox = Physics2D.OverlapBox(groundedCheckPosition, transform.localScale, 0, layerMaskPlatforms);
return overlapBox;
}
}

One major issue is that the jump input is being polled every frame (Update), but the jump code is done every several frames (FixedUpdate), so if you press jump, it is most likely the FixedUpdate method will never see that jump, explaining why it happens so rarely.
You'd need to save the jump state (maybe in a boolean), so by the time Fixed Update happens, it knows that that a jump occurred. Then set that jump to false, and do the jump logic.

Related

Trying to get reversed movement on collision on Unity2

so I am trying to make a shooting machine that shoots bullet and bullet gets back from the same way it went through when hitting the wall without speeding up and without changing angle (just the opposite way)
i added force and tried many ways but nothing works , please help
here is my code (the last one) even though i normalized the force but i still feel like its speeding up
public Rigidbody2D rb;
private float bulletForce = 20f;
private bool collided;
Vector2 dir;
private void Awake()
{
instance = this;
rb = gameObject.GetComponent<Rigidbody2D>();
dir = transform.up;
}
void Update()
{
rb.AddForce(dir.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Edge"))
{
dir = Vector2.Reflect(rb.position, other.contacts[0].normal);
rb.velocity = dir.normalized * bulletForce;
transform.up = dir.normalized;
}
}
this is wanted results explanation
this is current results explanation
If you just want to exactly invert the direction than
rb.velocity = -rb.velocity;
transform.up = rb.velocity;
and of course it is speeding up since you constantly add force in
void Update()
{
rb.AddForce(dir.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
why don't you just disable any friction for this bullet and set an initial velocity once?
public class CollideReflector : MonoBehaviour
{
[SerializeField] Rigidbody2D rb;
[SerializeField] Vector2 direction;
[SerializeField] float bulletForce = 20f;
[SerializeField]float smooth;
private bool collided;
// STARTER
private void Awake()
{
instance = this;
rb = gameObject.GetComponent<Rigidbody2D>();
direction = transform.up;
}
void Update()
{
rb.AddForce(direction.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Edge"))
{
var x = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
Quaternion target = -x;
transform.rotation = Quaternion.Slerp(transform.rotation, x, Time.deltaTime * smooth);
rb.AddForce(-direction.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
}
}

Unity: Input.GetButtonDown is not reliably detected in Update?

I have a player script that I'm trying to implement jumping in. The problem is that Input.GetButtonDown("Jump") doesn't consistently fire in Update. I know this is a problem when it's in FixedUpdate. Here is my code.
Note: I put [SerializeField] on pressingJump and holdingJump so I could see what's happening. pressingJump is inconsistent (as expected) but holdingJump works perfectly.
using UnityEngine;
public class Player : MonoBehaviour
{
public float fallMultiplier = 15f;
public float lowJumpMultiplier = 10f;
public float walkSpeed = 20f;
public float jumpSpeed = 15f;
public bool canMove = true;
public bool canJump = true;
Rigidbody rb;
float horizontalInput;
bool doJump;
bool pressingJump;
bool holdingJump;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
CaputureInput();
}
void CaputureInput()
{
if (canMove) {
horizontalInput = Input.GetAxisRaw("Horizontal");
}
pressingJump = Input.GetButtonDown ("Jump");
doJump = pressingJump && canJump;
holdingJump = Input.GetButton ("Jump") && canJump;
}
void FixedUpdate()
{
Move();
Jump();
}
void Move()
{
rb.velocity = new Vector2(horizontalInput * walkSpeed, rb.velocity.y);
}
void Jump()
{
if (doJump) {
rb.velocity += Vector3.up * jumpSpeed;
doJump = false;
}
if (rb.velocity.y < 0) {
rb.velocity += Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
} else if (rb.velocity.y > 0 && !holdingJump) {
rb.velocity += Vector3.up * Physics.gravity.y * (lowJumpMultiplier - 1) * Time.deltaTime;
}
}
}
Ok found the solution here: https://www.reddit.com/r/Unity3D/comments/9nr2sd/inputgetbuttondown_and_getbuttonup_dont_work/e7ogta1?utm_source=share&utm_medium=web2x
This was the problem I was having.
Edit: Comment pointed out a link might not be accepted. Here is the relevant content from link. It points out why the issue is occurring and how to fix it.
What you end up with, with the code you've written, is essentially the
same as when you do input checking in FixedUpdate.
This is because Update runs several times in between every
FixedUpdate. Now, what this means for your code in this case is that
yes, you do capture the state of ButtonDown("Jump") during Update, but
think about this: what happens to button_down/up_jump if another
Update happens before a FixedUpdate? Both GetButtonDown and
GetButtonUp are functions that are true only for the one frame in
which the keypress/-release happened. In other words, this is
happening
Update runs -> button_down_jump is false
user presses "Jump".
Update runs -> button_down_jump is true
Update runs -> button_down_jump is false
FixedUpdate runs -> nothing happens, because of button_down_jump's
state
Now, you've actually had a few cases where you press/unpress "jump" at
just the right time to manage to get anything printed at all. This
will only happen given that the following happens:
User un-/press "jump"
Update runs (ONCE)
FixedUpdate runs
What you actually want to do is something like this:
void Update() {
if(Input.GetButtonDown("jump")) {
button_down_jump = true; //this captures the state of the boolean beyond the one frame, as it's only set whenever the input
event happens
}
if(Input.GetButtonUp("jump")) {
button_up_jump = true;
} }

How to optimize jump like in Flappy Bird in Unity?

I can write somehow this code for optimization?
If not use coroutines, when I click on space the next jump has more force and so on.
If use rb.MovePosition, the character will move as if 15 fps. I know, change Time in settings. But I want to know if exist another method...
private void Update() {
if(Input.GetKeyDown(KeyCode.Space)) {
StopAllCoroutines();
StartCoroutine(Jump());
}
}
private IEnumerator Jump() {
if(rb.bodyType != RigidbodyType2D.Dynamic) {
rb.bodyType = RigidbodyType2D.Dynamic;
}
rb.constraints = RigidbodyConstraints2D.FreezePositionY;
_pos = transform.position;
for (float t = 0; t < 1; t += Time.deltaTime * 4f)
{
transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x, _pos.y + .35f, transform.position.z), t);
yield return null;
}
rb.constraints = RigidbodyConstraints2D.None;
}
Rigidbodies exist so you don't need to directly adjust an object's transform. Since you have a Rigidbody2d you can just set the velocity directly:
public float jumpSpeed = 5f; // Whatever feels right
private void FixedUpdate() {
if(Input.GetKeyDown(KeyCode.Space)) {
rb.velocity = Vector2.up * jumpSpeed;
}
}
(Edited to use velocity instead of AddForce)

Smooth Player Ball Rolling - Unity 3D

I was trying to achieve this kind of player ball movement:
Catch Up (Ketchapp)
From my side I have tried and record a video of my current implementation:
CatchUpBallMovementDemo
Two kinds of problem, I was facing:
ball making so much jerk while moving on the plain track that I hope you have clearly noticed in my recorded video
when ball reach left or right edge and you try to swipe its making jerk again rather than remain restricted because clamping related code already added
I have just created a demo project so here I am providing the link for it so personally you can check and provide me a suggestion for making ball movement perfect.
Demo Project Source Link: CatchUpBallDemo
Demo Project SIZE 20MB
What at present making jerk in ball movement that I can't able to decide, whether its following camera jerk, whether ball not moving properly though I have created a plain track for checking purpose.
Ball Inspector Detail:
Complete code added within the working demo project. Share your suggestions with me to solve this.
Code Scripts:
BallController
[RequireComponent (typeof(Rigidbody))]
public class BallController : MonoBehaviour
{
//
private Rigidbody myRigidBody;
private bool isJumper;
private bool allowSpeedIncrease;
private BallInputHandler ballInputHandler;
private float speed;
private float speedMilestone;
private float jumpCounter;
private float scoreElapsedTime;
[SerializeField]
private bool isGrounded;
//
public float ballHorzRange;
public float ballStartSpeed;
public float ballTopSpeed;
public float smoothnessValue;
public float smoothnessX;
private void Awake ()
{
DoOnAwake ();
}
private void DoOnAwake ()
{
ballInputHandler = GetComponent<BallInputHandler> ();
myRigidBody = GetComponent<Rigidbody> ();
speed = ballStartSpeed;
speedMilestone = ballStartSpeed;
}
public void Start ()
{
DoOnStart ();
}
private void DoOnStart ()
{
// assinging player transform to camera to follow
Camera.main.GetComponent<CameraFollow> ().FollowPlayer (transform);
}
void Update ()
{
// slowly increase ball moving speed
if (allowSpeedIncrease) {
speed += Time.deltaTime;
if (speed >= speedMilestone) {
allowSpeedIncrease = false;
speed = speedMilestone;
}
}
}
void FixedUpdate ()
{
// do jumping
if (isJumper) {
jumpCounter++;
if (jumpCounter >= 3) {
isJumper = false;
jumpCounter = 0;
}
myRigidBody.AddForce (Vector3.up * 700f);
}
// applying continuous forward velocity
Vector3 nextVelocity = myRigidBody.velocity;
nextVelocity.x = ballInputHandler.horizontalInput * smoothnessX;
nextVelocity.z = speed;
if (isGrounded) {
nextVelocity.y = 0;
} else if (!isJumper) {
nextVelocity.y -= speed * 0.1f;
}
myRigidBody.velocity = nextVelocity.normalized * speed;
ClampingBallMovement ();
}
// ball horizontal movement limitation
private void ClampingBallMovement ()
{
Vector3 currRigidbodyPos = myRigidBody.position;
if (currRigidbodyPos.x <= -ballHorzRange || currRigidbodyPos.x >= ballHorzRange) {
currRigidbodyPos.x = Mathf.Clamp (currRigidbodyPos.x, -ballHorzRange, ballHorzRange);
myRigidBody.position = currRigidbodyPos;
}
}
void OnTriggerEnter (Collider other)
{
if (other.CompareTag (GameConstants.TAG_TRACK_SPAWNER)) {
GameController.Instance.SpawnPlateform ();
} else if (other.CompareTag (GameConstants.TAG_TRACK_DESTROYER)) {
Destroy (other.transform.parent.gameObject);
}
}
}
BallMeshRolling
public class BallMeshRolling : MonoBehaviour
{
private Vector3 ballLastPosition;
void Start ()
{
ballLastPosition = transform.parent.position;
}
void Update ()
{
// implementation-1
float speed = Vector3.Distance (transform.parent.position, ballLastPosition) * 30f;
transform.RotateAround (transform.position, Vector3.right, speed);
// float dragDifference = (transform.position.x - ballLastPosition.x) * 30f;
// transform.RotateAround (transform.position, Vector3.forward, dragDifference);
ballLastPosition = transform.parent.position;
}
}
CameraFollow
public class CameraFollow : MonoBehaviour
{
//
private Vector3 newPos;
private Vector3 initialPosition;
//
public Transform player;
public Vector3 offSet;
void Awake ()
{
initialPosition = transform.position;
}
void LateUpdate ()
{
if (!player)
return;
newPos = player.position + offSet;
newPos.x = ReMap (newPos.x);
newPos.y = Mathf.Clamp (newPos.y, initialPosition.y, initialPosition.y + 1f);
// transform.position = newPos;
transform.position = Vector3.Lerp (transform.position, newPos, 10f * Time.deltaTime);
}
public void FollowPlayer (Transform target)
{
player = target;
ResetCamera ();
}
public float ReMap (float value, float from1 = -4f, float to1 = 4f, float from2 = -2.5f, float to2 = 2.5f)
{
return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
}
public void ResetCamera ()
{
transform.position = initialPosition;
}
}
I could solve the second problem by simply adding this to BallController.ClampingBallMovement():
private void ClampingBallMovement ()
{
Vector3 currRigidbodyPos = myRigidBody.position;
if (currRigidbodyPos.x <= -ballHorzRange || currRigidbodyPos.x >= ballHorzRange) {
currRigidbodyPos.x = Mathf.Clamp (currRigidbodyPos.x, -ballHorzRange, ballHorzRange);
myRigidBody.position = currRigidbodyPos;
}
// I ADDED THIS
// Clamp the velocity as well
if (currRigidbodyPos.x <= -ballHorzRange && myRigidBody.velocity.x < 0 || currRigidbodyPos.x >= ballHorzRange && myRigidBody.velocity.x > 0)
{
myRigidBody.velocity = new Vector3(0, myRigidBody.velocity.y, myRigidBody.velocity.z);
}
}
you clamped the position but did not clamp the velocity as well.
I could not reproduce the first jerking arround on my PC.

I want to create the ball movement like the one in 'chilly snow' game. I want to curve the ball, but it revolves

I am new to unity and don't know a lot of stuff. I've been watching tutorials and I saw one in which the guy created a replica of famous 'Chilly Snow'. The game is complete but the movement of ball isn't like the one in chilly snow. The ball starts orbiting continuously when I press mouse button. I wanted to know how to create that kind of movement, so that the ball turns left and right in a curve but doesn't go in to an orbit. I googled a lot but wasn't able to find my required result. I would really appreciate if anyone could point me in the right direction. Images are attached.Chilly Snow | Movement of my ball
public class movement : MonoBehaviour {
private float points;
public float playerSpeed;
private float rotationSpeed;
public Text score;
private bool isMovingLeft;
public GameObject player;
public bool isDead;
void Start () {
Time.timeScale = 0;
isDead = false;
isMovingLeft = true;
points = 0;
}
void Update ()
{
if (isDead == false)
{
points += Time.deltaTime;
}
transform.Translate (Vector3.down * playerSpeed * Time.deltaTime);
if (Input.GetMouseButtonDown (0))
{
Time.timeScale = 1;
isMovingLeft = !isMovingLeft;
rotationSpeed += 0.5f * Time.deltaTime;
}
if (Input.GetMouseButton (0))
{
rotationSpeed = 1f;
}
if (isMovingLeft) {
rotationSpeed += 1.5f * Time.deltaTime;
transform.Rotate(0,0,rotationSpeed);
} else
transform.Rotate(0,0, - rotationSpeed);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Obstacle") {
Die ();
}
}
public void Die()
{
playerSpeed = 0f;
isDead = true;
Invoke ("Restart", 2f);
}
void Restart(){
SceneManager.LoadScene ("Ski_scene_1");
}
void FixedUpdate()
{
score.GetComponent<Text>().text = points.ToString("0");
}
}
Here is how I would approach it without doing a rotation... using your code.
public class movement : MonoBehaviour {
private float points;
public Text score;
public GameObject player;
public bool isDead;
private float currentXSpeed;
private float targetSpeed;
public float maxXSpeed;
public float speedChange;
void Start () {
Time.timeScale = 0;
isDead = false;
isMovingLeft = true;
points = 0;
targetSpeed = maxXSpeed;
}
void Update ()
{
if (isDead == false)
{
points += Time.deltaTime;
}
if(Input.GetMouseButtonDown(0))
{
Time.timeScale = 1;
targetSpeed = -targetSpeed;
}
currentSpeed = mathf.MoveTowards(currentSpeed, targetSpeed, speedChange * Time.deltaTime);
Vector3 movementDirection = new Vector3(currentSpeed, Vector3.down.y * playerSpeed, 0.0f);
transform.Translate (movementDirection * Time.deltaTime);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Obstacle") {
Die ();
}
}
public void Die()
{
playerSpeed = 0f;
isDead = true;
Invoke ("Restart", 2f);
}
void Restart(){
SceneManager.LoadScene ("Ski_scene_1");
}
void FixedUpdate()
{
score.GetComponent<Text>().text = points.ToString("0");
}
}
You need something like sinusoidal movement or any other graph you fancy.
An example would be for this is like;
gameObject.transform.Translate(Vector3.right * Time.deltaTime*cubeSpeed);
gameObject.transform.position += transform.up * Mathf.Sin (Time.fixedTime * 3.0f ) * 0.1f;
Above pseudo is for 2D graph simulation, can be adapted to your situation.
The object is always moving to right and going up and down while making a sinusoidal movement. Because the up and down speed is not fixed hence you get the sinusoidal or like sinusoidal movement.
In your case, while the object is always going down it will make the sinusoidal movement to left and right.
Your movement is based on the rotation so, if you give this sinusoidal speed as your rotation speed, you can achieve this.
Another aproach can be lerp or slerp
Lerp allows you to make kinda smooth transactions between 2 vectors.
Like moving from pointA to pointB in X seconds.
For rotation you will need Quaternion.Lerp There is a great answer on Unity Answers you can check that if you haven't before.
Hope this helps! Cheers!