Jump in using Rigidbody or Character controller - unity3d

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

Related

Why is my character falling/leaning over on mouse click in unity?

My character using CharacterController seems to be falling over! Is it the rotation that's the issue? I've been hitting my head against the wall for a few days trying to get this solved. any thoughts?
an small vid of what's happening: https://imgur.com/a/AyPvLtm
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(CharacterController))]
public class Player : MonoBehaviour
{
[SerializeField] private float playerSpeed = 10f;
[SerializeField] private float rotationSpeed = 8f;
public float SpeedChangeRate = 10.0f;
private Camera mainCamera;
private Vector3 targetPosition;
private CharacterController characterController;
private Coroutine coroutine;
private int groundLayer;
private void Awake() {
mainCamera = Camera.main;
characterController = GetComponent<CharacterController>();
groundLayer = LayerMask.NameToLayer("Ground");
}
void Update()
{
if (Mouse.current.leftButton.isPressed) Move();
}
private void Move() {
Ray ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
Physics.Raycast(ray: ray, hitInfo: out RaycastHit hit);
if (hit.collider && hit.collider.gameObject.layer.CompareTo(groundLayer) == 0) {
if (coroutine != null) StopCoroutine(coroutine);
coroutine = StartCoroutine(PlayerMoveTowards(hit.point));
targetPosition = hit.point;
}
}
private IEnumerator PlayerMoveTowards(Vector3 target) {
while (Vector3.Distance(transform.position, target) > 0.1f) {
Vector3 destination = Vector3.MoveTowards(transform.position, target, playerSpeed * Time.deltaTime);
Vector3 direction = target - transform.position;
Vector3 movement = direction.normalized * playerSpeed * Time.deltaTime;
characterController.Move(movement);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction.normalized), rotationSpeed * Time.deltaTime);
yield return null;
}
}
}
The reason is that at close distances, the difference between the main player's Target and Pivot point becomes very small and the height will be effective in determining the direction. Just set the direction Y to 0 to solve the problem.
Vector3 direction = target - transform.position;
direction.y = 0;
Figured this out.
It was my capsule collider. I had it set to the X-Axis, causing the collider to be rotated 90 degrees.
So my character would move and then flip to the side. Updating the collider direct to be on the Y-Axis fixed the problem.

Camera keeps rotating

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

how do i make something which moves with Velocity jump in Unity?

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");
}
}

How to stop the player from jumping while in the air?

I don't want my player to jump in the air but I can't seem to find anything out.
This is what I have. They can jump, but they can jump forever and that's a problem.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
public bool alive;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start () {
rigidBody = GetComponent<Rigidbody2D> ();
// Use this for initialization
}
// Update is called once per frame
void Update () {
movement = Input.GetAxis ("Horizontal");
if (movement > 0f) {
rigidBody.velocity = new Vector2 (movement * speed, rigidBody.velocity.y);
}
else if (movement < 0f) {
rigidBody.velocity = new Vector2 (movement * speed, rigidBody.velocity.y);
}
else {
rigidBody.velocity = new Vector2 (0,rigidBody.velocity.y);
}
if(Input.GetButtonDown ("Jump")){
rigidBody.velocity = new Vector2(rigidBody.velocity.x,jumpSpeed);
}
}
}
An simple option is to maintain a boolean such as _inAir that gets set to true when the player first jumps, and to false when their RigidBody2D collides with the ground (see, e.g., OnCollisionEnter2D).
Then, the check if(Input.GetButtonDown ("Jump")){ becomes
if (!_inAir && Input.GetButtonDown("Jump")) {

Jittery movement of the camera when rotating AND moving - 2D top down Unity

I am making a 2d top down game where the player can rotate the camera around himself as he moves through the world.
Everything works fine when the player is moving around the world the camera follows him fine. if he standing still then the camera rotation also works very well. However as soon as I start to do both then there is a jittery in the camera that makes all other objects jitter besides the player.
Now in working with this problem I have found out that this could have to do with the fact that I use rigidbody2d.AddRelativeForce (so physics) to move the player and that his movements are checked in FixedUpdate.
https://forum.unity3d.com/threads/camera-jitter-problem.115224/ http://answers.unity3d.com/questions/381317/camera-rotation-jitterness-lookat.html
I have tried moving my camera rotation and the following scripts to LateUpdate, FixedUpdate, Update you name it. Nothing seems to work. I am sure that there is some sort of delay between movement of the camera and the rotation that is causing this. I am wondering if anyone has any feedback?
I have tried disabling Vsync, does not remove it entirely
I have tried interpolating and extrapolating the rigidbody and although there is a difference it does not remove it entirely. Ironically it seemd if I have it set to none, it works best.
Scripts:
To Follow character, script applied to a gameobject that has the camera as a child
public class FollowPlayer : MonoBehaviour {
public Transform lookAt;
public Spawner spawner;
private Transform trans;
public float cameraRot = 3;
private bool smooth = false;
private float smoothSpeed = 30f;
private Vector3 offset = new Vector3(0, 0, -6.5f);
//test
public bool changeUpdate;
private void Start()
{
trans = GetComponent<Transform>();
}
private void FixedUpdate()
{
CameraRotation();
}
private void LateUpdate()
{
following();
}
public void following()
{
Vector3 desiredPosition = lookAt.transform.position + offset;
if (smooth)
{
transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
}
else
{
transform.position = desiredPosition;
}
}
void CameraRotation()
{
if (Input.GetKey("q"))
{
transform.Rotate(0, 0, cameraRot);
}
if (Input.GetKey("e"))
{
transform.Rotate(0, 0, -cameraRot);
}
}
public void SetTarget(string e)
{
lookAt = GameObject.Find(e).GetComponent<Transform>();
}
}
The character Controller, script applied to the Player, is called in FixedUpdate
private void HandleMovement()
{
if (Input.GetKey("w"))
{
rigid.AddRelativeForce(Vector2.up * speed);
}
if (Input.GetKey("s"))
{
rigid.AddRelativeForce(Vector2.down * speed);
}
if (Input.GetKey("a"))
{
if (facingRight)
{
Flip();
}
rigid.AddRelativeForce(Vector2.left * speed);
}
if (Input.GetKey("d"))
{
if (!facingRight)
{
Flip();
}
rigid.AddRelativeForce(new Vector2(1,0) * speed);
}
}
Try to use Coroutines. I modified some of my scripts to be more familiar to Your code, tried it, and I didn't see any jittery. I hope that will help You.
Camera Class:
public class CameraController : MonoBehaviour {
[SerializeField]
Transform CameraRotator, Player;
[SerializeField]
float rotationSpeed = 10f;
float rotation;
bool rotating = true;
void Start()
{
StartCoroutine(RotatingCamera());
}
IEnumerator RotatingCamera()
{
while (rotating)
{
rotation = Input.GetAxis("HorizontalRotation");
CameraRotator.Rotate(Vector3.up * Time.deltaTime * rotation * rotationSpeed);
CameraRotator.position = Player.position;
yield return new WaitForFixedUpdate();
}
}
private void OnDestroy()
{
StopAllCoroutines();
}
}
Player Class:
public class PlayerMovement : MonoBehaviour {
[SerializeField]
float movementSpeed = 500f;
Vector3 movementVector;
Vector3 forward;
Vector3 right;
[SerializeField]
Transform CameraRotator;
Rigidbody playerRigidbody;
float inputHorizontal, inputVertical;
void Awake()
{
playerRigidbody = GetComponent<Rigidbody>();
StartCoroutine(Moving());
}
IEnumerator Moving()
{
while (true)
{
inputHorizontal = Input.GetAxis("Horizontal");
inputVertical = Input.GetAxis("Vertical");
forward = CameraRotator.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
Vector3 right = new Vector3(forward.z, 0, -forward.x);
movementVector = inputHorizontal * right + inputVertical * forward;
movementVector = movementVector.normalized * movementSpeed * Time.deltaTime;
playerRigidbody.AddForce(movementVector);
yield return new WaitForFixedUpdate();
}
}
}
I fixed this problem finally:
First I made my cameraRotation() and follow() into 1 function and gave it a better clearer name:
public void UpdateCameraPosition()
{
if (Input.GetKey("q"))
{
transform.Rotate(0, 0, cameraRot);
}
else if (Input.GetKey("e"))
{
transform.Rotate(0, 0, -cameraRot);
}
Vector3 desiredPosition = lookAt.transform.position + offset;
transform.position = desiredPosition;
}
I then called that function from the character controller straight after the handling of movement. Both calls (handleMovement & cameraPosition) in fixedUpdate.
void FixedUpdate()
{
HandleMovement();
cameraController.UpdateCameraPosition();
}
and the jittering was gone.
So it seems it was imply because there was a slight delay between the two calls as the previous posts I read had said. But I had failed to be able to properly Set them close enough together.
Hope this helps someone.