How to Prevent sliding in 2d movement - c#

hi i want to move my charachter i looked around but couldnt find solutions for my code i just want when my charachter moves and i not pressed move forward button then it stop but not instantly it just stops instantly after i unpressed d button here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public Rigidbody2D rb2d;
bool ismoving;
public float speed = 5f;
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
if (Input.GetButton("Horizontal"))
{
ismoving = true;
}
else { ismoving = false; }
if (ismoving)
{
rb2d.AddForce(new Vector2(horizontal, 0) * speed * Time.fixedDeltaTime *10);
}
else
{
while((rb2d.velocity) != (rb2d.velocity = Vector2.zero))
{
rb2d.AddForce(new Vector2(horizontal, 0) * Time.fixedDeltaTime *-1);
}
}
}
}

You can change the multiplier for your deceleration to a greater value
while((rb2d.velocity) != (rb2d.velocity = Vector2.zero))
{
rb2d.AddForce(new Vector2(horizontal, 0) * Time.fixedDeltaTime * -10);
}
Now it should decelerate 10 times faster than before

Currently, you stop adding force when the key is released. How about approaching a speed of 0 once the key is released? Like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public Rigidbody2D rb2d;
bool ismoving;
public float maxspeed = 5f;
private float currentSpeed = 0f;
private float movingDirection = 0f;
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
if (Input.GetButton("Horizontal"))
{
ismoving = true;
movingDirection = horizontal;
}
else
{
ismoving = false;
// keep the movingDirection as it is.
}
if (ismoving)
{
// accelerate
currentSpeed += 5 * Time.fixedDeltaTime;
currentSpeed = Mathf.Clamp(currentSpeed, 0, maxspeed);
}
else
{
currentSpeed -= 5 * Time.fixedDeltaTime;
currentSpeed = Mathf.Clamp(currentSpeed, 0, maxspeed);
// also fake some friction
rb2d.velocity = rb2d.velocity * 0.96f;
}
// always apply the force, it may be 0 though.
rb2d.AddForce(new Vector2(movingDirection, 0) * currentSpeed;
}
}
Maybe it works better when setting velocity instead of adding force with this approach. But you may get the point: Instead of instantly stopping to add force when the key is released, we simply decrease a variable currentspeed and continue to work with that until we stop. Since horizontal is getting 0 quickly after releasing the key, I added a helper variable to remember the direction we were going before releasing the key called movingDirection.
Also a nice-to-know tip: Try to do all Input... Calls in Update(), save states in variables that you then use in FixedUpdate(). Because otherwise, you may run into problems, when things like Input.GetButtonDown() is true for 2-3 FixedUpdate Calls, but you want things to happen once per click/press like shooting.

Related

I wrote code about the player's jump but it doesnt work

this is the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
private Rigidbody2D Rig;
public float speed = 5;
public float fallspeed = 2.5f;
public float jamp = 1;
void Start()
{
Rig = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
Rig.velocity = Vector2.up * jamp;
}
if (Rig.velocity.y < 0)
{
speed = 2.5f;
Rig.velocity += Vector2.up * Physics2D.gravity.y * (fallspeed -1) * Time.deltaTime;
}
}
}
a friend gave me the code so I don't know where the problem is because I just started programing
The speed is to move slower to the sides in the air...
You dont have any keyCode to use you jump ?
if (Input.GetKeyDown(KeyCode.W))
{
Rig.velocity = Vector2.up * jamp;
}
Do you want to use this part to make your character Jump ? When you press "w", maybe you have to increase the value of "Jamp" because Vector2.up * 1 won't change something.
Since jamp only runs in one frame, it requires a high number. Increase the jamp number to about 300.

How to make the character move a certain distance when a button is pressed or tapped

So I'm working on a 2D game right now just to learn different stuff or codes related to making 2D games.
So I've come to a trouble where I got curious on how to make a character move a certain distance like per say 1 block per tap of button. I will give an example here. So take imagine the grid as a land.
Move a certain distance.
This one is the one my character is doing with my current code
and here's my movement code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keycontrol : MonoBehaviour
{
private float moveSpeed;
private Rigidbody2D rb2d;
private Vector2 change;
private Animator animator;
bool isXMoving;
bool isYMoving;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
}
void Update()
{
change.x = Input.GetAxisRaw("Horizontal");
change.y = Input.GetAxisRaw("Vertical");
if (Mathf.Abs(change.x) > Mathf.Abs(change.y))
{
change.y = 0;
}
else
{
change.x = 0;
}
animator.SetFloat("walk_right", change.x);
animator.SetFloat("walk_left", -change.x);
animator.SetFloat("walk_down", -change.y);
animator.SetFloat("walk_up", change.y);
}
void FixedUpdate()
{
rb2d.MovePosition(rb2d.position + change * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 150;
animator.speed = 1.5f;
}
else
{
moveSpeed = 70;
animator.speed = 1f;
}
}
}
Thanks a lot for help
I think the problem is just your movement speed. You multiply your speed with Time.fixedDeltaTime but that isn't necessary because that value will be constant. Instead, try just setting the speed to 1 and remove the Time.fixedDeltaTime.
Note: Time.deltaTime is used to make the character move a certain amount per frame because the shorter the time between frames, the less the character will move. Time.fixedDeltaTime stays constant because it is the time between each physics frame.
If I'm understanding correctly, the reason it keeps moving is because the input stays greater than zero. You could add a variable to check if the keys are already down to stop the movement.
There are two options here I think,
Make the user click everytime then want to move (press key, lift finger, press key, etc)
Add a timer to make it move every Nth second
For (1) we could just add an variable to say we are moving already.
//Changes IsXMoving and IsYMoving to a single boolean
bool isMoving = false;
///Start, Update, etc
void FixedUpdate()
{
//Check if we are already moving - if we are not, update movement
if (!isMoving)
{
rb2d.MovePosition(rb2d.position + change * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 150;
animator.speed = 1.5f;
}
else
{
moveSpeed = 70;
animator.speed = 1f;
}
}
//Check we are moving by getting the magnitude - if it zero, we are still
isMoving = (change.magnitude != 0);
}
The second option (2) would basically replace this with a basic timer.
//Removed IsXMoving and IsYMoving
//lastMove will store the time we last allowed movement and delay is
//the minimum time between movements in seconds
float lastMove;
float delay = 1; //1 second
void FixedUpdate()
{
//Check if enough time has passed to be allowed to move
if (lastMove + delay < Time.time)
{
rb2d.MovePosition(rb2d.position + change * moveSpeed * Time.fixedDeltaTime);
if(Input.GetKey("left shift"))
{
moveSpeed = 150;
animator.speed = 1.5f;
}
else
{
moveSpeed = 70;
animator.speed = 1f;
}
//Only update the time if we are moving
if (change.magnitude > 0)
lastMove = Time.time;
}
}

Make a Tank Aim Properly

Hi I am trying to make my tank fire, but it doesn't seem to work.
My tank's gun has a firing point which is used to fire the object. FirePoint is the point from which the laser beam is instantiated. When I turn my turret though the point goes off. The point is a child of the gun turret. What do I need to do? If I haven't explained it enough, please ask and I will try my best to help.
This is my player controller script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float Speed = 0;
public float MaxSpeed;
public float TurnSpeed;
public float AccelRate = 1;
public float BrakeSpeed = 1;
public GameObject LaserBeam;
public GameObject FirePoint;
public Vector3 Offset;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Increase forward when up arrow pressed
if (Input.GetKey(KeyCode.UpArrow))
{
Speed = Speed + AccelRate;
}
// Move backward when down arrow pressed
if (Input.GetKey(KeyCode.DownArrow))
{
Speed = Speed - AccelRate;
}
// Turn when left arrow pressed
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(Vector3.down * Time.deltaTime * TurnSpeed);
}
// Turn when right arrow pressed
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(Vector3.up * Time.deltaTime * TurnSpeed);
}
// Reset vehicle rotation
if (Input.GetKey(KeyCode.Return))
{
transform.eulerAngles = new Vector3(0, 0, 0);
}
// Press the brakes
if (Input.GetKey(KeyCode.Space) && (Speed > 0 || Speed < 0))
{
Speed = Speed - BrakeSpeed;
if (Speed < 0) { Speed = 0; }
}
//Ensure vehicle does not pass the maxspeed
if (Speed > MaxSpeed)
{
Speed = MaxSpeed;
}
//Move vehicle
transform.Translate(Vector3.right * Time.deltaTime * Speed);
if (Input.GetKey(KeyCode.UpArrow) == false && Speed > 0)
{
Speed = Speed - AccelRate;
}
//Fire
if (Input.GetKeyDown(KeyCode.F))
{
Instantiate(LaserBeam, FirePoint.transform.position + Offset, FirePoint.transform.rotation);
}
}
}
I fixed it! I simply set the offset to 0,0,0 and it worked.

How can I change a bullet shooting speed and keep the bullet shooting distance using physics?

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEditor;
using UnityEngine;
public class ShootBullets : MonoBehaviour
{
public float bulletDistance;
public bool automaticFire = false;
public float fireRate;
public Rigidbody bullet;
private float gunheat;
private bool shoot = false;
private GameObject bulletsParent;
private GameObject[] startpos;
// Start is called before the first frame update
void Start()
{
bulletsParent = GameObject.Find("Bullets");
startpos = GameObject.FindGameObjectsWithTag("Pod_Weapon");
}
void Fire()
{
for (int i = 0; i < startpos.Length; i++)
{
Rigidbody bulletClone = (Rigidbody)Instantiate(bullet, startpos[i].transform.position, startpos[i].transform.rotation, bulletsParent.transform);
bulletClone.velocity = transform.forward * bulletDistance;
// The bullet or any ammo/weapon should be on Y rotation = 0
Destroy(bulletClone.gameObject, 0.5f);
}
}
// Update is called once per frame
void Update()
{
if (automaticFire == false)
{
if (Input.GetMouseButtonDown(0))
{
Fire();
}
}
else
{
if (shoot == true)
{
Fire();
shoot = false;
}
}
if (gunheat > 0) gunheat -= Time.deltaTime;
if (gunheat <= 0)
{
shoot = true;
gunheat = fireRate;
}
}
}
I want to keep the distance like in this line :
bulletClone.velocity = transform.forward * bulletDistance;
but also to control the bullet speed. maybe it's a problem when using physics ?
my problem is that the bullets shot too fast.
the question is if it's possible to control the speed and keep the distance using physics ?
and does the function Fire should be called from Update or FixedUpdate ?
I meant something different with "over lifetime" but it doesn't matter. The speed is currently only set once so it is only dependent on the distance you shot the bullet from. Not the distance left to the target.
If you want to keep distance in the equation but decrease the result, have you thought about dividing the speed? IE add something like this
bulletClone.velocity = transform.forward * bulletDistance / 3;
you can also compare the speed to a maximum value and decide on which to pick IE
if(bulletDistance < 30)
{
bulletClone.velocity = transform.forward * bulletDistance;
}
else
{
bulletClone.velocity = transform.forward * 30
}
You can set the speed to anything you want.

How to program a bunch of 1st person animations at different speeds

I have made 4 different types of animation clips in an animator for an an empty gameobject called "Animator". The main camera is a child of this.
The animations feature a running cycle, a walking cycle, a crouch cycle, and an idle cycle. They all have a trigger that let's them play.
How am I able to measure the speed of the player and execute these animations when the player reaches a certain speed. I have found someone else trying to do this and it works but only for idle and walk. But unfortunately I can't get the sprint and crouch to work. I'm not sure what to do, either have the sprint and crouch animations or just change the speed of the walk animation depending on whether the player is sprinting or crouching. I'll leave a comment where the code I found is.
Here's what I have in my player controller (thge trigger stop is for the idle animation):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
Animator _ar;
public float speed;
[Range(-5, -20)]
public float gravity = -9.81f;
public float sprintSpeed = 6f;
public float walkSpeed = 4f;
public float crouchSpeed = 2f;
public float standHeight = 1.6f;
public float crouchHeight = 1f;
Vector3 velocity;
bool isGrounded;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
public Light _l;
//Set this to the transform you want to check
public Transform objectTransfom;
private float noMovementThreshold = 0.0001f;
private const int noMovementFrames = 1;
Vector3[] previousLocations = new Vector3[noMovementFrames];
public bool isMoving;
//Let other scripts see if the object is moving
public bool IsMoving
{
get { return isMoving; }
}
void Awake()
{
//For good measure, set the previous locations
for (int i = 0; i < previousLocations.Length; i++)
{
previousLocations[i] = Vector3.zero;
}
}
void Start()
{
_ar = GameObject.Find("Animator").GetComponentInChildren<Animator>();
}
// Update is called once per frame
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
//Below here is the code I found. The if statements for isMoving, is what I put in to see if
//this worked.
//Store the newest vector at the end of the list of vectors
for (int i = 0; i < previousLocations.Length - 1; i++)
{
previousLocations[i] = previousLocations[i + 1];
}
previousLocations[previousLocations.Length - 1] = objectTransfom.position;
//Check the distances between the points in your previous locations
//If for the past several updates, there are no movements smaller than the threshold,
//you can most likely assume that the object is not moving
for (int i = 0; i < previousLocations.Length - 1; i++)
{
if (Vector3.Distance(previousLocations[i], previousLocations[i + 1]) >= noMovementThreshold)
{
//The minimum movement has been detected between frames
isMoving = true;
break;
}
else
{
isMoving = false;
}
}
if(isMoving == true)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
speed = sprintSpeed;
_ar.SetTrigger("WalkSprint");
}
else if (Input.GetKeyUp(KeyCode.LeftControl))
{
speed = crouchSpeed;
_ar.SetTrigger("WalkCrouch");
//transform.localScale = new Vector3(0.8f, 0.5f, 0.8f);
}
else
{
speed = walkSpeed;
_ar.SetTrigger("Walk");
//transform.localScale = new Vector3(0.8f, 0.85f, 0.8f);
}
}
else
{
_ar.SetTrigger("Stop");
}
}
}
Unfortunately, as with many issue in Game Dev, this could be a number of different issues (or all of them!). Here is where you can start to debug:
Check your error log to see if there is anything obvious that jumps out at you, like a bad reference to a Game Object/Componenet.
Watch the animator. You should be able to have the Animator open, side-by-side with your game window while the game is running. You should be able to see the animations running and transitioning. See if something is not linked properly, or if an animation time is configured incorrectly, etc.
Add some debug statements, like outputting the current trigger being set. I would even verify that your inputs are configured correctly. Maybe add some additional conditionals at the beginning that debug what inputs are being pressed.
As #OnionFan said, your Input check is for KeyUp for the Crouch key. That should probably be KeyDown.

Categories