I am trying to make a FPS game but when I press w for a bit and then release it slides a bit further than wanted. I am pretty new to Unity and think it has something to do with the updates.
Code:
public float moveSpeed = 5f;
public float jumpForce = 5f;
public CharacterController controller;
private Vector3 moveDirection;
public float gravityScale;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
float yStore = moveDirection.y;
moveDirection = (transform.forward * Input.GetAxis("Vertical")) + (transform.right * Input.GetAxis("Horizontal"));
moveDirection = moveDirection.normalized * moveSpeed;
moveDirection.y = yStore;
if (controller.isGrounded)
{
moveDirection.y = 0f;
if (Input.GetButtonDown("Jump"))
{
moveDirection.y = jumpForce;
}
}
moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale);
controller.Move(moveDirection * Time.deltaTime);
}
add a physics material to your ground and set the dynamic friction to 1. Next, set the static friction from 0.5 to 1. And last but not least, set the bounciness to 0.
Play around with these values a bit until you find something that is satisfactory.
here is the link to the documentation:
https://docs.unity3d.com/Manual/class-PhysicMaterial.html
it basically explains what each property does.
Related
I'm working on a 2D game in Unity attempting to make my player jump. Despite watching tons of videos and adjusting the code many times, he simply won't jump when I press the space bar. After even checking the input manager in Unity, I'm sure it's a simple fix I'm missing somewhere but I don't see where it could be.
public class FoxyController : MonoBehaviour
{
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
public float jumpVelocity = 10f;
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
}
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
if (Input.GetKey(KeyCode.Space))
{
Jump();
}
}
void FixedUpdate()
{
Vector2 position= rigidbody2d.position;
position.x = position.x + 4f * horizontal * Time.deltaTime;
position.y = position.y + 4f * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
void Jump()
{
rigidbody2d.velocity = Vector2.up * jumpVelocity;
}
}
Use -> rb.AddForce(Vector2.up * jumpAmount, ForceMode2D.Impulse); where jumpAmount can be multiplayer, you can use 10f as jumpAmount value.
if (Input.GetKey(KeyCode.Space))
{
rb.AddForce(Vector2.up * jumpAmount, ForceMode2D.Impulse);
}
Add Above code in update method instead of jump() method.
I have began developing an fps script and followed a tutorial to help with the script. Everything works great now but the only issue is any objects in the view seem to stutter whenever the player is moving and rotating at the same time.
The script for the player's movement and camera rotation is below.
Can anybody point me in the right direction?
Thank you.
{
public Transform cam;
public Rigidbody rb;
public float camRotationSpeed = 5f;
public float camMinimumY = -60f;
public float camMaximumY = 75f;
public float rotationSmoothSpeed = 10f;
public float walkSpeed = 9f;
public float runSpeed = 14f;
public float maxSpeed = 20f;
public float jumpPower = 30f;
public float extraGravity = 45;
float bodyRotationX;
float camRotationY;
Vector3 directionIntentX;
Vector3 directionIntentY;
float speed;
public bool grounded;
void Update()
{
LookRotation();
Movement();
ExtraGravity();
GroundCheck();
if(grounded && Input.GetButtonDown("Jump"))
{
Jump();
}
}
void LookRotation()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
bodyRotationX += Input.GetAxis("Mouse X") * camRotationSpeed;
camRotationY += Input.GetAxis("Mouse Y") * camRotationSpeed;
camRotationY = Mathf.Clamp(camRotationY, camMinimumY, camMaximumY);
Quaternion camTargetRotation = Quaternion.Euler(-camRotationY, 0, 0);
Quaternion bodyTargetRotation = Quaternion.Euler(0, bodyRotationX, 0);
transform.rotation = Quaternion.Lerp(transform.rotation, bodyTargetRotation, Time.deltaTime * rotationSmoothSpeed);
cam.localRotation = Quaternion.Lerp(cam.localRotation, camTargetRotation, Time.deltaTime * rotationSmoothSpeed);
}
void Movement()
{
directionIntentX = cam.right;
directionIntentX.y = 0;
directionIntentX.Normalize();
directionIntentY = cam.forward;
directionIntentY.y = 0;
directionIntentY.Normalize();
rb.velocity = directionIntentY * Input.GetAxis("Vertical") * speed + directionIntentX * Input.GetAxis("Horizontal") * speed + Vector3.up * rb.velocity.y;
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
if (Input.GetKey(KeyCode.LeftShift))
{
speed = runSpeed;
}
if (!Input.GetKey(KeyCode.LeftShift))
{
speed = walkSpeed;
}
}
void ExtraGravity()
{
rb.AddForce(Vector3.down * extraGravity);
}
void GroundCheck()
{
RaycastHit groundHit;
grounded = Physics.Raycast(transform.position, -transform.up, out groundHit, 1.25f);
}
void Jump()
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
This probably happens because the frame needs to update the camera rotation and the player position at the same time. i would suggest doing the rotation of the camera in fixed update. because this will run at the end of each frame.
like this:
void FixedUpdate()
{
LookRotation();
}
another thing i would suggest is to move the player while the groundcheck is being ran, because if you do it seperately i can see a bug coming up when the player moves faster then the code can run or something. so a tip would be or to run it inside the movement method, or call the method while you are calling the movement method.
this:
void Movement()
{
directionIntentX = cam.right;
directionIntentX.y = 0;
directionIntentX.Normalize();
directionIntentY = cam.forward;
directionIntentY.y = 0;
directionIntentY.Normalize();
rb.velocity = directionIntentY * Input.GetAxis("Vertical") * speed + directionIntentX * Input.GetAxis("Horizontal") * speed + Vector3.up * rb.velocity.y;
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
if (Input.GetKey(KeyCode.LeftShift))
{
speed = runSpeed;
}
if (!Input.GetKey(KeyCode.LeftShift))
{
speed = walkSpeed;
}
GroundCheck();
}
or litteraly copy and paste the code within your movement method.
the only problem that i face that the player only jump when they build momentum and i dont want that i want player jump by pressing space while standing or moving i tried velocity.y=jumphight which doesnt work too
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovment : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
Vector3 velocity;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
bool isGrounded;
public float JumpHight = 3f;
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y<0)
{
controller.slopeLimit = 45.0f;
velocity.y = -2f;//when player is grounded it just put some gravity to him all the time
}
float x = Input.GetAxis("Horizontal");//moves left and right
float z = Input.GetAxis("Vertical");//moves up and down
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move*speed*Time.deltaTime);
if(Input.GetButtonDown("Jump") && controller.isGrounded)
{
velocity.y = Mathf.Sqrt(JumpHight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
you could use an addforce on the rigidbody with a ForceMode force , and if you don't want your physic depending on the fps use FixedUpdate instead of update
GetComponent<Rigidbody>().AddForce(Vector3.up,ForceMode.Force);
Vector3 velocity;
public float gravity = -9.82f;
public float JumpHeight = 3f;
if(Input.GetButtonDown("Jump")
{
velocity.y = Matf.Sqrt(JumpHeight * -2f * gravity);
}
You could also do what the other person said, the reason this person's line of code might not have worked it due to how weak it is. Here is an updated version of said code.
GetComponent<Rigidbody>().AddForce(Vector3.up * 10f ,ForceMode.Impulse);
The reason I am using the * is to increase the "up" variable since it means Vector3(0f, 1f, 0f); and using the ForceMode.Impulse to make it more volatile and stronger.
Hope this code helps you in your game making,
Kind Regards. SB
I've seen people say that you should set a delay timer right after the walking of a platform or just before you touch the floor because this makes your game feel so much better! Here's the code I've tried previously -
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
//Variables
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
// is the controller on the ground?
if (controller.isGrounded) {
//Feed moveDirection with input.
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
//Multiply it by speed.
moveDirection *= speed;
//Jumping
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
//Applying gravity to the controller
moveDirection.y -= gravity * Time.deltaTime;
//Making the character move
controller.Move(moveDirection * Time.deltaTime);
}
}
If you want to make the player jump right before you touch the ground, just use a timer that automatically counts down. Change it so that you don't jump if you press the jump button, but you instead reset the timer. Here is an example:
public float jumpRememberTime = 0.2f;
private float jumpRememberTimer;
private void Update()
{
jumpRememberTimer -= Time.deltaTime;
if (Input.GetButtonDown ("Jump"))
jumpRememberTimer = jumpRememberTime;
if (jumpRememberTimer > 0f && controller.isGrounded)
{
moveDirection.y = jumpSpeed; // jump
}
}
For allowing the player to jump right after they leave a platform you also need a timer. This is called coyote time. You use a timer and make it count down once the player has left the platform. This is the code after implementing this.
public float jumpRememberTime = 0.2f;
private float jumpRememberTimer;
public float groundedRememberTime = 0.2f;
private float groundedRememberTimer = 0f;
private void Update()
{
jumpRememberTimer -= Time.deltaTime;
if (Input.GetButtonDown ("Jump"))
jumpRememberTimer = jumpRememberTime;
if (isGrounded)
groundedRememberTimer = groundedRememberTime;
else
groundedRememberTimer -= Time.deltaTime;
if (jumpRememberTimer > 0f && groundedRememberTimer > 0f)
{
moveDirection.y = jumpSpeed; // jump
}
}
I'm having an issue where my gameObject barely jumps at all. I think it has something to do with moveDirection because the jumping works when I comment out p.velocity = moveDirection.
Any suggestions on how to fix this?
using UnityEngine;
using System.Collections;
public class Controller : MonoBehaviour
{
public float jumpHeight = 8f;
public Rigidbody p;
public float speed = 1;
public float runSpeed = 3;
public Vector3 moveDirection = Vector3.zero;
// Use this for initialization
void Start ()
{
p = GetComponent<Rigidbody>();
p.velocity = Vector3.zero;
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown (KeyCode.Space))
{
p.AddForce(new Vector3(0, jumpHeight, 0), ForceMode.Impulse);
}
Move ();
}
void Move ()
{
if(Input.GetKey(KeyCode.D))
{
transform.Rotate(Vector3.up, Mathf.Clamp(180f * Time.deltaTime, 0f, 360f));
}
if(Input.GetKey(KeyCode.A))
{
transform.Rotate(Vector3.up, -Mathf.Clamp(180f * Time.deltaTime, 0f, 360f));
}
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
if(Input.GetKey(KeyCode.LeftShift))
{
moveDirection *= runSpeed;
}
else
{
moveDirection *= speed;
}
p.velocity = moveDirection;
}
}
Try using a much higher value for your jumpheight variable. I usually go with something in the hundreds.
Because right after doing the AddForce(...) literally within the same frame you override the velocity with moveDirection. You should be adding to the current velocity, instead of overriding it entirely as such:
Vector3 velocity = p.velocity;
p.velocity = velocity + moveDirection;
This is exactly why Unity warns against messing with velocity directly, youd be better off just doing another AddForce(...) for your movement:
p.AddForce(moveDirection * Time.deltaTime);
EDIT:
i don't like digressing too far from the OP's question, but your new problems are probably because you are doing too much with moveDirection half of what i don't even understand why but it should for the most part look like this:
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")).normalized;
float _speed = Input.GetKey(KeyCode.LeftShift) ? runspeed : speed;
p.AddForce(moveDirection * _speed * Time.deltaTime);
Okay I figured out how to fix it. Instead of those MoveDirection variables I changed it to
if(Input.GetKey(KeyCode.W)) {
transform.position += transform.forward * Time.deltaTime * speed;
}
if(Input.GetKey(KeyCode.S)) {
transform.position -= transform.forward * Time.deltaTime * speed;
}
and now it works just fine.