CharacterController jump in unity - unity3d

Hello I was trying to do movement script in Unity. Also I wanted to add jump, but everytime when I jump it moves up for like 0.025 on Y direction and stops the player in air*(if I am on 0 and I jump it moves on 0.02545 then 0.0543 etc...)* and I can spam Space to move player up. I added gravity but it looks it doesn't work.. I don't know how to fix it. I hope someone can help me with my problem...
Here is the function what I am using...
Vector3 moveDirection = Vector3.zero;
public float walkingSpeed = 10.0f;
public bool canJump = true;
public float jumpSpeed = 8.0f;
public float gravity = 10.0f;
CharacterController characterController;
void Movement()
{
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 right = transform.TransformDirection(Vector3.right);
float moveX = walkingSpeed * Input.GetAxis("Vertical");
float moveY = walkingSpeed * Input.GetAxis("Horizontal");
float MovementY = moveDirection.y;
moveDirection = (forward * moveX) + (right * moveY);
if (Input.GetButtonDown("Jump") && canJump)
{
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * Time.deltaTime);
}

Because you are resetting moveDirection every frame (when you call moveDirection = (forward * moveX) + (right * moveY) you aren't letting the gravity accumulate. You should instead save the vertical speed separately and add it every frame.
Something like the following:
Vector3 moveDirection = Vector3.zero;
public float walkingSpeed = 10.0f;
public bool canJump = true;
public float jumpSpeed = 8.0f;
public float gravity = 10.0f;
CharacterController characterController;
private float verticalSpeed;
void Movement()
{
float moveX = walkingSpeed * Input.GetAxis("Vertical");
float moveY = walkingSpeed * Input.GetAxis("Horizontal");
verticalSpeed -= gravity * Time.deltaTime;
if (Input.GetButtonDown("Jump") && canJump)
{
verticalSpeed = jumpSpeed;
}
characterController.Move((moveX * transform.forward + moveY * transform.right + verticalSpeed * transform.up)
* Time.deltaTime);
}
transform.forward is equivalent to transform.TransformDirection(Vector3.forward)

Related

When jumping, the rotation value becomes 0

this is my PlayerMovement script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float turnSmoothTime = 0.1f;
float turnSmoothVelocity;
public float Speed = 10f;
private Vector3 moveDirection;
public float groundDistance = 0.4f;
public float gravity = -9.81f;
public float jumpPower = 3.5f;
public float directionY;
bool isGrounded;
public Animator anim;
public Transform cam;
private void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
moveDirection = new Vector3(horizontal, 0f, vertical).normalized;
if (controller.isGrounded)
{
if (Input.GetKeyDown(KeyCode.Space))
{
directionY = jumpPower;
}
else
{
directionY = 0;
}
}
if (!controller.isGrounded)
{
directionY += gravity * Time.deltaTime;
}
moveDirection.y = directionY;
if (moveDirection.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(moveDirection.x, moveDirection.z) * Mathf.Rad2Deg;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
controller.Move(moveDirection * Speed * Time.deltaTime);
}
bool hasHorizontalInput = !Mathf.Approximately(horizontal, 0f);
bool hasVerticalInput = !Mathf.Approximately(vertical, 0f);
bool isWalking = hasHorizontalInput || hasVerticalInput;
}
}
I want to make smooth jump system using by characterController.
My code works fine in the ground state, but when I press space(for jump), it returns the current rotation y value to 0.
(I think this problem is because the jump's position value is y, but the movement's rotation value is also y.)
how do i solve it? I want the rotation value not to change even if I jump.
I solved.
It was a code execution order issue.
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized;
if (controller.isGrounded && Input.GetButton("Jump"))
{
movingDirection.y = jumpSpeed;
}
movingDirection.y -= gravity * Time.deltaTime;
controller.Move(movingDirection * Time.deltaTime * speed);
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
controller.Move(direction * speed * Time.deltaTime);
}

How to make jump faster when player is running?

I have a character controller movement where the player can walk, run and jump. However, I facing an issue with the jumping. When jumping while walking, the jump speed looks good. But when jumping while running, the jump speed is too slow compared to the run speed. How can I fix this?
Here is my code:
public class PlayerMovement : MonoBehaviour
{
[SerializeField] Transform playerCamera = null;
[SerializeField] float mouseSensitivity = 3.5f;
[SerializeField] float walkSpeed = 10.0f;
[SerializeField] float RunSpeed = 12.0f;
[SerializeField] float gravity = 9.81f;
[SerializeField] bool lockCursor = true;
[SerializeField] [Range(0.0f, 0.5f)] float moveSmoothTime = 0.3f;
public float jumpHeight = 3f;
Vector3 velocity;
public float verticalVelocity;
float cameraPitch = 0.0f;
CharacterController controller = null;
Vector2 currentDir = Vector2.zero;
Vector2 currentDirVelocity = Vector2.zero;
Vector2 currentMouseDelta = Vector2.zero;
Vector2 currentMouseDeltaVelocity = Vector2.zero;
void Start()
{
controller = GetComponent<CharacterController>();
if (lockCursor)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
void Update()
{
UpdateMouseLook();
UpdateMovement();
}
void UpdateMouseLook()
{
Vector2 targetMouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
currentMouseDelta = Vector2.SmoothDamp(currentMouseDelta, targetMouseDelta, ref currentMouseDeltaVelocity, mouseSmoothTime);
cameraPitch -= currentMouseDelta.y * mouseSensitivity;
cameraPitch = Mathf.Clamp(cameraPitch, -90.0f, 90.0f);
playerCamera.localEulerAngles = Vector3.right * cameraPitch;
transform.Rotate(Vector3.up * currentMouseDelta.x * mouseSensitivity);
}
void UpdateMovement()
{
Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
targetDir.Normalize();
currentDir = Vector2.SmoothDamp(currentDir, targetDir, ref currentDirVelocity, moveSmoothTime);
if (controller.isGrounded)
velocity.y = 0.0f;
velocity += (velocity.y < 0 ? Physics.gravity * 2 : Physics.gravity) * Time.deltaTime;
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * walkSpeed + Vector3.up * velocity.y;
if (Input.GetKeyDown(KeyCode.J) && controller.isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
velocity += (velocity.y < 0 ? Physics.gravity * 2 : Physics.gravity) * Time.deltaTime;
}
controller.Move(velocity * Time.deltaTime);
if ((Input.GetKey("left shift") || Input.GetKey("right shift")) && controller.isGrounded && !Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.DownArrow))
{
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * RunSpeed + Vector3.up * velocity.y;
controller.Move(velocity * Time.deltaTime);
}
}
I optimized the above code and removed some dublicate. I also noticed that the speed problem was due to the presence of isGrounded in the body of the running condition, which made running dependent on being on the ground. This is the player script:
public class Player : MonoBehaviour
{
[SerializeField] Transform playerCamera = null;
[SerializeField] float mouseSensitivity = 3.5f;
[SerializeField] float walkSpeed = 10.0f;
[SerializeField] float runSpeed = 12.0f;
[SerializeField] float gravity = 9.81f;
[SerializeField] bool lockCursor = true;
[SerializeField] [Range(0.0f, 0.5f)] float moveSmoothTime = 0.3f;
public float jumpHeight = 3f;
Vector3 velocity;
private float verticalVelocity;
private Vector3 inputVector;
float cameraPitch = 0.0f;
CharacterController controller = null;
Vector2 currentDir = Vector2.zero;
Vector3 currentDirVelocity = Vector3.zero;
Vector2 currentMouseDelta = Vector2.zero;
Vector2 currentMouseDeltaVelocity = Vector2.zero;
void Start()
{
controller = GetComponent<CharacterController>();
if (lockCursor)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
void Update()
{
UpdateMouseLook();
UpdateMovement();
}
void UpdateMouseLook()
{
var targetMouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
currentMouseDelta = Vector2.SmoothDamp(currentMouseDelta, targetMouseDelta, ref currentMouseDeltaVelocity, moveSmoothTime);
cameraPitch -= currentMouseDelta.y * mouseSensitivity;
cameraPitch = Mathf.Clamp(cameraPitch, -90.0f, 90.0f);
playerCamera.localEulerAngles = Vector3.right * cameraPitch;
transform.Rotate(Vector3.up * currentMouseDelta.x * mouseSensitivity);
}
void UpdateMovement()
{
// jumping
var isGrounded = Physics.Raycast(transform.position, Vector3.down, 1.1f) && velocity.y <= 0;
if (isGrounded)
{
velocity.y = Input.GetKeyDown(KeyCode.Space) ? Mathf.Sqrt(jumpHeight) : 0f;
}
else
{
velocity += (velocity.y < 0 ? Physics.gravity * 2 : Physics.gravity) * Time.deltaTime;
}
controller.Move(velocity);
// movement
inputVector = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;
var smoothDamp = Vector3.SmoothDamp(inputVector, inputVector, ref currentDirVelocity, moveSmoothTime);
var runKey = (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) &&
!Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.DownArrow);
controller.Move(smoothDamp * (runKey ? runSpeed : walkSpeed) * Time.deltaTime);
}
}
Also, these settings were suitable for a height 2 capsule:
If your character is greater than 2, adjust the length of the ground detection raycast accordingly because the controller.isGrounded condition does not always work.
When you are using character controller you need to do all the calculations for all the situations.
To get the result you are looking for you can do a calculation beetween jump and walking speed.
Another way is to use Rigid body (lock rotations) and add forces for jump and move.
both examples here: https://www.youtube.com/watch?v=b1uoLBp2I1w

Unity Player floating down instead of falling

for some reason my Player is reacting really weirdly to the gravity, he falls normally for about 1 second then just floats down the rest of the way really slowly. increasing the gravity doesnt change anything either. Im at a loss.
Any help would be greatly appreciated!
using UnityEngine;
public class newThirdPersonMovement : MonoBehaviour
{
public CharacterController controller;
public Transform cam;
public float speed = 6;
public float gravity = -20f;
public float jumpHeight = 1;
Vector3 velocity;
bool isGrounded;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
float turnSmoothVelocity;
public float turnSmoothTime = 0.1f;
// Update is called once per frame
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized;
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
controller.Move(moveDir.normalized * speed * Time.deltaTime);
}
}
}

Unity 3D - Camera follow behind main character + offset

I use the attached c# script to control the camera.
Mouse scroll (pulley/roller/wheel): Zooming in and out of the main character
Up Arrow (or W key) and Down Arrow (or X key): Raise and Lower the camera
Right arrow (or D key) and Left arrow (or A key): Rotate the camera around the main character
I try to get the camera to follow the back of the main character, and add it the offset that player defined by using mouse and arrows.
This line correctly moves the camera according to the input from the mouse and arrows:
transform.position = target.position + offset * currentZoom;
This line correctly moves the camera so that it will follow the back of the main character:
transform.position = target.position - target.forward + Vector3.up;
But each of them works correctly only if the other is canceled. If I try to merge them into one line, like:
transform.position = target.position - target.forward + Vector3.up + offset * currentZoom;
then the camera doesn't move properly:
Using the left and right arrows moves the camera around the main
character in ellipse/oval shape instead of in a circle
When the character moves, the offsset set by the right and left
arrows isn't saved but the camera returns to being exactly behind
the back of the main character
What do I need to do to combine the two lines so that camera does move properly?
using UnityEngine;
public class CameraController : MonoBehaviour
{
public Transform target;
public Vector3 offset = new Vector3(10f, 6f, 0f);
public float RotationX = .5f;
public float rightLeftSpeed = 5f;
public float currentZoom = .13f;
public float minZoom = .1f;
public float maxZoom = 1f;
public float speedZoom = .1f;
public float currentHeight = 6f;
public float minHeight = 0f;
public float maxHeight = 10f;
public float speedHeight = 1f;
void Update()
{
currentZoom -= Input.GetAxis("Mouse ScrollWheel") * speedZoom;
currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);
currentHeight += Input.GetAxis("Vertical") * speedHeight * Time.deltaTime;
currentHeight = Mathf.Clamp(currentHeight, minHeight, maxHeight);
offset.y = currentHeight;
offset = Quaternion.AngleAxis(-Input.GetAxis("Horizontal") * rightLeftSpeed, Vector3.up) * offset;
}
void LateUpdate()
{
transform.position = target.position + offset * currentZoom;
transform.position = target.position - target.forward + Vector3.up;
transform.LookAt(target.position + Vector3.up * RotationX);
}
}
I tested your code and adjusted it til it worked like you were trying to have it work. Instead of using offset, I used an angle. Then after setting the position, I rotate around the object by that angle. I set the height as part of setting the position. Lastly, I multiplied the target.forward by currentZoom to make it the distance the camera is from the object. I also adjusted the default values since these changes would make it really close otherwise. I'm pretty sure there are ways to simplify this a bit, but this works!
public class CameraController : MonoBehaviour {
public Transform target;
public float angle;
public float RotationX = .5f;
public float rightLeftSpeed = 5f;
public float currentZoom = 5f;
public float minZoom = 2f;
public float maxZoom = 8f;
public float speedZoom = .5f;
public float currentHeight = 6f;
public float minHeight = 3f;
public float maxHeight = 7f;
public float speedHeight = 1f;
void Update() {
currentZoom -= Input.GetAxis("Mouse ScrollWheel") * speedZoom * Time.deltaTime * 60f;
currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);
currentHeight += Input.GetAxis("Vertical") * speedHeight * Time.deltaTime * 60f;
currentHeight = Mathf.Clamp(currentHeight, minHeight, maxHeight);
angle -= Input.GetAxis("Horizontal") * rightLeftSpeed * Time.deltaTime * 60f;
}
void LateUpdate() {
var newPosition = target.position - (target.forward * currentZoom) + Vector3.up;
newPosition.y = target.position.y + currentHeight;
transform.position = newPosition;
transform.RotateAround(target.position, Vector3.up, angle);
transform.LookAt(target.position + Vector3.up * RotationX);
}
}

How to make my stick rotating after bouncing with button long pressed?

Basically I want to make bouncing stick and rotate control, with the left-right button.i'm facing an issue that the rotate not good as I expected because it won't follow my button like being affected by something after bouncing,
I'm using 2d physics material with friction = 1 and Bounciness = 0.9797 for perfect bouncing also attached to rigidbody2d.
I don't know, should I attach it on collider?
here my Player control Script:
public Rigidbody2D r2d;
public float vertical;
public float horizontal;
public Joystick joystick;
private void Start() {
r2d = gameObject.GetComponent < Rigidbody2D > ();
joystick = FindObjectOfType < Joystick > ();
}
private void Update() {
Movement();
}
public void Movement() {
r2d.velocity = r2d.velocity.normalized * 7f;
//horizontal = joystick.Horizontal;
//vertical = joystick.Vertical;
//if (horizontal == 0 && vertical == 0)
//{
// Vector3 curRot = transform.localEulerAngles;
// Vector3 homeRot = transform.localEulerAngles;
// transform.localEulerAngles = Vector3.Slerp(curRot, homeRot, Time.deltaTime * 2);
//}
//else
//{
// transform.localEulerAngles = new Vector3(0f, 0f, Mathf.Atan2(horizontal, vertical) * -180 / Mathf.PI);
//}
}
public Vector3 target;
public float rotationSpeed = 10f;
public float offset = 5;
public void turnLeft() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, -rotation, rotationSpeed * Time.deltaTime);
}
public void turnRight() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, rotationSpeed * Time.deltaTime);
}
Whenever there is a Rigidbody/Rigidbody2D involved you do not want to manipulate anything via the .transform component!
This breaks the physics, collision detection and leads to strange movements basically the transform "fighting" against physics for priority.
What you rather want to do would be e.g. adjusting the Rigidbody2D.angularVelocity
public void turnLeft()
{
// Note that Time.deltaTime only makes sense if this is actually called every frame!
r2d.angularVelocity -= rotationSpeed * Time.deltaTime;
}
public void turnRight()
{
r2d.angularVelocity += rotationSpeed * Time.deltaTime;
}