I'm working on unity and am trying to give my player character a jump button however when he jump he teleport up not jumping
private float speed = 10f;
private bool canjump = false;
private Rigidbody rb;
private float jump =100f;
private float movementX;
private float movementy;
public bool isJumping;
private float jumpdecay =20f;
public float fallmultipler = 2.5f;
public float lowjumpmultiplier = 2f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get();
movementX = movementVector.x;
}
private void Update()
{
Vector3 movement = new Vector2(movementX, 0);
rb.velocity = movement * speed;
if (Input.GetKeyDown(KeyCode.Space))
{
canjump = true;
}
}
void OnTriggerEnter(Collider collision)
{
if(collision.gameObject.tag == "ground")
{
isJumping = false;
}
}
void OnTriggerExit(Collider collision)
{
isJumping = true;
}
private void FixedUpdate()
{
if (canjump & isJumping == false)
{
rb.velocity = Vector3.up * jump;
canjump = false;
}
}
It's happen because on Update you change your velocity including the y and then every frame your y axis of the velocity vector become 0.
to fix that you should save your y and replace after modify your velocity.
change inside your code in the update method this:
Vector3 movement = new Vector2(movementX, 0);
rb.velocity = movement * speed;
with this:
Vector3 movement = new Vector2(movementX, 0);
float currentVelocity = rb.velocity.y;
rb.velocity = movement * speed;
rb.velocity = new Vector3(rb.velocity.x, currentVelocity, rb.velocity.z);
if it's help you, please mark this answer as the good answer, if not please let me know and I will help you.
You are reseting the y velocity inside of update
Vector3 movement = new Vector2(movementX, 0);
rb.velocity = movement * speed;
Try someting like
rb.velocity = new Vector2(movementX * speed, rb.velocity.y)
rb.velocity.y returns current y velocity, because of that said velocity remains unchanged, allowing for the jump to work normally
Related
I have drag and shoot script in my unity game(like in angry birds).It works correctly if I quickly release the mouse button, but when I hold it for a long time and then release , the object falls to the cursor level and its velocity(which is calculated by object.position - dragStartPosition) become too much.What's wrong with it?
I have these methods:
private Vector3 startPositionOnDrag;
public float throwForce;
private Vector2 initVelocity;
public bool isMoving = false;
public Rigidbody2D rigidbody;
private void OnMouseDown()
{
startPositionOnDrag = new Vector3(transform.position.x, transform.position.y, 0);
}
private void OnMouseDrag()
{
if (!isMoving)
{
Vector3 mousePosVector = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 diff = startPositionOnDrag - mousePosVector;
if (diff.magnitude < 1.5f)
{
transform.position = new Vector3(mousePosVector.x, mousePosVector.y, 0);
}
else
{
float diffLength = diff.magnitude;
Vector3 targetPosition = startPositionOnDrag - ((startPositionOnDrag - mousePosVector) * 1.5f/diffLength);
transform.position = new Vector2(targetPosition.x, targetPosition.y);
}
}
}
private void OnMouseUp()
{
if (!isMoving)
{
Vector2 diff = startPositionOnDrag - transform.position; //smthg wrong in magnitude
Vector2 directionToMove = (startPositionOnDrag - transform.position).normalized; //correct
initVelocity = directionToMove * throwForce * Mathf.Sqrt(diff.magnitude);
rigidbody.velocity = initVelocity;
isMoving = true;
}
}
I am trying to make a first-person game in Unity but I keep having issues with my character controller. The player keeps rotating when it collides with objects that have physics (Or rigidbody)
It doesn't rotate when it collides with objects that don't have physics.
It's not my mouse because my MouseX and Y Values aren't changing.
Here is the code for the Player
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class PlayerControllerRB : MonoBehaviour
{
public float speed = 10f;
public float jumpHeight = 4.65f;
[SerializeField] private Rigidbody rb;
private PlayerInput playerInput;
private PlayerInput.OnFootActions onFoot;
[SerializeField] private Camera cam;
public float xSensitivity = 8f;
public float ySensitivity = 8f;
private float xRotation;
private float yMovement;
private float hMovement;
[SerializeField] private Transform Feet;
[SerializeField] public LayerMask Ground;
private void Awake()
{
rb = GetComponent<Rigidbody>();
playerInput = new PlayerInput();
onFoot = playerInput.onFoot;
onFoot.Jump.performed += ctx => Jump();
}
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
#region
private void OnEnable()
{
playerInput.Enable();
onFoot.Enable();
}
private void OnDisable()
{
playerInput.Disable();
onFoot.Disable();
}
#endregion
private void FixedUpdate()
{
ProcessMove(onFoot.Movement.ReadValue<Vector2>());
}
private void Update()
{
ProcessLook(onFoot.Look.ReadValue<Vector2>());
}
void ProcessMove(Vector2 input)
{
Vector3 MoveDirection = Vector3.zero;
hMovement = input.x;
yMovement = input.y;
MoveDirection = transform.forward * yMovement + transform.right * hMovement;
//MoveDirection.y = rb.velocity.y;
Debug.Log(MoveDirection * speed);
rb.AddForce(MoveDirection * speed, ForceMode.Acceleration);
}
void Jump()
{
Ray ray = new Ray(Feet.position, Vector3.down);
RaycastHit info;
if(Physics.Raycast(ray, out info, 0.3f, Ground))
{
rb.AddForce(Vector3.up * jumpHeight, ForceMode.Impulse);
}
}
void ProcessLook(Vector2 input)
{
float MouseY = input.y;
float MouseX = input.x;
xRotation -= (MouseY * Time.deltaTime) * ySensitivity;
xRotation = Mathf.Clamp(xRotation, -80f, 80f);
cam.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
transform.Rotate(Vector3.up * (MouseX * Time.deltaTime) * xSensitivity);
}
}
I tried freezing the y rotation but then I get a jittry camera.
Can anyone help me? It would also be nice if you had any recommendations to improve the controller.
Please comment if you need any more information. Sorry if the post is junk, I'm new to Stackoverflow
Well, you said It doesn't rotate when it collides with objects that don't have physics. In order to use the colliders one of them has to have a rigibody component. So if that's the case maybe is the script that is inside the oncollisionenter causing the problems. But I don't see any oncollisionenter script here
i have been recreating my jump code, i have it all done but i can't add force or anything else.
Here's my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class pBeh : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
public Rigidbody rb;
public float jumpSpeed = 5.2f;
private Vector3 movingDirection = Vector3.zero;
public CharacterController controller;
public float speed;
float turnSmoothVelocity;
public float turnSmoothTime;
public bool canJump = false;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * 10;
float vertical = Input.GetAxis("Vertical") * 10;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
if (canJump == true && Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Jumped");/*
transform.Translate(Vector3.up * 5.0f * Time.deltaTime);
rb.AddRelativeForce(Vector3.up * 8.0f);
rb.AddForce(Vector3.up * 8.0f)
i have tried a lot more, but it just doesn't work.
The sphere (Player) does nothing or shakes.
*/
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "enemy")
{
SceneManager.LoadScene("SampleScene");
}
}
void FixedUpdate()
{
if ((controller.collisionFlags & CollisionFlags.Below) != 0)
{
//Debug.Log("ground");
canJump = true;
}
else
{
canJump = false;
}
}
As i said it works just fine i just can't find reason why i cannot jump.
I have all character controller right and rigidbody too. If you could help i would be happy.
Btw i am beginner so i copied movement to be same as camera. Thanks!
From what I know, rigidbody and character controller do not work together (on the same object) so you have to choose one or the other, if you are using rigidbody then a ground check or similiar stuff would not be necessary since rigidbody is using unity physicis system so a lot of the stuff would be already done for you to simulate physics but you should still read thru the document
So i have a simple scene in unity, a player with a parallax background and a Tilemap as a ground, as well as some very simple post processing. I know this isn't a The minute i move, there is a consistent stutter just under ever second. I'm not sure whether it's to do with my player movement code, camera movement or anything else. I'm also using a Cinemachine virtual camera. My rigidbody interpolation is set to interpolate and collision detection set to continuous. Here's my player movement if this helps. Here is a sample of what it looks like, if you look at the background or the tilemap it's quite noticeable. https://youtu.be/h2rSheZWtKs
[SerializeField] private LayerMask groundLayerMask;
public float speed;
public float Jump;
public sword swordScript;
public GameObject swordSprite;
private float move;
private Rigidbody2D rb;
private BoxCollider2D boxCollider2d;
private bool facingRight;
public SpriteRenderer spr;
public Animator PlayerAnims;
public bool movementAllowed;
void Awake()
{
Application.targetFrameRate = 60;
Application.targetFrameRate = Screen.currentResolution.refreshRate;
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Start is called before the first frame update
void Start()
{
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void FixedUpdate()
{
if(movementAllowed == true)
{
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (isGrounded() && Input.GetButtonDown("Jump"))
{
rb.AddForce(new Vector2(rb.velocity.x, Jump));
}
}
}
void Update()
{
move = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (movementAllowed == true)
{
Flip(move);
if (move == 0)
{
PlayerAnims.SetBool("isRunning", false);
}
else
{
PlayerAnims.SetBool("isRunning", true);
}
}
}
private bool isGrounded()
{
float extraHeightText = .1f;
RaycastHit2D raycasthit2d = Physics2D.BoxCast(boxCollider2d.bounds.center, boxCollider2d.bounds.size, 0f, Vector2.down, extraHeightText, groundLayerMask);
Color rayColour;
if (raycasthit2d.collider != null)
{
rayColour = Color.green;
PlayerAnims.SetBool("isJumping", false);
}
else
{
rayColour = Color.red;
PlayerAnims.SetBool("isJumping", true);
}
Debug.DrawRay(boxCollider2d.bounds.center + new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, boxCollider2d.bounds.extents.y + extraHeightText), Vector2.right * (boxCollider2d.bounds.extents.x), rayColour);
return raycasthit2d.collider != null;
}
private void Flip(float move)
{
if (move > 0 && !facingRight || move < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
if (swordScript.isFollowing == true)
{
Vector3 swordScale = swordSprite.transform.localScale;
swordScale.x *= -1;
swordSprite.transform.localScale = swordScale;
}
}
}
You are setting rb.velocity in both the Update() and FixedUpdate() methods. I would try only using one of those.
On top of that, your jump check also re-applies the X velocity along with the upward force. So if you're jumping the player will be pushed forward at double speed.
You also have an error being outputted in the console about an Index being out of range... I would look into that.
Can you also post your code for the parallax background?
FixedUpdate is a method where you want to do everything physics, player-controller and simulation related.
Update is just for rendering-related fluff i.e. code of no real consequence other than making things look correctly.
Hence:
Move all your player/physics controller code to FixedUpdate.
Move bg parallax code to Update.
Use Time.deltaTime (in Update) and Time.fixedDeltaTime (in FixedUpdate) time steps when animating or interpolating between values.
Ad #3.: Although - as #Menyus noted (below) - Time.deltaTime is all you really need.
Time.fixedDeltaTime is for that extra intent explicitness (but was necessary in earlier unity versions).
I was hoping I could get some help! I've been trying to make a platformer using velocity to move but I can't find a good way to do jumping using the system. Every frame the velocity's y just resets itself and I don't know how to create a jump. I have tried using ForceMode.VelocityChange and I have tried to write out equations. The player falls extremely slowly even with gravity turned on.
playerBody.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange);
I have the same issues when I try to set the y velocity to change with gravity
float MoveDirectionY = jumpForce * Physics.gravity.y;
enter image description here
Nothing seems to be working here. When i play the game gravity still pulls the object down slowly but if i turn off gravity it doesnt pull the object down at all.
The game does log the statement letting me know that it does know the space button was pressed.alt text
I want to also provide my code here:
using System.Collections;
using System.Collections.Generic;
using System.Transactions;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private Rigidbody playerBody;
[SerializeField] private Vector3 inputVector;
[SerializeField] public float speed = 0.01f;
[SerializeField] public bool jump;
[SerializeField] private float turnSpeed = 45;
[SerializeField] public float jumpForce = 35000f;
[SerializeField] private bool isOnGround = true;
[SerializeField] float enemyPushForce = 100;
public int ingredient;
public GameManager gameManager;
public camSwitch cs;
public float horizontalInput;
public float verticalInput;
float playerFacingAngleY;
private GameObject FocalPoint;
// Start is called before the first frame update
void Start()
{
//Just making sure we have the rigid body of the game object the script is attached to so we can move it later
playerBody = gameObject.GetComponent<Rigidbody>();
FocalPoint = GameObject.Find("Focal Point");
}
// Update is called once per frame
//This is where the player script should be realizing we are using inputs
void Update()
{
horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");
playerFacingAngleY += horizontalInput * turnSpeed;
Vector3 playerFacingDirection = new Vector3(0, playerFacingAngleY, 0);
playerBody.rotation = Quaternion.Euler(playerFacingDirection);
float moveDirectionX = (FocalPoint.transform.position.x - gameObject.transform.position.x) *speed * verticalInput * Time.deltaTime;
float MoveDirectionY = jumpForce * Physics.gravity.y;
float moveDirectionZ = (FocalPoint.transform.position.z - gameObject.transform.position.z) * speed * verticalInput * Time.deltaTime;
Vector3 moveDirection = new Vector3(moveDirectionX, MoveDirectionY, moveDirectionZ);
playerBody.velocity = moveDirection;
if (Input.GetKeyDown(KeyCode.Space) && isOnGround == true)
{
playerBody.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange);
isOnGround = false;
print("player has jumped");
}
}
private void OnCollisionEnter(Collision collision)
{
isOnGround = true;
if (collision.gameObject.tag == "Enemy")
{
Debug.Log("Player ran into an enemy");
if (cs.inSky == true)
{
speed = 0;
}
else
{
speed = 10;
}
}
else if (collision.gameObject.tag == "Ingredient")
{
Debug.Log("Player collided with an ingredient");
collision.gameObject.SetActive(false);
ingredient++;
}
else if (collision.gameObject.tag == "Ground") {
isOnGround = true;
print("player has hit the ground");
}
}
}
Do not play with rigidbody in Update method. Use FixedUpdate() instead.
In addition, do not change velocity using rb.velocity = ... but use rigibody.AddForce() method. Try something like this:
void FixedUpdate() //using rigidbody? => ONLY FIXEDUPDATE
{
horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");
playerFacingAngleY += horizontalInput * turnSpeed;
Vector3 playerFacingDirection = new Vector3(0, playerFacingAngleY, 0);
playerBody.rotation = Quaternion.Euler(playerFacingDirection);
float moveDirectionX = (FocalPoint.transform.position.x - gameObject.transform.position.x) *speed * verticalInput * Time.deltaTime;
float moveDirectionZ = (FocalPoint.transform.position.z - gameObject.transform.position.z) * speed * verticalInput * Time.deltaTime;
Vector3 moveDirection = new Vector3(moveDirectionX, 0.0f, moveDirectionZ); //0.0f - just turn on gravity in rigidbody component or you can change it if you want some additional Vertical force
playerBody.AddForce(moveDirection, ForceMode.VelocityChange); //force mode change to whatever you want
if (Input.GetKeyDown(KeyCode.Space) && isOnGround == true)
{
playerBody.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange);
isOnGround = false;
print("player has jumped");
}
}