Issue with flipping sprite in Unity 2D - c#

I'm new to unity and I was following a youtube guide on scripting a 2D platformer, I have gotten to the point now where I am trying to add a flip to the sprite when I turn to go in the opposite direction.
I have added a code and now this is constantly flipping left to right. If I understand correctly its probably because I am constantly applying > 0.1f when moving resulting in the function to continuously run but honestly I am lost so any help would be appreciated.
using UnityEngine;
using System.Collections;
[RequireComponent (typeof (Controller2D))]
public class Player : MonoBehaviour {
public float jumpHeight = 4;
public float timeToJumpApex = .4f;
float accelerationTimeAirbourne = .2f;
float acceleratinTimeGrounded =.1f;
public float moveSpeed = 6;
float jumpVelocity;
float gravity;
Vector3 velocity;
float velocityXSmoothing;
Controller2D controller;
void Start(){
controller = GetComponent<Controller2D>();
gravity = -(2 * jumpHeight) / Mathf.Pow (timeToJumpApex, 2);
jumpVelocity = Mathf.Abs(gravity) * timeToJumpApex;
print ("gravity: " + gravity + " Jump Velocity: " + jumpVelocity);
}
void Update(){
if (controller.collisions.above || controller.collisions.above) {
velocity.y = 0;
}
Vector2 input = new Vector2 (Input.GetAxisRaw ("Horizontal"),
Input.GetAxisRaw ("Vertical"));
if (Input.GetKeyDown (KeyCode.Space) && controller.collisions.below) {
velocity.y = jumpVelocity;
}
float targetVelocityX = input.x * moveSpeed;
velocity.x = Mathf.SmoothDamp(velocity.x, targetVelocityX, ref
velocityXSmoothing, (controller.collisions.below)?
acceleratinTimeGrounded:accelerationTimeAirbourne);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
void FixedUpdate(){
if ((Input.GetAxis("Horizontal") > 0.1f && this.transform.localScale.x != 1)
|| (Input.GetAxis("Horizontal") < -0.1f && this.transform.localScale.x !=
-1))
{
flip();
}
}
void flip()
{
this.transform.localScale = new Vector3(this.transform.localScale.x *
-1,
this.transform.localScale.y, this.transform.localScale.z);
}
}

Your error is here
void FixedUpdate(){
if ((Input.GetAxis("Horizontal") > 0.1f && this.transform.localScale.x != 1)|| (Input.GetAxis("Horizontal") < -0.1f && this.transform.localScale.x !=
-1)){
flip();
}
}
After you flip, the condition still evaluates to true. You will need a boolean hasflipped to check if you have already flipped, and if you have don't flip again :)
Fixed update is causing this check to happen once per frame, so you're going to get a bunch of flickering as your sprite flips every frame, unless you specify only to flip once

Related

Slowly decrease movement speed after releasing left shift

So, I am still developing a game in Unity, where my only problem now is that I can't figure out how to slowly decrease the speed of my character after releasing left shift. Slowly increasing speed while holding shift is the only one I had worked out because I used the incrementing technique, but the speed slowly decreasing after releasing left shift is not. Can someone help me? Here's the code, I apologize, I am literally a beginner at this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
//Codes for setting walk and sprint speed (You should put speed in "Default Speed". "Walk Speed" is public so I can see if my speed is increasing)
public float defaultSpeed = 8f;
public float walkSpeed = 8f;
public float sprintIncrease = 15f;
public float sprintLimit = 16f;
//Gravity force
public float gravity = -60f;
//Probably jump height?
public float jumpHeight = 2f;
//For checking if you're on the ground
public Transform groundCheck;
public float groundDistance = 0.5f;
public LayerMask groundMask;
//Code to check if you are on the ground
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
//For checking again if you're on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
//Code to slowly increase sprint FORWARD while holding left shift
if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code to prevent sprinting while holding S and when combined with A or D
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") < 0)
{
walkSpeed = defaultSpeed;
}
//Code for allowing to slowly increase sprint LEFT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") < 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code for allowing to slowly increase sprint RIGHT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//To stop Sprint Speed while holding shift from exceeding Sprint Limit
if (walkSpeed > sprintLimit)
{
walkSpeed = sprintLimit;
}
//Executes when shift is released, to slowly go back to default speed(This is my problem)
if (Input.GetKeyUp(KeyCode.LeftShift))
{
walkSpeed = defaultSpeed;
}
//To check if you're grounded so velocity doesn't increase
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
//The basic horizontal and vertical axises
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
//The basic code for movement
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * walkSpeed * Time.deltaTime);
//The code for jumping
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
I thank everyone in advance.
if (!Input.GetKey(KeyCode.LeftShift))
{
walkSpeed -= sprintIncrease * Time.deltaTime;
}
the above code will do what you asked for. Just a heads up, the way you're implementing stuff is beginner-friendly but not performance friendly.
Ok, I have figured this out myself. I rearrange my ifs and else statement to look more organized. I added the else statement where if you don't hold shift while walking, it continuously subtracts the walk speed with the sprint increase, but to stop it from being lower than the default speed, I added an if statement where if the walk speed becomes lower than the default speed, it becomes equal to the default speed. Note that I rearranged my statements to trigger an else statement.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
//Codes for setting walk and sprint speed (You should put speed in "Default Speed". "Walk Speed" is public so I can see if my speed is changing or not)
public float defaultSpeed = 8f;
public float walkSpeed = 8f;
public float sprintIncrease = 15f;
public float sprintLimit = 16f;
//Gravity force
public float gravity = -60f;
//Probably jump height?
public float jumpHeight = 2f;
//For checking if you're on the ground
public Transform groundCheck;
public float groundDistance = 0.5f;
public LayerMask groundMask;
//Code to check if you are on the ground
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
//For checking again if you're on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
//Code to prevent sprinting while holding S and when combined with A or D(New Code)
if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") < 0)
{
walkSpeed -= sprintIncrease * Time.deltaTime;
}
//Code to slowly increase sprint FORWARD while holding left shift
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code for allowing to slowly increase sprint LEFT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") < 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code for allowing to slowly increase sprint RIGHT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//To make sure that your speed decrease smoothly if not holding left shift(New code)
else
{
walkSpeed -= sprintIncrease * Time.deltaTime;
}
//To stop Sprint Speed while holding shift from exceeding Sprint Limit
if (walkSpeed > sprintLimit)
{
walkSpeed = sprintLimit;
}
//To stop Walk Speed from getting lower than Default Speed(New Code)
if (walkSpeed < defaultSpeed)
{
walkSpeed = defaultSpeed;
}
//To check if you're grounded so velocity doesn't increase
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
//The basic horizontal and vertical axises
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
//The basic code for movement
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * walkSpeed * Time.deltaTime);
//The code for jumping
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}

How do I disable diagonal movement in Unity 2D?

I would like to ask if there is a way to disable diagonal movement in Unity 2D.
The thing is when I press 'W' + 'D'(move key) at the same time then the character starts to move diagonally.
So instead of the character moving diagonal when combining button press, I want it to go completely straight instead if I press 'd' or any other key to move even if I'm still pressing the other button at the same time. So to say prioritize the function of the last button I pressed.
Here's a short video to explain my problem further .
https://youtu.be/aPZii5HfP4s
And here's the code for my character movement.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keycontrol : MonoBehaviour
{
public float moveSpeed = 0f;
public Rigidbody2D rb2d;
Vector2 movement;
public Animator animator;
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
animator.SetFloat("walk_right", movement.x);
animator.SetFloat("walk_left", -movement.x);
animator.SetFloat("walk_down", -movement.y);
animator.SetFloat("walk_up", movement.y);
}
void FixedUpdate()
{
rb2d.MovePosition(rb2d.position + movement * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 200 * Time.deltaTime;
animator.speed = 1.5f;
}
else
{
moveSpeed = 110 * Time.deltaTime;
animator.speed = 1f;
}
}
}
Thanks for help
A simple way to do this is to prioritize one axis over the other and just wrap the other check in a condition.
movement.x = Input.GetAxisRaw("Horizontal");
if (movement.x != 0)
{
movement.y = Input.GetAxisRaw("Vertical");
}
However, this can fail, because depending on your input, the axis might return values close to zero when using a controller. In this case, you could just get both values and check for the larger one.
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
if (Mathf.Abs(movement.x) > Mathf.Abs(movement.y))
{
movement.y = 0;
}
else
{
movement.x = 0;
}
Sharing as an answer since I can't comment on this post, you should check out the new input system unity released recently: https://docs.unity3d.com/Packages/com.unity.inputsystem#1.0/manual/QuickStartGuide.html
It gives better control over inputs such as event systems so you can lock the movement until the first key is released.
You can handle the movement only in one of the axis handled each chance in the code, find draft below:
bool isXMoving;
bool isYMoving;
// Update is called once per frame
void Update()
{
if (Input.GetAxisRaw("Horizontal") != 0f && !isYMoving) {
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = 0;
isXMoving = true;
isYMoving = false;
}
if (Input.GetAxisRaw("Horizontal") != 0f && !isXMoving) {
movement.y = Input.GetAxisRaw("Vertical");
movement.x = 0;
isYMoving = true;
isXMoving = false;
}
Debug.Log($"X: {movement.x} Y: {movement.y}"); //check
animator.SetFloat("walk_right", movement.x);
animator.SetFloat("walk_left", -movement.x);
animator.SetFloat("walk_down", -movement.y);
animator.SetFloat("walk_up", movement.y);
}
You can add condition to check if the horizontal movement is pressed.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keycontrol : MonoBehaviour
{
public float moveSpeed = 0f;
public Rigidbody2D rb2d;
Vector2 movement;
public Animator animator;
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
if(movement.x == 0){
movement.y = Input.GetAxisRaw("Vertical");
}
animator.SetFloat("walk_right", movement.x);
animator.SetFloat("walk_left", -movement.x);
animator.SetFloat("walk_down", -movement.y);
animator.SetFloat("walk_up", movement.y);
}
void FixedUpdate()
{
rb2d.MovePosition(rb2d.position + movement * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 200 * Time.deltaTime;
animator.speed = 1.5f;
}
else
{
moveSpeed = 110 * Time.deltaTime;
animator.speed = 1f;
}
}
}

How to make sliding mechanic gain speed when on a slope

I am a new unity developer that is trying to make a 3d game. So far I have managed to develop a pretty cool first-person character controller. It uses a character controller and it has sliding and jumping mechanics.
And the question is:
How can I make my player lose sliding speed when sliding up a slope and gain sliding speed when sliding down a slope?
Here is my code so far and please keep in mind that my code is messy and that I am a still beginner. If you need any further information please don't hesitate to ask. Thanks for your time! Also, any suggestions are more than welcome!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovementScript : MonoBehaviour
{
//Character controller refrence
private CharacterController controller;
//Camera refrence
[SerializeField] Camera fpsCam;
//IsGrounded variables
private float groundDistance = 1.5f;
public bool isGrounded;
//SomethingAbove variables
private float cellingDistance = 1.5f;
public bool somethingAbove;
//Variables
//Speed that is modified
private float speed = 12f;
//Default speed
private float baseSpeed = 12f;
//Slide speed that is modified
private float slideSpeed = 15f;
//Default slide speed
private float slideSpeedStorage = 15f;
//Crouch speed
private float crouchSpeed = 3f;
//Jump height
private float jumpHeight = 2f;
private bool isJumping = false;
//Gravity
private float gravity = -14.715f;
//Air resistance
private float xAirResistance = 0.5f;
private float zAirResistance = 0.35f;
//Air multipiler
private float airMultiplierJump = 1.1f;
//Fov
private float fovWhenSliding = 100f;
private float defaultFov;
//Crouch variables
float originalHeight;
float reducedHeight = 0.5f;
//Player input
float x;
float z;
bool jump;
bool control;
//Directions
Vector3 velocity;
private Vector3 move = new Vector3();
private Vector3 slideDirection = new Vector3();
private Vector3 jumpDirection = new Vector3();
private void Awake()
{
controller = GetComponent<CharacterController>();
}
private void Start()
{
//Getting the original height
originalHeight = controller.height;
//Getting the default fov
defaultFov = fpsCam.fieldOfView;
}
private void Update()
{
MyInput();
Calculations();
PlayerMovement();
}
private void MyInput()
{
//Getting WASD input
x = Input.GetAxis("Horizontal");
z = Input.GetAxis("Vertical");
//Space bar input
jump = Input.GetButtonDown("Jump");
//Left control input
control = Input.GetKey(KeyCode.LeftControl);
}
private void Calculations()
{
//Checking if player is grounded
Debug.DrawRay(transform.position, Vector3.down * groundDistance, Color.red);
isGrounded = Physics.Raycast(transform.position, Vector3.down, groundDistance);
//Checking if player can get up
Debug.DrawRay(transform.position, Vector3.up * cellingDistance, Color.black);
somethingAbove = Physics.Raycast(transform.position, Vector3.up, cellingDistance);
/*//Getting the player has enough speed and getting jump direction
if (isGrounded && jump && z > 0)
{
//If pressing W the jump direction is forward
jumpDirection = transform.forward;
}*/
//Movement in air
if (isGrounded)
{
//On ground movement
move = transform.right * x + transform.forward * z;
}
else
{
//If pressing W
if (z > 0)
{
//Jump direction multiplied by airMultiplierJump
move = transform.forward * z * airMultiplierJump + transform.right * x * xAirResistance;
}
else
{
//Jump direction = Vector3.zero;
move = transform.forward * z * zAirResistance + transform.right * x * xAirResistance;
}
}
//Checking if the player has enough speed for sliding and getting direction
if (Input.GetKeyDown(KeyCode.LeftControl) && isGrounded)
{
if (z == 1 || x == 1 || x == -1)
{
//If pressing W || A || D slide direction is the direction u are moving towards
slideDirection = transform.forward * z + transform.right * x;
}
else
{
//If pressing S the slide direction is zero
slideDirection = Vector3.zero;
}
}
//Adding extra force so the player stays on ground
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
//Calculating gravity
velocity.y += gravity * Time.deltaTime;
//Normalizing the move vector so the diagonal and normal movement are the same speed
if (move.sqrMagnitude > 1)
{
move.Normalize();
}
//Extra force on slope downwards so the player stays on it
if((x != 0 || z != 0) && OnSlope())
{
controller.Move(Vector3.down * controller.height / 2 * 2f);
}
}
private void PlayerMovement()
{
Jump();
Slide();
//Moving the player with WASD
controller.Move(move * speed * Time.deltaTime);
//Applying gravity
controller.Move(velocity * Time.deltaTime);
}
private void Slide()
{
//Checking for left control input and if the player is grounded
if(control && isGrounded && !OnSlope())
{
StartSlide();
}
//Checking if the player can uncrouch
else if(!somethingAbove && isGrounded)
{
StopSlide();
}
else if (!control)
{
controller.height = originalHeight;
speed = baseSpeed;
}
else if(control && !isGrounded)
{
controller.height = originalHeight;
speed = baseSpeed;
}
else
{
controller.height = reducedHeight;
speed = crouchSpeed;
}
}
//Starting to slide
private void StartSlide()
{
if (z != 1 || x != -1 || x != 1)
{
speed = crouchSpeed;
}
else
{
speed = 0f;
}
controller.height = reducedHeight;
controller.Move(slideDirection * Time.deltaTime * slideSpeed);
slideSpeed -= 10f * Time.deltaTime;
if (slideSpeed <= 0)
{
slideSpeed = 0f;
speed = crouchSpeed;
}
}
//Stopping the slide
private void StopSlide()
{
controller.height = originalHeight;
speed = baseSpeed;
//Slide speed recovery
slideSpeed = Mathf.Lerp(slideSpeed, slideSpeedStorage, Time.deltaTime * 2);
}
//Jumping mechanic
private void Jump()
{
if (jump && isGrounded)
{
isJumping = true;
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
}
private bool OnSlope()
{
if (isJumping)
{
return false;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, Vector3.down, out hit, controller.height / 2 * 5f))
if(hit.normal != Vector3.up)
{
return true;
}
return false;
}
//Stopping the slide if hitting object
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if(hit.transform.tag == "SlideStop")
{
slideSpeed = 0f;
speed = crouchSpeed;
}
}
}```
private bool OnSlope()
{
if (isJumping)
{
return false;
}
RaycastHit hit;
if(Physics.Raycast(transform.position, Vector3.down, out hit, controller.height / 2 * 5f))
if(hit.normal != Vector3.up)
{
return true;
}
return false;
}
One issue is comparing Vector3s which is bad practice, since they are arrays of floats. Even if the plane is completely planar, it might still return true due to what's known as 'floating point errors'. A better practice is to use:
Vector3.distance(hit.normal, Vector3.up) > .1f // or some other small value;

Character doesn't jump sometimes - Unity

I am new to Unity and I am using the following CharacterController for my character. Everything is working well, except that sometimes the character jumps and sometimes it doesn't when I hit the spacebar. I used Debog.Log using Raycast to check if my character is grounded, and the result was True. So what is preventing my character from jumping whenever I hit the key?
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]
public class RPGMovement : MonoBehaviour
{
public float ForwardSpeed = 8f;
public float BackwardSpeed = 4f;
public float StrafeSpeed = 5f;
public float RotateSpeed = 110f;
CharacterController m_CharacterController;
Vector3 m_LastPosition;
Animator m_Animator;
PhotonView m_PhotonView;
PhotonTransformView m_TransformView;
float m_AnimatorSpeed;
Vector3 m_CurrentMovement;
float m_CurrentTurnSpeed;
Vector3 playerVelocity;
private bool groundedPlayer;
private float jumpHeight = 0.9f;
private float gravityValue = -20.81f;
void Start()
{
m_CharacterController = GetComponent<CharacterController>();
m_Animator = GetComponent<Animator>();
m_PhotonView = GetComponent<PhotonView>();
m_TransformView = GetComponent<PhotonTransformView>();
}
void Update()
{
if (m_PhotonView.isMine == true)
{
ResetSpeedValues();
UpdateRotateMovement();
UpdateForwardMovement();
UpdateBackwardMovement();
UpdateStrafeMovement();
MoveCharacterController();
UpdateJump();
ApplySynchronizedValues();
}
UpdateAnimation();
}
void UpdateAnimation()
{
Vector3 movementVector = transform.position - m_LastPosition;
float speed = Vector3.Dot(movementVector.normalized, transform.forward);
float direction = Vector3.Dot(movementVector.normalized, transform.right);
if (Mathf.Abs(speed) < 0.2f)
{
speed = 0f;
}
if (speed > 0.6f)
{
speed = 1f;
direction = 0f;
}
if (speed >= 0f)
{
if (Mathf.Abs(direction) > 0.7f)
{
speed = 1f;
}
}
m_AnimatorSpeed = Mathf.MoveTowards(m_AnimatorSpeed, speed, Time.deltaTime * 5f);
m_Animator.SetFloat("Speed", m_AnimatorSpeed);
m_Animator.SetFloat("Direction", direction);
m_LastPosition = transform.position;
}
void ResetSpeedValues()
{
m_CurrentMovement = Vector3.zero;
m_CurrentTurnSpeed = 0;
}
void ApplySynchronizedValues()
{
m_TransformView.SetSynchronizedValues(m_CurrentMovement, m_CurrentTurnSpeed);
}
void MoveCharacterController()
{
m_CharacterController.Move(m_CurrentMovement * Time.deltaTime);
}
void UpdateForwardMovement()
{
if (Input.GetKey(KeyCode.W) || Input.GetAxisRaw("Vertical") > 0.1f)
{
m_CurrentMovement = transform.forward * ForwardSpeed;
}
}
void UpdateBackwardMovement()
{
if (Input.GetKey(KeyCode.S) || Input.GetAxisRaw("Vertical") < -0.1f)
{
m_CurrentMovement = -transform.forward * BackwardSpeed;
}
}
void UpdateStrafeMovement()
{
if (Input.GetKey(KeyCode.Q) == true)
{
m_CurrentMovement = -transform.right * StrafeSpeed;
}
if (Input.GetKey(KeyCode.E) == true)
{
m_CurrentMovement = transform.right * StrafeSpeed;
}
}
void UpdateRotateMovement()
{
if (Input.GetKey(KeyCode.A) || Input.GetAxisRaw("Horizontal") < -0.1f)
{
m_CurrentTurnSpeed = -RotateSpeed;
transform.Rotate(0.0f, -RotateSpeed * Time.deltaTime, 0.0f);
}
if (Input.GetKey(KeyCode.D) || Input.GetAxisRaw("Horizontal") > 0.1f)
{
m_CurrentTurnSpeed = RotateSpeed;
transform.Rotate(0.0f, RotateSpeed * Time.deltaTime, 0.0f);
}
}
void UpdateJump()
{
groundedPlayer = m_CharacterController.isGrounded;
if (groundedPlayer && playerVelocity.y < 0)
{
playerVelocity.y = 0f;
}
if (Input.GetButtonDown("Jump") && groundedPlayer)
{
playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
m_Animator.SetTrigger("Jump");
print("Jumping Now");
}
playerVelocity.y += gravityValue * Time.deltaTime;
m_CharacterController.Move(playerVelocity * Time.deltaTime);
}
}
Best guess is that "m_PhotonView.isMine" is not returning true on the frames where you're missing input. It only checks jump input for that frame, so if the last frame you pressed it but jumping wasn't checked then that input is lost forever. First test this. Change the update code to this:
void Update()
{
if (Input.GetButtonDown("Jump")) { Debug.Log("Jump was pressed at {Time.time}"); }
if (m_PhotonView.isMine == true)
{
if (Input.GetButtonDown("Jump")) { Debug.Log("Attempting Jump at {Time.time}"); }
ResetSpeedValues();
UpdateRotateMovement();
UpdateForwardMovement();
UpdateBackwardMovement();
UpdateStrafeMovement();
MoveCharacterController();
UpdateJump();
ApplySynchronizedValues();
}
UpdateAnimation();
}
Then play the game and jump a bunch. The first debug log line should happen every time you click the spacebar no matter what. The second debug line would only happen if physics are calculated that frame. Both have times attached. Keep jumping until the jump doesn't work. If that jump only produces the first debug log and not the second, then I am correct and that is your issue.
If so, then it's an easy fix. Add a new bool variable called "jumpInput". Whenever you check if jump was pressed, instead check if "jumpInput" is true. Then, change update to this:
void Update()
{
if (Input.GetButtonDown("Jump")) { jumpInput = true; }
if (m_PhotonView.isMine == true)
{
ResetSpeedValues();
UpdateRotateMovement();
UpdateForwardMovement();
UpdateBackwardMovement();
UpdateStrafeMovement();
MoveCharacterController();
UpdateJump();
ApplySynchronizedValues();
jumpInput = false;
}
UpdateAnimation();
}
This way if you pressed jump, it's set to true... but it's only set to false after physics are done. So if you press jump on frame 20 and physics are somehow not calculated until frame 25, it'll still know that you pressed jump at some point and thus execute it. If you're using networking, you might want to also have another variable that's what frame jump was pressed. That way you can figure out how many frames it's been since input and compensate for missed time in the jump if necessary.

How would I increase the friction of a car so that it doesn't glide when I don't give it any inputs?

everyone. I am new to Unity 2D and C# and I was wondering how I could stop my car from gliding and sliding forward in my game when I don't want it to since it doesn't really feel like I am in control of my car if it's slipping so much. I would like it so if I don't give the car any inputs, or give counter inputs that the car almost immediately stops or starts moving the other way. I have tried creating a Physics2D material and increasing the friction but it really had no effect on the gameplay. I've also tried checking so that if there is no player inputs the rb.velocity is set to 0, or around .2 of what it currently is so it's a smoother stop but that only works if the player moves then lets go of the movement key, not if they try moving the opposite direction. I've also thought about checking which direction the car is moving by comparing a previous location with a current one then adding force in the opposite direction to stop the car but that seems very performance-intensive and I don't really know where I would start. If anyone has any suggestions for how I would go about doing this then please let me know how. This is the code I have so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarController : MonoBehaviour
{
public Rigidbody2D carRigidbody;
public Rigidbody2D backTire;
public Rigidbody2D frontTire;
private float movement;
public float fspeed = 100;
public float bspeed = 60;
public float carTorque = 10;
public float decVel = .9f;
private bool beganMoving;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
movement = Input.GetAxis("Horizontal");
}
void FixedUpdate() {
if (movement == 1 || movement == -1) {
beganMoving = true;
}
if (movement == 0 && beganMoving) {
backTire.velocity = new Vector2 (backTire.velocity.x * decVel * Time.fixedDeltaTime, backTire.velocity.y);
frontTire.velocity = new Vector2 (backTire.velocity.x * decVel * Time.fixedDeltaTime, backTire.velocity.y);
}
backTire.AddTorque(-movement * bspeed * Time.fixedDeltaTime);
frontTire.AddTorque(-movement * fspeed * Time.fixedDeltaTime);
carRigidbody.AddTorque(-movement * carTorque * Time.fixedDeltaTime);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarController : MonoBehaviour
{
public Rigidbody2D carRigidbody;
public Rigidbody2D backTire;
public Rigidbody2D frontTire;
private float movement;
public float fspeed = 100;
public float bspeed = 60;
public float carTorque = 10;
public float decVel = .9f;
private bool beganMoving;
// Update is called once per frame
void Update()
{
movement = Input.GetAxis("Horizontal");
}
void FixedUpdate() {
if (movement == 1 || movement == -1) {
beganMoving = true;
}
if (movement <= 0.1f)
{
beganMoving = false;
}
if (movement <= 0.8f && beganMoving) // If the movement is starting to decrease and it the car has already started moving, set the velocities to zero.
{
backTire.velocity = Vector3.zero;
frontTire.velocity = Vector3.zero;
}
if (movement == 0 && beganMoving) {
backTire.velocity = new Vector2 (backTire.velocity.x * decVel * Time.fixedDeltaTime, backTire.velocity.y);
frontTire.velocity = new Vector2 (backTire.velocity.x * decVel * Time.fixedDeltaTime, backTire.velocity.y);
}
backTire.AddTorque(-movement * bspeed * Time.fixedDeltaTime);
frontTire.AddTorque(-movement * fspeed * Time.fixedDeltaTime);
carRigidbody.AddTorque(-movement * carTorque * Time.fixedDeltaTime);
}
Hi everyone browsing past this with similar issues. The way I solved this issue in the end was by implementing this whole chunk of code here:
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
if (movement == 1 || movement == -1) {
beganMoving = true;
} // this makes sure we've started moving which will be used later
if (movement == 0 && isGrounded) {
backTire.velocity = new Vector2 (backTire.velocity.x * .8f * Time.fixedDeltaTime, backTire.velocity.y);
frontTire.velocity = new Vector2 (frontTire.velocity.x * .8f * Time.fixedDeltaTime, frontTire.velocity.y); // this whole if statement is so that our car will stop or decelerate when no input is given to it as to stop it from rolling all across the ground
}
if (movement > 0 && prevMove < 0) { // checks if we are moving forward (right) when we used to move backwards (left)
backTire.velocity = new Vector2 (backTire.velocity.x * decVel * Time.fixedDeltaTime, backTire.velocity.y);
frontTire.velocity = new Vector2 (frontTire.velocity.x * decVel * Time.fixedDeltaTime, frontTire.velocity.y); //stops us if the if statement returns true
prevMove = 1; // sets our previous movement to moving forward to make it not repeat itself and to check with later on
} else if (movement < 0 && prevMove > 0 ) { // checks if we are moving backwards when we used to be moving forwards
backTire.velocity = new Vector2 (backTire.velocity.x * decVel * Time.fixedDeltaTime, backTire.velocity.y);
frontTire.velocity = new Vector2 (frontTire.velocity.x * decVel * Time.fixedDeltaTime, frontTire.velocity.y); //stops car
prevMove = -1; // sets previous movement to moving backwards
} else {
if (beganMoving == true) { // when we start moving we set the previous movement to which ever direction we decided to first move in
prevMove = movement;
beganMoving = false; // set began moving to false. This doesn't make sense logically since we did begin moving but it's so this if statement doesn't repeat itself again
}
}
I've included comments so you can hopefully understand what and why I did. I hope this helps anyone with similar issues.

Categories