I am working on a movement script for my 2D platformer, and this code stopped working as soon as I moved the AddForce command to FixedUpdate rather than Update. It will still print the Debug.Log, and it will print the correct value of the Movment Variable, but the Rigidbody does not move at all when I use the arrow keys in-game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerMovment : MonoBehaviour
{
float hInput;
float moveSpeed = 3;
float accel = 1f;
float decel;
float Movment;
[SerializeField] Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
decel = accel * -1f;
}
// Update is called once per frame
void Update()
{
calcMovment();
}
void calcMovment()
{
if (Input.GetKey(KeyCode.LeftShift))
{
hInput = Input.GetAxis("Horizontal") * moveSpeed * 1.5f;
}
else
{
hInput = Input.GetAxis("Horizontal") * moveSpeed;
}
float targetSpeed = hInput * moveSpeed;
//Debug.Log(targetSpeed);
float speedDiff = targetSpeed - rb.velocity.x;
//Debug.Log(speedDiff);
float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? accel : decel;
//Debug.Log(accelRate);
Movment = Mathf.Pow(Mathf.Abs(speedDiff) * accelRate, 0.5f) * Mathf.Sign(speedDiff);
//Debug.Log(Movment);
}
void FixedUpdate()
{
Debug.Log(Movment);
rb.AddForce(Movment * Vector2.right);
//Debug.Log(rb.velocity.x);
}
}
The problem begins in these 2 lines of code:
float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? accel : decel;
Movment = Mathf.Pow(Mathf.Abs(speedDiff) * accelRate, 0.5f) * Mathf.Sign(speedDiff);
accelRate becomes negative in one moment which leads to the negative base in in the Mathf.Pow() the second line, and according to the official MSDN documentation (here), if x < 0 but not NegativeInfinity; y is not an integer, NegativeInfinity, or PositiveInfinity -> NaN, and in your case x is Mathf.Abs(speedDiff) * accelRate and it's negative
Related
Im trying to make a simple FPS player movement with rigid body. The code below works for moving with WASD but for jumping its a bit weird. When pressing space, the character jumps so little and kind of jerks. I'd figure there's something wrong with the Move() function because if I comment that part out, the jumping works fine.
public LayerMask groundMask;
public Transform groundCheck;
public Rigidbody rb;
[Space]
public float speed;
public float jump;
private float x;
private float z;
private void Update()
{
Move();
Jump();
}
void Move()
{
x = Input.GetAxis("Horizontal");
z = Input.GetAxis("Vertical");
Vector3 move = (transform.right * x + transform.forward * z) * speed * Time.deltaTime;
rb.velocity = move;
}
void Jump()
{
if (Input.GetKeyDown(KeyCode.Space) && IsGrounded())
{
rb.AddForce(Vector3.up * jump, ForceMode.Impulse);
}
}
bool IsGrounded()
{
return Physics.CheckSphere(groundCheck.position, 0.1f, groundMask);
}
Well in Move you hard overwrite the velocity.
You rather want to keep the Y axis.
Also when dealing with a velocity this already is a value per second so here you don't want to apply Time.deltaTime.
void Move()
{
x = Input.GetAxis("Horizontal");
z = Input.GetAxis("Vertical");
var move = (transform.right * x + transform.forward * z) * speed;
move.y = rb.velocity.y;
rb.velocity = move;
}
in general in order to not move faster diagonal I would rather suggest
// This will make sure that the total magnitude of the vector is maximum 1
var input = Vector3.ClampMagnitude(transform.right * x + transform.forward * z, 1f);
move = input * speed;
move.y = rb.velocity.y;
rb.velocity = move;
I have a Player (made out of an cylinder, some FirstCam, SecondCam and ThirdCam, for switching views when pressing a certain key - doesn't matter), which is located on a cube (wide enough to take a walk on it). There's nothing else below the cube.
This is how it looks like:
This is the Player's structure:
This is the inspector for Player:
I have the following script ResetToInitial.cs, attached to my Player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResetToInitial : MonoBehaviour {
Vector3 pos;
void Start() {
pos = transform.position;
}
void Update() {
if (transform.position.y < -10) {
transform.position = pos;
}
}
}
and also some movement script PlayerMovement.cs that allows him to move up, down, left, right, jump and sprint.
This is PlayerMovement.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerMovement : MonoBehaviour {
public CharacterController controller;
Vector3 velocity;
bool isGrounded;
public Transform groundCheck;
public LayerMask groundMask;
public TextMeshPro State;
public TextMeshPro State2;
public TextMeshPro State3;
// Start is called before the first frame update
void Start() {
}
// Update is called once per frame
void Update() {
float groundDistance = 0.4f;
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");
float g = -20f;
float jumpHeight = 1f;
float speed = 6f;
if (Input.GetKey(KeyCode.LeftShift)) {
speed = 8f;
State.text = "running mode";
State2.text = "running mode";
State3.text = "running mode";
} else {
speed = 5f;
State.text = "walking mode";
State2.text = "walking mode";
State3.text = "walking mode";
}
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
if (Input.GetButton("Jump") && isGrounded) {
velocity.y = Mathf.Sqrt(jumpHeight * -2f * g);
}
velocity.y += g * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
ResetToInitial.cs is intended to teleport the Player to the initial position (back on the cube, the position recorded when the scene loads), after he falls of the cube. The problem is transform.position won't move the player anywhere. It won't do anything. I tried to output something in the last if to see if it works, and the output was printed, but still no teleportation happened.
What could be the problem?
Here's my code, and, before anybody says it, I do not want to use translate or a character controller or any of that. Basically, with my current code, as soon as I stop holding any of the input keys, my character slides all over the place. How can I counteract this? By the way, a lot of these values defined at the beginning I have changed in the editor.
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] Rigidbody rb;
[SerializeField] float speed = 10f;
[SerializeField] float jumpForce = 1;
[SerializeField] float distanceFromGround = .5f;
[SerializeField] float maxSpeed = 1;
float currSpeed;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float x = Input.GetAxisRaw("Horizontal") * currSpeed;
float y = Input.GetAxisRaw("Vertical") * currSpeed;
if(Input.GetAxisRaw("Jump") == 1 && Grounded())
{
rb.AddForce(Vector3.up * jumpForce);
}
Vector3 movePos = transform.right * x + transform.forward * y;
Vector3 newMovePos = new Vector3(movePos.x, 0, movePos.z);
rb.AddForce(newMovePos);
}
private void FixedUpdate()
{
currSpeed = speed;
if (!Grounded())
{
currSpeed = speed / 2;
}
if (Input.GetAxisRaw("Horizontal") != 0 && Input.GetAxisRaw("Vertical") != 0)
{
currSpeed = speed * .75f;
}
if(rb.velocity.magnitude > maxSpeed)
{
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
}
}
bool Grounded()
{
return Physics.Raycast(transform.position, Vector3.down, distanceFromGround);
}
}
You can stop all movements by making rigidbody kinematic if condition is met by simply adding rb.isKinematic =true/false;
Or directly affect rb velocity in update.
Sor example you'd have in your update
rb.velocity=slowedVelocity;
so whenever you'd not be adding any velocity you are reducing it.
Another thing you migth be asking is to jsut add constraints in your editor so player is not moving and rotating in ways you do not waint it to do.
If I move forward while looking up my player jumps or at least attempts to fly. If I press Space bar and do move forward while looking up my player jumps even higher. I honestly have no idea on whats's going on. My prediction is the forward. If I look up Forward is relative to where I'm looking.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class P_MOVEMENT : MonoBehaviour
{
private float ACCELERATION = 10.0f;
private float GRAVITY = -5.0f;
private float SPEED = 5.0f;
private float RUNNING_SPEED = 2.0f;
private float JUMP_IMPULSE = 2.5f;
private bool isRunning = false;
CharacterController P_CC;
Vector3 P_MOVE;
//Camera Moving Mouse
private float X_AXIS = 0.0f;
private float Y_AXIS = 0.0f;
private float CAMERA_SPEED = 2.0f;
// Start is called before the first frame update
void Start()
{
P_CC = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if(P_CC.isGrounded)
{
// Player Movement
P_MOVE = transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal");
// Special Cases Check
// Running
isRunning = ( Input.GetKey(KeyCode.LeftShift) ) ? true : false;
P_MOVE = (isRunning) ? P_MOVE * SPEED * RUNNING_SPEED : P_MOVE * SPEED;
// Jumping
if(Input.GetAxis("Jump") > 0)
{
P_MOVE += Vector3.up * JUMP_IMPULSE;
}
}
else
{
P_MOVE += Vector3.up * GRAVITY * Time.deltaTime;
}
// Player Camera Movement
X_AXIS += CAMERA_SPEED * Input.GetAxis("Mouse X");
Y_AXIS -= CAMERA_SPEED * Input.GetAxis("Mouse Y");
// Restrict 90 Degree Up and Down
Y_AXIS = Mathf.Clamp(Y_AXIS, -60f, 90f);
// Update Rotation
transform.eulerAngles = new Vector3(Y_AXIS, X_AXIS, 0.0f);
}
void FixedUpdate()
{
P_CC.Move(P_MOVE * Time.deltaTime);
}
}
You are probably right. Your transform.forward is about the local GameObject coordinates instead of the global ones.
You could try to update only transform.forward.x and transform.forward.z. So you will ignore transform.forward.y. This way the player should not move up.
Something like this:
P_MOVE = transfrom.forward.x * Input.GetAxis("Vertical") + transform.forward.z * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal");
i have a weird glitch, when i walk down from a corner (i dont press jump), the player will falling down with very fast speed. If i jump, then everything goes normal. (Its Quill18 FPS controller, i learn from there so thats why i dont use the built in controller instead)
using UnityEngine;
using System.Collections;
[RequireComponent (typeof(CharacterController))]
public class FirstPersonController : MonoBehaviour
{
public float movementSpeed = 5.0f;
public float mouseSensitivity = 5.0f;
public float jumpSpeed = 20.0f;
float verticalRotation = 0;
public float upDownRange = 60.0f;
float verticalVelocity = 0;
CharacterController characterController;
// Use this for initialization
void Start()
{
// Screen.lockCursor = true;
characterController = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
// Rotation
float rotLeftRight = Input.GetAxis("Mouse X") * mouseSensitivity;
transform.Rotate(0, rotLeftRight, 0);
verticalRotation -= Input.GetAxis("Mouse Y") * mouseSensitivity;
verticalRotation = Mathf.Clamp(verticalRotation, -upDownRange, upDownRange);
Camera.main.transform.localRotation = Quaternion.Euler(verticalRotation, 0, 0);
// Movement
float forwardSpeed = Input.GetAxis("Vertical") * movementSpeed;
float sideSpeed = Input.GetAxis("Horizontal") * movementSpeed;
verticalVelocity += Physics.gravity.y * Time.deltaTime;
if (characterController.isGrounded && Input.GetButton("Jump"))
{
verticalVelocity = jumpSpeed;
}
Vector3 speed = new Vector3(sideSpeed, verticalVelocity, forwardSpeed ;
speed = transform.rotation * speed;
characterController.Move(speed * Time.deltaTime);
}
}
The problem is that every frame you're running this line:
verticalVelocity += Physics.gravity.y * Time.deltaTime;
Thus, you're gaining "momentum" each second, and it wont stop ever until you jump because you're "resetting" the Y velocity to a normal value. I've ran into this problem before, and it can be fixed simply by only adding the Y velocity when you're not grounded. You can use Raycast to check if you have ground, and if you dont, increase verticalVelocity by that amount.