Unity Character controller climbing Terrain - c#

I'm working on terrain and I made this pit and my character controller acts like
it is on ground but its floating for sure and when I move forward it will get dragged down by the gravity but it gets "stuck" again floating and if I'm on the bottom of the pit and try to climb it it actually climbs the big slop while my slop limit is 45 and it counts like its grounded so I can jump again and yea I tried making a raycast to check if its grounded but still it only fixes the problem with climbing but it still if I jump at the sides of the pit I will start floating.
Here is the script .
using UnityEngine;
using System.Collections;
public class moveController : MonoBehaviour
{
private CharacterController controller;
public float moveSpeed = 15f;
public float jumpForce = 15f;
private Vector3 moveDirection;
private float gravityScale = 0.1f;
private float up_Down;
private float right_Left;
private float mouseX;
private float mouseY;
//headbob
private float currentAngle = 0;
private float smooth = 20.0F;
private float tiltAngle = 1.0F;
private float tiltAroundZ;
Vector3 h_bob;
//AccelerationVariables
private float jumpVelocityPerSecond = 3f;
private float speedVelocityPerSecond = 3f;
// jump or not , moving or not , walking or not,
private bool isJumping;
private bool isMoving;
private bool isWalking;
// look variables
Vector2 mouselook;
Vector2 smoothV;
private float smoothing = 2f;
private float sensitivity = 1.5f;
private Camera eyes;
private void Awake()
{
controller = GetComponent<CharacterController>();
eyes = Camera.main;
}
void Start()
{
}
void Update()
{
Move();
SlowDown();
//DeadHop();
// MaxSpeed_Jump();
Crouch();
}
private void Move()
{
// moveDirection = new Vector3(Input.GetAxis("Horizontal") * moveSpeed, moveDirection.y, Input.GetAxis("Vertical") * moveSpeed);
up_Down = Input.GetAxis("Vertical");
right_Left = Input.GetAxis("Horizontal");
mouseX = Input.GetAxis("Mouse X");
mouseY = Input.GetAxis("Mouse Y");
tiltAroundZ = Input.GetAxis("Horizontal") * tiltAngle;
currentAngle = Mathf.MoveTowards(currentAngle, tiltAroundZ, Time.deltaTime * smooth);
Vector3 moveDirSide = transform.right * right_Left * moveSpeed;
Vector3 moveDirForward = transform.forward * up_Down * moveSpeed ;
Vector3 BodyRot = transform.rotation.eulerAngles;
BodyRot.y += mouseX;
var md = new Vector2(mouseX, mouseY);
md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
mouselook += smoothV;
mouselook.y = Mathf.Clamp(mouselook.y, -80f, 80f);
// check if he is moving
if (Input.GetButton("Horizontal"))
{
isMoving = true;
}
else if (Input.GetButton("Vertical"))
{
isMoving = true;
}
else
{
isMoving = false;
}
// check if he is jumping
if (Input.GetButton("Jump"))
{
isJumping = true;
}
else if (Input.GetButtonUp("Jump"))
{
isJumping = false;
}
///check if grounded so he can jump
if (controller.isGrounded)
{
if (isJumping)
{
moveDirection.y = jumpForce;
}
}
moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale);
controller.Move(moveDirSide * Time.deltaTime);
controller.Move(moveDirForward * Time.deltaTime);
controller.Move(moveDirection * Time.deltaTime);
eyes.transform.localRotation = Quaternion.Euler(-mouselook.y, Vector3.right.x, -currentAngle);
transform.localRotation = Quaternion.AngleAxis(mouselook.x, BodyRot);
}
a
private void SlowDown()
{
if (Input.GetButton("SlowDown"))
{
moveSpeed = 5f;
jumpForce = 10f;
isWalking = true;
}
else if (Input.GetButtonUp("SlowDown"))
{
moveSpeed = 15f;
jumpForce = 15f;
isWalking = false;
}
}
//private void DeadHop()
//{
// if (isMoving)
// {
// jumpForce += jumpVelocityPerSecond * Time.deltaTime ;
// moveSpeed += speedVelocityPerSecond * Time.deltaTime ;
// }
// else if (isMoving == false)
// {
// jumpForce = 10f;
// moveSpeed = 10f;
// }
//}
//private void MaxSpeed_Jump()
//{
// if(moveSpeed >= 15)
// {
// moveSpeed = 15;
// }
// if(jumpForce >= 15)
// {
// jumpForce = 15;
// }
//}
private void Crouch()
{
if (Input.GetButton("Crouch") && isJumping == false)
{
controller.height = 1.5f;
moveSpeed = 5f;
}
else if (Input.GetButtonUp("Crouch") && isJumping == false)
{
moveSpeed = 15f;
controller.height = 3f;
}
if (Input.GetButton("Crouch") && isJumping == true)
{
controller.height = 1.5f;
}
else if (Input.GetButtonUp("Crouch") && isJumping == true)
{
moveSpeed = 15f;
controller.height = 3f;
}
}
}

Related

3D fps Game with gun adding recoil

I wanted to add Guns with recoil to my 3d fps game. It worked but for some reason all the time when i look completely downwards i walk backwards or frontwards. This only happens when the gun is active.
The Gun Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunScript : MonoBehaviour
{
[SerializeField] float Recoil = 500f;
[SerializeField] float TimeTillNextShoot;
[SerializeField] float Range = 100f;
[SerializeField] Transform GunTipposition;
[SerializeField] float recoilRadius = 100f;
public Camera PlayerCamera;
public Rigidbody rbPlayer;
private void Update()
{
Shoot();
}
public void Shoot()
{
if (Input.GetButtonDown("Fire1"))
{
RaycastHit hit;
if(Physics.Raycast(PlayerCamera.transform.position, PlayerCamera.transform.forward, out hit, Range))
{
Debug.Log(hit.transform.name);
Enemy Enemytarget = hit.transform.GetComponent<Enemy>();
if(Enemytarget != null)
{
Enemytarget.TakeDamage(true);
}
}
if (gameObject.CompareTag("ShotGun"))
{
Transform RecoilPosition = GunTipposition.transform;
rbPlayer.AddExplosionForce(Recoil, RecoilPosition.position, recoilRadius);
}
}
}
}
The player Movement:
// Some stupid rigidbody based movement by Dani
using System;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Assignables")]
[Tooltip("this is a reference to the MainCamera object, not the parent of it.")]
public Transform playerCam;
[Tooltip("reference to orientation object, needed for moving forward and not up or something.")]
public Transform orientation;
[Tooltip("LayerMask for ground layer, important because otherwise the collision detection wont know what ground is")]
public LayerMask whatIsGround;
private Rigidbody rb;
[Header("Rotation and look")]
private float xRotation;
[Tooltip("mouse/look sensitivity")]
public float sensitivity = 50f;
private float sensMultiplier = 1.5f;
[Header("Movement")]
[Tooltip("additive force amount. every physics update that forward is pressed, this force (multiplied by 1/tickrate) will be added to the player.")]
public float moveSpeed = 4500;
[Tooltip("maximum local velocity before input is cancelled")]
public float maxSpeed = 20;
[Tooltip("normal countermovement when not crouching.")]
public float counterMovement = 0.175f;
private float threshold = 0.01f;
[Tooltip("the maximum angle the ground can have relative to the players up direction.")]
public float maxSlopeAngle = 35f;
private Vector3 crouchScale = new Vector3(1, 0.5f, 1);
private Vector3 playerScale;
[Tooltip("forward force for when a crouch is started.")]
public float slideForce = 400;
[Tooltip("countermovement when sliding. this doesnt work the same way as normal countermovement.")]
public float slideCounterMovement = 0.2f;
private bool readyToJump = true;
private float jumpCooldown = 0.25f;
[Tooltip("this determines the jump force but is also applied when jumping off of walls, if you decrease it, you may end up being able to walljump and then get back onto the wall leading to infinite height.")]
public float jumpForce = 550f;
float x, y;
bool jumping;
private Vector3 normalVector = Vector3.up;
[Header("Wallrunning")]
private float actualWallRotation;
private float wallRotationVel;
private Vector3 wallNormalVector;
[Tooltip("when wallrunning, an upwards force is constantly applied to negate gravity by about half (at default), increasing this value will lead to more upwards force and decreasing will lead to less upwards force.")]
public float wallRunGravity = 1;
[Tooltip("when a wallrun is started, an upwards force is applied, this describes that force.")]
public float initialForce = 20f;
[Tooltip("float to choose how much force is applied outwards when ending a wallrun. this should always be greater than Jump Force")]
public float escapeForce = 600f;
private float wallRunRotation;
[Tooltip("how much you want to rotate the camera sideways while wallrunning")]
public float wallRunRotateAmount = 10f;
[Tooltip("a bool to check if the player is wallrunning because thats kinda necessary.")]
public bool isWallRunning;
[Tooltip("a bool to determine whether or not to actually allow wallrunning.")]
public bool useWallrunning = true;
[Header("Collisions")]
[Tooltip("a bool to check if the player is on the ground.")]
public bool grounded;
[Tooltip("a bool to check if the player is currently crouching.")]
public bool crouching;
private bool surfing;
private bool cancellingGrounded;
private bool cancellingSurf;
private bool cancellingWall;
private bool onWall;
private bool cancelling;
public static PlayerMovement Instance { get; private set; }
void Awake()
{
Instance = this;
rb = GetComponent<Rigidbody>();
//Create a physic material with no friction to allow for wallrunning and smooth movement not being dependant
//and smooth movement not being dependant on the in-built unity physics engine, apart from collisions.
PhysicMaterial mat = new PhysicMaterial("tempMat");
mat.bounceCombine = PhysicMaterialCombine.Average;
mat.bounciness = 0;
mat.frictionCombine = PhysicMaterialCombine.Minimum;
mat.staticFriction = 0;
mat.dynamicFriction = 0;
gameObject.GetComponent<Collider>().material = mat;
}
void Start()
{
playerScale = transform.localScale;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
readyToJump = true;
wallNormalVector = Vector3.up;
}
private void FixedUpdate()
{
Movement();
}
private void Update()
{
MyInput();
Look();
}
private void LateUpdate()
{
//call the wallrunning Function
WallRunning();
WallRunRotate();
}
private void WallRunRotate()
{
FindWallRunRotation();
float num = 12f;
actualWallRotation = Mathf.SmoothDamp(actualWallRotation, wallRunRotation, ref wallRotationVel, num * Time.deltaTime);
playerCam.localRotation = Quaternion.Euler(playerCam.rotation.eulerAngles.x, playerCam.rotation.eulerAngles.y, actualWallRotation);
}
/// <summary>
/// Find user input. Should put this in its own class but im lazy
/// </summary>
private void MyInput()
{
x = Input.GetAxisRaw("Horizontal");
y = Input.GetAxisRaw("Vertical");
jumping = Input.GetButton("Jump");
crouching = Input.GetKey(KeyCode.LeftControl);
//Crouching
if (Input.GetKeyDown(KeyCode.LeftControl))
StartCrouch();
if (Input.GetKeyUp(KeyCode.LeftControl))
StopCrouch();
}
private void StartCrouch()
{
transform.localScale = crouchScale;
transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
if (rb.velocity.magnitude > 0.2f && grounded)
{
if (grounded)
{
rb.AddForce(orientation.transform.forward * slideForce);
}
}
}
private void StopCrouch()
{
transform.localScale = playerScale;
transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
}
private void Movement()
{
//Extra gravity
rb.AddForce(Vector3.down * Time.deltaTime * 10);
//Find actual velocity relative to where player is looking
Vector2 mag = FindVelRelativeToLook();
float xMag = mag.x, yMag = mag.y;
//Counteract sliding and sloppy movement
CounterMovement(x, y, mag);
//If holding jump && ready to jump, then jump
if (readyToJump && jumping) Jump();
//Set max speed
float maxSpeed = this.maxSpeed;
//If sliding down a ramp, add force down so player stays grounded and also builds speed
if (crouching && grounded && readyToJump)
{
rb.AddForce(Vector3.down * Time.deltaTime * 3000);
return;
}
//If speed is larger than maxspeed, cancel out the input so you don't go over max speed
if (x > 0 && xMag > maxSpeed) x = 0;
if (x < 0 && xMag < -maxSpeed) x = 0;
if (y > 0 && yMag > maxSpeed) y = 0;
if (y < 0 && yMag < -maxSpeed) y = 0;
//Some multipliers
float multiplier = 1f, multiplierV = 1f;
// Movement in air
if (!grounded)
{
multiplier = 0.5f;
multiplierV = 0.5f;
}
// Movement while sliding
if (grounded && crouching) multiplierV = 0f;
//Apply forces to move player
rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * multiplier * multiplierV);
rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * multiplier);
}
private void Jump()
{
if ((grounded || isWallRunning || surfing) && readyToJump)
{
MonoBehaviour.print("jumping");
Vector3 velocity = rb.velocity;
readyToJump = false;
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(normalVector * jumpForce * 0.5f);
if (rb.velocity.y < 0.5f)
{
rb.velocity = new Vector3(velocity.x, 0f, velocity.z);
}
else if (rb.velocity.y > 0f)
{
rb.velocity = new Vector3(velocity.x, velocity.y / 2f, velocity.z);
}
if (isWallRunning)
{
rb.AddForce(wallNormalVector * jumpForce * 3f);
}
Invoke("ResetJump", jumpCooldown);
if (isWallRunning)
{
isWallRunning = false;
}
}
}
private void ResetJump()
{
readyToJump = true;
}
private float desiredX;
private void Look()
{
float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
//Find current look rotation
Vector3 rot = playerCam.transform.localRotation.eulerAngles;
desiredX = rot.y + mouseX;
//Rotate, and also make sure we dont over- or under-rotate.
xRotation -= mouseY;
float clamp = 89.5f;
xRotation = Mathf.Clamp(xRotation, -clamp, clamp);
//Perform the rotations
playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, 0);
orientation.transform.localRotation = Quaternion.Euler(0, desiredX, 0);
}
private void CounterMovement(float x, float y, Vector2 mag)
{
if (!grounded || jumping) return;
//Slow down sliding
if (crouching)
{
rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideCounterMovement);
return;
}
//Counter movement
if (Math.Abs(mag.x) > threshold && Math.Abs(x) < 0.05f || (mag.x < -threshold && x > 0) || (mag.x > threshold && x < 0))
{
rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * -mag.x * counterMovement);
}
if (Math.Abs(mag.y) > threshold && Math.Abs(y) < 0.05f || (mag.y < -threshold && y > 0) || (mag.y > threshold && y < 0))
{
rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * -mag.y * counterMovement);
}
//Limit diagonal running. This will also cause a full stop if sliding fast and un-crouching, so not optimal.
if (Mathf.Sqrt((Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2))) > maxSpeed)
{
float fallspeed = rb.velocity.y;
Vector3 n = rb.velocity.normalized * maxSpeed;
rb.velocity = new Vector3(n.x, fallspeed, n.z);
}
}
/// <summary>
/// Find the velocity relative to where the player is looking
/// Useful for vectors calculations regarding movement and limiting movement
/// </summary>
/// <returns></returns>
public Vector2 FindVelRelativeToLook()
{
float lookAngle = orientation.transform.eulerAngles.y;
float moveAngle = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * Mathf.Rad2Deg;
float u = Mathf.DeltaAngle(lookAngle, moveAngle);
float v = 90 - u;
float magnitue = rb.velocity.magnitude;
float yMag = magnitue * Mathf.Cos(u * Mathf.Deg2Rad);
float xMag = magnitue * Mathf.Cos(v * Mathf.Deg2Rad);
return new Vector2(xMag, yMag);
}
//a lot of math (dont touch)
private void FindWallRunRotation()
{
if (!isWallRunning)
{
wallRunRotation = 0f;
return;
}
_ = new Vector3(0f, playerCam.transform.rotation.y, 0f).normalized;
new Vector3(0f, 0f, 1f);
float num = 0f;
float current = playerCam.transform.rotation.eulerAngles.y;
if (Math.Abs(wallNormalVector.x - 1f) < 0.1f)
{
num = 90f;
}
else if (Math.Abs(wallNormalVector.x - -1f) < 0.1f)
{
num = 270f;
}
else if (Math.Abs(wallNormalVector.z - 1f) < 0.1f)
{
num = 0f;
}
else if (Math.Abs(wallNormalVector.z - -1f) < 0.1f)
{
num = 180f;
}
num = Vector3.SignedAngle(new Vector3(0f, 0f, 1f), wallNormalVector, Vector3.up);
float num2 = Mathf.DeltaAngle(current, num);
wallRunRotation = (0f - num2 / 90f) * wallRunRotateAmount;
if (!useWallrunning)
{
return;
}
if ((Mathf.Abs(wallRunRotation) < 4f && y > 0f && Math.Abs(x) < 0.1f) || (Mathf.Abs(wallRunRotation) > 22f && y < 0f && Math.Abs(x) < 0.1f))
{
if (!cancelling)
{
cancelling = true;
CancelInvoke("CancelWallrun");
Invoke("CancelWallrun", 0.2f);
}
}
else
{
cancelling = false;
CancelInvoke("CancelWallrun");
}
}
private bool IsFloor(Vector3 v)
{
return Vector3.Angle(Vector3.up, v) < maxSlopeAngle;
}
private bool IsSurf(Vector3 v)
{
float num = Vector3.Angle(Vector3.up, v);
if (num < 89f)
{
return num > maxSlopeAngle;
}
return false;
}
private bool IsWall(Vector3 v)
{
return Math.Abs(90f - Vector3.Angle(Vector3.up, v)) < 0.05f;
}
private bool IsRoof(Vector3 v)
{
return v.y == -1f;
}
/// <summary>
/// Handle ground detection
/// </summary>
private void OnCollisionStay(Collision other)
{
int layer = other.gameObject.layer;
if ((int)whatIsGround != ((int)whatIsGround | (1 << layer)))
{
return;
}
for (int i = 0; i < other.contactCount; i++)
{
Vector3 normal = other.contacts[i].normal;
if (IsFloor(normal))
{
if (isWallRunning)
{
isWallRunning = false;
}
grounded = true;
normalVector = normal;
cancellingGrounded = false;
CancelInvoke("StopGrounded");
}
if (IsWall(normal) && (layer == (int)whatIsGround || (int)whatIsGround == -1 || layer == LayerMask.NameToLayer("Ground") || layer == LayerMask.NameToLayer("ground"))) //seriously what is this
{
StartWallRun(normal);
onWall = true;
cancellingWall = false;
CancelInvoke("StopWall");
}
if (IsSurf(normal))
{
surfing = true;
cancellingSurf = false;
CancelInvoke("StopSurf");
}
IsRoof(normal);
}
float num = 3f;
if (!cancellingGrounded)
{
cancellingGrounded = true;
Invoke("StopGrounded", Time.deltaTime * num);
}
if (!cancellingWall)
{
cancellingWall = true;
Invoke("StopWall", Time.deltaTime * num);
}
if (!cancellingSurf)
{
cancellingSurf = true;
Invoke("StopSurf", Time.deltaTime * num);
}
}
private void StopGrounded()
{
grounded = false;
}
private void StopWall()
{
onWall = false;
isWallRunning = false;
}
private void StopSurf()
{
surfing = false;
}
//wallrunning functions
private void CancelWallrun()
{
//for when we want to stop wallrunning
MonoBehaviour.print("cancelled wallrun");
Invoke("GetReadyToWallrun", 0.1f);
rb.AddForce(wallNormalVector * escapeForce);
isWallRunning = false;
}
private void StartWallRun(Vector3 normal)
{
MonoBehaviour.print("wallrunning");
//cancels all y momentum and then applies an upwards force.
if (!grounded && useWallrunning)
{
wallNormalVector = normal;
if (!isWallRunning)
{
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(Vector3.up * initialForce, ForceMode.Impulse);
}
isWallRunning = true;
}
}
private void WallRunning()
{
//checks if the wallrunning bool is set to true and if it is then applies
//a force to counter gravity enough to make it feel like wallrunning
if (isWallRunning)
{
rb.AddForce(-wallNormalVector * Time.deltaTime * moveSpeed);
rb.AddForce(Vector3.up * Time.deltaTime * rb.mass * 40f * wallRunGravity * -Physics.gravity.y);
}
}
}
I used a addForce funktion to add the recoil.Please help me.
This sentence is juist written because i need to add more details

How to jump properly using character controller?

I'm using a character controller for my player movement. I had walking and running working, but I couldn't get the jumping to work.
Here is my code:
[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;
[SerializeField] [Range(0.0f, 0.5f)] float mouseSmoothTime = 0.03f;
public float jumpHeight = 3f;
Vector3 velocity;
public float verticalVelocity;
float cameraPitch = 0.0f;
float VelocityY = 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)
VelocityY = 0.0f;
VelocityY += gravity * Time.deltaTime;
velocity = (transform.forward * currentDir.y + transform.right * currentDir.x) * walkSpeed + Vector3.up * VelocityY;
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 * VelocityY;
controller.Move(velocity * Time.deltaTime);
}
if (Input.GetKeyDown(KeyCode.J) && controller.isGrounded)
{
Debug.Log("Now Jumping!!");
VelocityY = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
}
Note: I'm not using rigidbody on my character.
The jumping is not working every time, on some clicks, it jumps and on most of the clicks nothing happens even Debug.Log("Now Jumping!!"); is not getting printed every time I hit J. How can I fix this?
I solved this problem. You have no choice but to add physics to the character controller. This is a simple code that has the same feature, but you should coordinate the movement and jump.
public class Player : MonoBehaviour
{
private Vector3 playerVelocity;
private CharacterController _controller;
public float jumpPower = 1f; // 1 is ok for -9.8 gravity
void Start()
{
_controller = GetComponent<CharacterController>();
}
void Update()
{
playerVelocity += Physics.gravity * Time.deltaTime;
_controller.Move(playerVelocity);
if (_controller.isGrounded)
{
playerVelocity.y = Input.GetKeyDown(KeyCode.Space) ? jumpPower : 0;
}
}
}

Making a (unity) moment script that allows my character to have dynamic jump, coyote time, jump buffering, and dash

I am new to unity and am trying to take two scripts that I have written based on youtube tutorials and make a script that allows my character to have dynamic jump, coyote time, jump buffering, and dash. Everything is working except for the dash now. When I play, all of the features work, including the anti-gravity during the dash, but my character does not speed up; it remains at the same speed as when walking. I think the two IEnumerator may be conflicting, but I am unsure of how to resolve it. So far, everything I have tried has not worked. I appreciate the help! enter image description here
using System.Collections;
using UnityEngine;
public class PlayerMovementBendux : MonoBehaviour
{
private float horizontal;
public float speed = 8f;
public float jumpingPower = 16f;
private bool isFacingRight = true;
private bool isJumping;
private float coyoteTime = 0.2f;
private float coyoteTimeCounter;
private float jumpBufferTime = 0.2f;
private float jumpBufferCounter;
private bool canDash = true;
private bool isDashing;
public float dashingPower = 24f;
public float dashingTime = 0.2f;
public float dashingCooldown = 1f;
[SerializeField] private Rigidbody2D rb;
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask groundLayer;
[SerializeField] private TrailRenderer tr;
private void Update()
{
if (isDashing)
{
return;
}
horizontal = Input.GetAxisRaw("Horizontal");
if (IsGrounded())
{
coyoteTimeCounter = coyoteTime;
}
else
{
coyoteTimeCounter -= Time.deltaTime;
}
if (Input.GetButtonDown("Jump"))
{
jumpBufferCounter = jumpBufferTime;
}
else
{
jumpBufferCounter -= Time.deltaTime;
}
if (coyoteTimeCounter > 0f && jumpBufferCounter > 0f && !isJumping)
{
rb.velocity = new Vector2(rb.velocity.x, jumpingPower);
jumpBufferCounter = 0f;
StartCoroutine(JumpCooldown());
}
if (Input.GetButtonUp("Jump") && rb.velocity.y > 0f)
{
rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);
coyoteTimeCounter = 0f;
}
if (Input.GetKeyDown(KeyCode.LeftShift) && canDash)
{
StartCoroutine(Dash());
}
Flip();
}
private void FixedUpdate()
{
rb.velocity = new Vector2(horizontal * speed, rb.velocity.y);
}
private bool IsGrounded()
{
return Physics2D.OverlapCircle(groundCheck.position, 0.2f, groundLayer);
}
private void Flip()
{
if (isFacingRight && horizontal < 0f || !isFacingRight && horizontal > 0f)
{
Vector3 localScale = transform.localScale;
isFacingRight = !isFacingRight;
localScale.x *= -1f;
transform.localScale = localScale;
}
}
private IEnumerator JumpCooldown()
{
isJumping = true;
yield return new WaitForSeconds(0.4f);
isJumping = false;
}
private IEnumerator Dash()
{
canDash = false;
isDashing = true;
float originalGravity = rb.gravityScale;
rb.gravityScale = 0f;
rb.velocity = new Vector2(transform.localScale.x * dashingPower, 0f);
tr.emitting = true;
yield return new WaitForSeconds(dashingTime);
tr.emitting = false;
rb.gravityScale = originalGravity;
isDashing = false;
yield return new WaitForSeconds(dashingCooldown);
canDash = true;
}
}

Character is jittering after adding falling function

Let me just preface my question by saying I'm quite new to unity and programming as a whole. However I've been experimenting with some movement and after adding my falling function I've run into some trouble. Sometimes if I press play in Unity the character will start jittering quite heavy, every frame it also jumps between isInAir and isGrounded (as well as isInteracting). This causes my player to shake heavily and jitter forward as well.
Sometimes the falling animation will happen but my character falls really slowly, sometimes the animation doesn't work. Does anyone know how I can fix this?
Here is my PlayerLocomotion, the everything falling related is mentioned under HandleFalling.
using System.Collections.Generic;
using UnityEngine;
namespace FS
{
public class PlayerLocomotion : MonoBehaviour
{
PlayerManager playerManager;
Transform cameraObject;
InputHandler inputHandler;
public Vector3 moveDirection;
[HideInInspector]
public Transform myTransform;
[HideInInspector]
public AnimatorHandler animatorHandler;
public new Rigidbody rigidbody;
public GameObject normalCamera;
[Header("Ground & Air Detection Stats")]
[SerializeField]
float groundDetectionRayStartPoint = 0.5f;
[SerializeField]
float minimumDistanceNeededToBeginFall = 1f;
[SerializeField]
float groundDirectionRayDistance = 0.2f;
LayerMask ignoreForGroundCheck;
public float inAirTimer;
[Header("Movement Stats")]
[SerializeField]
float movementSpeed = 5;
[SerializeField]
float sprintSpeed = 7;
[SerializeField]
float rotationSpeed = 10;
[SerializeField]
float fallingSpeed = 45;
void Start()
{
playerManager = GetComponent<PlayerManager>();
rigidbody = GetComponent<Rigidbody>();
inputHandler = GetComponent<InputHandler>();
animatorHandler = GetComponentInChildren<AnimatorHandler>();
cameraObject = Camera.main.transform;
myTransform = transform;
animatorHandler.Initialize();
playerManager.isGrounded = true;
ignoreForGroundCheck = ~(1 << 10);
}
#region Movement
Vector3 normalVector;
Vector3 targetPosition;
private void HandleRotation(float delta)
{
Vector3 targetDir = Vector3.zero;
float moveOverride = inputHandler.moveAmount;
targetDir = cameraObject.forward * inputHandler.vertical;
targetDir += cameraObject.right * inputHandler.horizontal;
targetDir.Normalize();
targetDir.y = 0;
if (targetDir == Vector3.zero) targetDir = myTransform.forward;
float rs = rotationSpeed;
Quaternion tr = Quaternion.LookRotation(targetDir);
Quaternion targetRotation =
Quaternion.Slerp(myTransform.rotation, tr, rs * delta);
myTransform.rotation = targetRotation;
}
public void HandleMovement(float delta)
{
if (inputHandler.rollFlag) return;
if (playerManager.isInteracting) return;
moveDirection = cameraObject.forward * inputHandler.vertical;
moveDirection += cameraObject.right * inputHandler.horizontal;
moveDirection.Normalize();
moveDirection.y = 0;
float speed = movementSpeed;
if (inputHandler.sprintFlag)
{
speed = sprintSpeed;
playerManager.isSprinting = true;
moveDirection *= speed;
}
else
{
moveDirection *= speed;
}
Vector3 projectedVelocity =
Vector3.ProjectOnPlane(moveDirection, normalVector);
rigidbody.velocity = projectedVelocity;
animatorHandler
.UpdateAnimatorValues(inputHandler.moveAmount,
0,
playerManager.isSprinting);
if (animatorHandler.canRotate)
{
HandleRotation (delta);
}
}
public void HandleRollingAndSprinting(float delta)
{
if (animatorHandler.anim.GetBool("isInteracting")) return;
if (inputHandler.rollFlag)
{
moveDirection = cameraObject.forward * inputHandler.vertical;
moveDirection += cameraObject.right * inputHandler.horizontal;
if (inputHandler.moveAmount > 0)
{
animatorHandler.PlayTargetAnimation("Rolling", true);
moveDirection.y = 0;
Quaternion rollRotation =
Quaternion.LookRotation(moveDirection);
myTransform.rotation = rollRotation;
}
else
{
animatorHandler.PlayTargetAnimation("Backstep", true);
}
}
}
public void HandleFalling(float delta, Vector3 moveDirection)
{
playerManager.isGrounded = false;
RaycastHit hit;
Vector3 origin = myTransform.position;
origin.y += groundDetectionRayStartPoint;
if (Physics.Raycast(origin, myTransform.forward, out hit, 0.4f))
{
moveDirection = Vector3.zero;
}
if (playerManager.isInAir)
{
rigidbody.AddForce(-Vector3.up * fallingSpeed);
rigidbody.AddForce(moveDirection * fallingSpeed / 5f);
}
Vector3 dir = -moveDirection;
dir.Normalize();
origin = origin + dir * groundDirectionRayDistance;
targetPosition = myTransform.position;
Debug
.DrawRay(origin,
-Vector3.up * minimumDistanceNeededToBeginFall,
Color.red,
0.1f,
false);
if (Physics.Raycast(origin, -Vector3.up, out hit, minimumDistanceNeededToBeginFall, ignoreForGroundCheck))
{
normalVector = hit.normal;
Vector3 tp = hit.point;
playerManager.isGrounded = true;
targetPosition.y = tp.y;
if (playerManager.isInAir)
{
if (inAirTimer > 0.5f)
{
Debug.Log("You were in the air for " + inAirTimer);
animatorHandler.PlayTargetAnimation("Land", true);
inAirTimer = 0;
}
else
{
animatorHandler
.PlayTargetAnimation("Empty", false);
inAirTimer = 0;
}
playerManager.isInAir = false;
}
else
{
if (playerManager.isGrounded)
{
playerManager.isGrounded = false;
}
if (playerManager.isInAir == false)
{
if (playerManager.isInteracting == false)
{
animatorHandler
.PlayTargetAnimation("Falling", true);
}
Vector3 vel = rigidbody.velocity;
vel.Normalize();
rigidbody.velocity = vel * (movementSpeed / 2);
playerManager.isInAir = true;
}
}
if (playerManager.isInteracting || inputHandler.moveAmount > 0)
{
myTransform.position = Vector3.Lerp(myTransform.position, targetPosition, Time.deltaTime / 0.1f);
}
else
{
myTransform.position = targetPosition;
}
}
}
#endregion
}
}

My spherical world player controller is jittering randomly

I've got a problem with my spherical world player controller. It randomly jitter all the time.
Planet uses Mesh Collider, and it's rigidbody is set too: "is kinematic" and continous collisions.
Player's rigidbody is set to: "interpolate" and continous collisions.
Here is player controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] Transform cam, body, groundCheck;
[Space][SerializeField] float sensivity = 100f;
[SerializeField] float mass = 1f;
[SerializeField] float moveSpeed = 1f;
[SerializeField] float jumpHeight = 1f;
[SerializeField] LayerMask ground;
[SerializeField] float rotationChangeSpeed = 1f;
float xRotation = 0f;
Rigidbody rb;
Vector3 moveAmount, smoothMove;
Vector3 localUp;
bool grounded = false;
Quaternion targetRot;
float jumpTime = 0f;
Transform currentPlanet;
//On start
void Awake() {
Cursor.lockState = CursorLockMode.Locked;
rb = GetComponent<Rigidbody>();
}
//Physics simulation
void FixedUpdate() {
Grav();
FindingRotation();
Movement();
grounded = IsGrounded();
}
//Applying movement
void Movement() {
Vector3 localMove = transform.TransformDirection(moveAmount) * Time.fixedDeltaTime;
rb.MovePosition(rb.position + localMove);
}
//Simulating gravity
void Grav() {
List<CelestialBody> bodies = CelestialBody.bodies;
if(bodies.Count == 0) return;
Vector3 acceleration = Vector3.zero;
float maxForce = -1f;
for(int i = 0; i < bodies.Count; ++i) {
CelestialBody body = bodies[i];
float distance = Vector3.Distance(body.GetComponent<Transform>().position, transform.position);
float force = GravityManager.bigG * mass * body.mass / (distance * distance);
Vector3 direction = Vector3.Normalize(body.GetComponent<Transform>().position - transform.position);
if(force > maxForce) {
maxForce = force;
currentPlanet = body.transform;
}
acceleration += direction * force;
}
if(!grounded) GetComponent<Rigidbody>().AddForce(acceleration);
}
//Rotating according to body with highest gravity
void FindingRotation() {
localUp = Vector3.Normalize(transform.position - currentPlanet.position);
targetRot = Quaternion.FromToRotation(transform.up, localUp) * rb.rotation;
rb.rotation = Quaternion.Slerp(rb.rotation, targetRot, Time.fixedDeltaTime * rotationChangeSpeed);
}
//Per frame
void Update() {
CameraControls();
InputManager();
jumpTime -= Time.deltaTime;
}
//Camera controls
void CameraControls() {
float mouseX = Input.GetAxis("Mouse X") * sensivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * sensivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
cam.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
body.Rotate(Vector3.up * mouseX);
}
//Moving and jumping
void InputManager() {
Vector3 inputRaw = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")).normalized;
Vector3 input = inputRaw * moveSpeed;
moveAmount = Vector3.SmoothDamp(moveAmount, input, ref smoothMove, .15f);
if(grounded) {
if(Input.GetKeyDown(KeyCode.Space)) {
rb.AddForce(transform.up * jumpHeight, ForceMode.VelocityChange);;
jumpTime = .2f;
grounded = false;
}
else {
if(jumpTime <= 0f) rb.AddForce (-transform.up, ForceMode.VelocityChange);
}
}
}
//TODO: Improve with ray
bool IsGrounded() {
return (Physics.OverlapSphere(groundCheck.position, .1f, ground).Length > 0);
}
}
And here is Celestial Body:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CelestialBody : MonoBehaviour
{
public static List<CelestialBody> bodies = new List<CelestialBody>();
public float mass;
//public Vector3 speed;
void OnEnable() {
bodies.Add(this);
}
void OnDisable() {
bodies.Remove(this);
}
}
I will be really grateful for any advice.

Categories