I am following an FPS tutorial here. Unfortunately, at the end when Brackeys tests out the code, I cannot jump. Here is my player movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 10f;
public float gravity = -10f;
public float jumpHeight = 5f;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
bool isGrounded;
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);
if (Input.GetButton("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
Here is the screenshot for the code component in the unity editor:
Please help me!
Also, if you need any clarification, do not hesitate to ask!
I have some suggestions for your problem but I am not 100% sure that they will work.
Check that that the layer Ground is attached to the gameobject that is your platform. If you don't know how to do this, check this doc on layers: https://docs.unity3d.com/Manual/Layers.html
Another idea is that of the groundcheck. Make sure the ground check is just below the player.
My final suggestion is that of the key bindings. Make sure that Jump is assigned to your desired button.
I believe these will work. If there are still any problems, comment down below.
I haven't tried the code myself yet, but if you increase the Jumpheight to something like 300 the player should jump up.
This is because your formula:
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
Ends up being smaller than the gravity , so you don't have enough force to jump up.
No need for ground check from Brackeys's FPS code since the character controller has its public isGrounded property.
Related
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraSc : MonoBehaviour
{
public float sens;
public Transform body;
public Transform head;
float xRot = 0;
void Start()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
float x = Input.GetAxisRaw("Mouse X") * sens * Time.deltaTime;
float y = Input.GetAxisRaw("Mouse Y") * sens * Time.deltaTime;
xRot -= y;
xRot = Mathf.Clamp(xRot,-80f,80f);
transform.localRotation = Quaternion.Euler(xRot,0f,0f);
body.Rotate(Vector3.up, x);
transform.position = head.position;
//transform.rotation = head.rotation;
}
}
I have a body and I want my camera to follow my head. it follows of course but it vibrates, its like its not moving , its teleporting to head every second. I tried using FixedUpdate but it was worse. I tried Lerp too but lerp makes camera follow slow, when I move my mouse quick it takes a lot of time to follow.
If you don't need any acceleration or advanced movement for your camera, you can simply make your camera gameobject a child of your head gameobject in the scene hierarchy (or prefab). This will make your camera copy the position and rotation of the head gameobject without any coding.
If you wish to make it third person view, you can simply modify the child position which will always be local to the parent's one.
Hopefully this helps.
It's can be complex problem. Maybe one of these solutions can help.
Why you use Input.GetAxisRaw() - this function return value without smoothing filtering, try Input.GetAxis() as alternative.
"Vibration" effect can be if camera position updates later than your body position. Try setup position for you body object in LateUpdate().
Problem can be in rotation calculation, in your case euler angles will be enough. Try to use something like this:
public float sens = 100.0f;
public float minY = -45.0f;
public float maxY = 45.0f;
private float rotationY = 0.0f;
private float rotationX = 0.0f;
private void Update()
{
rotationX += Input.GetAxis("Mouse X") * sens * Time.deltaTime;
rotationY += Input.GetAxis("Mouse Y") * sens * Time.deltaTime;
rotationY = Mathf.Clamp(rotationY, minY, maxY);
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
I've been following along with a 3D shooter tutorial (pretty good so far) but I've hit a snag when it comes to my framerate and jumping. The framerate on my PC is just not consistent and consequently the jump height varies constantly and sometimes the character doesn't jump at all. I know handling jumping in Update (rather than FixedUpdate) can cause issues regarding framerates but the tutorial insists that using Time.deltaTime should resolve that. Any ideas on what I should do to try and keep my jumps consistent?
//Jumping
public float jumpHeight = 10f;
public Transform ground;
private bool readyToJump;
public LayerMask groundLayer;
public float groundDistance = 0.5f;
// Update is called once per frame
private void Update()
{
Jump();
PlayerMovement();
CameraMovement();
Shoot();
}
void PlayerMovement()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 movement = x * transform.right + z * transform.forward;
myController.Move(movement * speed * Time.deltaTime);
//9.8 meters/second^2
velocity.y += Physics.gravity.y * Mathf.Pow(Time.deltaTime, 2) * gravityModifier;
if (myController.isGrounded)
{
velocity.y = Physics.gravity.y * Time.deltaTime;
}
myController.Move(velocity);
}
private void CameraMovement()
{
float mouseX = Input.GetAxisRaw("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxisRaw("Mouse Y") * mouseSensitivity * Time.deltaTime;
cameraVerticalRotation -= mouseY;
cameraVerticalRotation = Mathf.Clamp(cameraVerticalRotation, minVertCameraAngle, maxVertCameraAngle);
transform.Rotate(Vector3.up * mouseX);
myHead.localRotation = Quaternion.Euler(cameraVerticalRotation, 0f, 0f);
}
void Jump()
{
readyToJump = Physics.OverlapSphere(ground.position, groundDistance, groundLayer).Length > 0;
if (Input.GetButtonDown("Jump") && readyToJump)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * Physics.gravity.y) * Time.deltaTime;
}
myController.Move(velocity);
}
Handling the acceleration yourself is a bad idea, especially in Update rather than FixedUpdate. You should know that, in real life, the velocity changes smoothly with the acceleration against time. If you draw a curve, it is a straight slope. However, in computer, if you just calculate the velocity frame by frame, the curve will be looked like stairs.
You may use the physics engine in Unity and add an instant velocity to the character when it jumps. Just let Unity handle the acceleration.
First, you need to add a Rigidbody component to it. Then, you may modify your code to:
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Jump()
{
readyToJump = Physics.OverlapSphere(ground.position, groundDistance, groundLayer).Length > 0;
if (Input.GetButtonDown("Jump") && readyToJump)
{
rb.velocity = Vector3.up * jumpHeight * 2f / -Physics.gravity.y * gravityModifier;
}
}
Don't forget to remove the code in PlayerMovement on handling falling after you have Use Gravity in the Rigidbody component.
Edit
If you are using CharacterController, you can only handle the acceleration yourself. You may just move the logic to FixedUpdate to solve the various height problem, or make a more accurate simulation. For example, use this to handle jumping:
velocity.y = jumpHeight * 2f / -Physics.gravity.y * gravityModifier;
and use this to handle falling:
myController.Move(velocity * Time.deltaTime + Physics.gravity * Mathf.Pow(Time.deltaTime, 2) / 2f * gravityModifier);
// Here you should check whether it will fall through the ground.
// If no, use this line to update the velocity.
velocity.y += Physics.gravity.y * gravityModifier * Time.deltaTime;
// Otherwise, update the position to make it on ground and set velocity.y to 0.
So I have this first person player controller c# script, (I followed brackeys' tutorial) and I have the jump input coded, basically word for word, but for some reason it doesn't jump, instead once I start the game, the player just floats up infinitely, which is definitely not what I want. Here's the script incase any of you know how to fix it(sorry if the error is a typo or something, but this would help greatly):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
public LayerMask groundMask;
public float groundDistance = 0.4f;
public Transform groundCheck;
public float jumpHeight = 3f;
Vector3 velocity;
bool isGrounded;
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);
if(Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
Thanks in advance.
I was making a PlayerMovement script today for a small 3D game I wanted to start. After some experimentation with the script, I realized that when you release a button to move, it won't instantly stop and instead the character body starts to slide.
For the most part, I had used Brackey's tutorial on PlayerMovement scripts but added a .Normalize() to make sure diagonals did not have more speed.
Does anyone know how to fix this? This is my PlayerMovement script.
public class PlayerMovement : MonoBehaviour
{
public float speed = 12f;
public float gravity = -0.05f;
public float jumpHeight = 4f;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
Vector3 move;
private bool isGrounded;
public CharacterController controller;
void FixedUpdate()
{
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;
move.Normalize();
controller.Move(Time.deltaTime * speed * move);
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
Thank you for any help or guidance!
Instead of Input.GetAxis, try using Input.GetAxisRaw, which returns the non-smoothed value for a target axis, resulting in a more FPS-like controller, more responsive and fast, without smoothing.
So i have completed the Roll a ball tutorial from Unity that is a little game that uses a sphere with a rigidbody applied to it with some basic movement script found here.
What i want now is to take it a step further and introduce a somewhat more advanced movement script which also takes mouse input into play.
What i am trying to achieve is so to add force based on the local axis, so if i i move the mouse left the ball turns and the force is added in that direction. Let me show what code i have come up with (added to a simple sphere with rigidbody applied):
using UnityEngine;
using System.Collections;
public class playerController : MonoBehaviour {
public float turnSpeed = 2.0f;
public float moveSpeed = 250.0f;
void FixedUpdate() {
float h = turnSpeed * Input.GetAxis("Mouse X");
transform.Rotate(0, h, 0);
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rigidbody.AddForce(movement * moveSpeed * Time.deltaTime);
}
}
Ok so what is happening is that the ball is turning when i move the mouse, and the ball is rolling if i use the arrowkeys, but what i'm not managing to figure out after some trial and error is to get the ball moving in the direction it is turning.
How would you approach this particular scenario? Any help is as always much appreciated guys.
I managed to get around this and sharing for others to see.
I reference to the camera GameObject and use the camera.transform on the keys. Guess it is really basic but still.
public GameObject Camera;
public float moveSpeed = 0.0f;
if (Input.GetKey ("right") || Input.GetKey ("d")) {
rigidbody.AddForce( Camera.transform.right * moveSpeed * Time.deltaTime);
}
if (Input.GetKey ("left") || Input.GetKey ("a")) {
rigidbody.AddForce( -Camera.transform.right * moveSpeed * Time.deltaTime);
}
if (Input.GetKey ("up") || Input.GetKey ("w")) {
rigidbody.AddForce( Camera.transform.forward * moveSpeed * Time.deltaTime);
}
if (Input.GetKey ("down") || Input.GetKey ("s")) {
rigidbody.AddForce( -Camera.transform.forward * moveSpeed * Time.deltaTime);
}
Something Like this should do the trick::
if (Input.GetKey ("up") || Input.GetKey ("w")) {
rigidbody.AddForce( Camera.transform.forward * moveSpeed * Time.deltaTime);
rigidbody.AddRelativeTorque(vector3.right * speed)
//Note that rotation happens around the axis, so when moving (forward orback you will rotate on the vector3.right/left) and when moving( Right/left you will use the vector3.forward/back)
}