I have coded the unity movement for my character. I made it so they can wall run bit it seems that wall running is somehow making my character walk weird. After wall running (if I wall run with the wall on my right) it will apply a force 90 degrees when I'm walking on the ground. The unknown force changes when each button is pressed (is W then apply both the W force and a force pushing it to the right). And the same happens with running on the left wall but it is at a -90 degree angle. Please help I've been stuck on this for a whole week. Thanks
This is the wall running code
using System.Collections.Generic;
using UnityEngine;
public class MoveChar : MonoBehaviour
{
[Header("Movement")]
float moveSpeed;
[SerializeField] float walkSpeed;
[SerializeField] float sprintSpeed;
[SerializeField] float slideSpeed;
[SerializeField] float wallRunSpeed;
float desiredMoveSpeed;
float lastDesiredMoveSpeed;
[SerializeField] float groundDrag;
[Header("Jumping")]
[SerializeField] float jumpForce;
[SerializeField] float jumpCoolDown;
[SerializeField] float airMultiplier;
bool readyToJump;
[HideInInspector] public bool doubleJump;
[Header("Crouching")]
[SerializeField] float crouchSpeed;
[SerializeField] float crouchYScale;
float crouchYStart;
bool exitingJump;
[Header("Slope Check")]
[SerializeField] float maxSlope;
RaycastHit slopeHit;
[Header("Ground Check")]
[SerializeField] float playerHeight;
[SerializeField] LayerMask whatIsGround;
bool grounded;
[Header("Keybinds")]
KeyCode jumpKey = KeyCode.Space;
KeyCode walkKey = KeyCode.LeftShift;
KeyCode crouchKey = KeyCode.C;
[SerializeField] Transform orientation;
[SerializeField] Transform camRotate;
float horizontalInput;
float verticalInput;
Vector3 moveDirection;
Rigidbody rb;
MovementState state;
enum MovementState
{
walking,
sprinting,
crouching,
sliding,
wallRunning,
air
}
[HideInInspector] public bool sliding;
[HideInInspector] public bool wallRunning;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
ResetJump();
crouchYStart = transform.localScale.y;
}
// Update is called once per frame
void Update()
{
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);
MyInput();
SpeedControl();
StateHandler();
if (grounded)
{
rb.drag = groundDrag;
}
else
{
rb.drag = 0;
}
}
private void FixedUpdate()
{
MovePlayer();
}
void MyInput()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
if (Input.GetKeyDown(jumpKey) && readyToJump && (grounded || doubleJump))
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCoolDown);
}
if (grounded && !Input.GetKey(jumpKey))
{
doubleJump = false;
}
if (Input.GetKeyDown(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z);
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
}
if (Input.GetKeyUp(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, crouchYStart, transform.localScale.z);
}
}
void StateHandler()
{
if (wallRunning)
{
state = MovementState.wallRunning;
desiredMoveSpeed = wallRunSpeed;
doubleJump = false;
}
if (sliding)
{
state = MovementState.sliding;
if (OnSlope() && rb.velocity.y < 0.1f)
{
desiredMoveSpeed = slideSpeed;
}
else
{
desiredMoveSpeed = sprintSpeed;
}
}
else if (Input.GetKey(crouchKey))
{
state = MovementState.crouching;
desiredMoveSpeed = crouchSpeed;
}
else if (grounded && Input.GetKey(walkKey))
{
state = MovementState.walking;
desiredMoveSpeed = walkSpeed;
}
else if (grounded)
{
state = MovementState.sprinting;
desiredMoveSpeed = sprintSpeed;
}
else
{
state = MovementState.air;
}
if (Mathf.Abs(desiredMoveSpeed - lastDesiredMoveSpeed) > 4f && moveSpeed != 0)
{
StopAllCoroutines();
StartCoroutine(SmoothlyLerpMoveSpeed());
}
else
{
moveSpeed = desiredMoveSpeed;
}
lastDesiredMoveSpeed = desiredMoveSpeed;
}
IEnumerator SmoothlyLerpMoveSpeed()
{
float time = 0;
float difference = Mathf.Abs(desiredMoveSpeed - moveSpeed);
float startValue = moveSpeed;
while (time < difference)
{
moveSpeed = Mathf.Lerp(startValue, desiredMoveSpeed, time / difference);
time += Time.deltaTime;
yield return null;
}
moveSpeed = desiredMoveSpeed;
}
void MovePlayer()
{
moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
if (OnSlope() && !exitingJump)
{
rb.AddForce(GetSlopeMoveDirection(moveDirection) * moveSpeed * 20f, ForceMode.Force);
if (rb.velocity.y > 0)
{
rb.AddForce(Vector3.down * 80f, ForceMode.Force);
}
}
else if (grounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
}
else if (!grounded)
{
rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
}
if (!wallRunning)
{
rb.useGravity = !OnSlope();
}
}
void SpeedControl()
{
if (OnSlope() && !exitingJump)
{
if (rb.velocity.magnitude > moveSpeed)
{
rb.velocity = rb.velocity.normalized * moveSpeed;
}
}
else
{
Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
if (flatVel.magnitude > moveSpeed)
{
Vector3 limitVel = flatVel.normalized * moveSpeed;
rb.velocity = new Vector3(limitVel.x, rb.velocity.y, limitVel.z);
}
}
}
void Jump()
{
exitingJump = true;
rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
doubleJump = !doubleJump;
}
void ResetJump()
{
readyToJump = true;
exitingJump = false;
}
public bool OnSlope()
{
if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, playerHeight * 0.5f + 0.3f))
{
float angle = Vector3.Angle(Vector3.up, slopeHit.normal);
return angle < maxSlope && angle != 0;
}
return false;
}
public Vector3 GetSlopeMoveDirection(Vector3 direction)
{
return Vector3.ProjectOnPlane(direction, slopeHit.normal).normalized;
}
}
This is the wall running code
using System.Collections.Generic;
using UnityEngine;
public class WallRunning : MonoBehaviour
{
[Header("Wallrunning")]
[SerializeField] LayerMask whatIsRunAble;
[SerializeField] LayerMask whatIsGround;
[SerializeField] float wallRunForce;
[SerializeField] float wallRunUpForce;
[SerializeField] float wallRunSideForce;
[SerializeField] float wallClimbSpeed;
[Header("Input")]
KeyCode jumpKey = KeyCode.Space;
float horizontalInput;
float verticalInput;
[Header("Detection")]
[SerializeField] float wallCheckDistance;
[SerializeField] float minJumpHeight;
RaycastHit leftWallHit;
RaycastHit rightWallHit;
bool wallLeft;
bool wallRight;
[Header("Exiting")]
[SerializeField] float exitWallTime;
bool exitingWall;
float exitWallTimer;
[Header("Gravity")]
[SerializeField] bool useGravity;
[SerializeField] float gravityCounterForce;
[Header("References")]
[SerializeField] Transform orientation;
MoveChar mc;
Rigidbody rb;
[SerializeField] Transform cam;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
mc = GetComponent<MoveChar>();
}
// Update is called once per frame
void Update()
{
CheckForWall();
StateMachine();
}
private void FixedUpdate()
{
if (mc.wallRunning)
{
WallRunMove();
}
}
void CheckForWall()
{
wallRight = Physics.Raycast(transform.position, orientation.right, out rightWallHit, wallCheckDistance, whatIsRunAble);
wallLeft = Physics.Raycast(transform.position, -orientation.right, out leftWallHit, wallCheckDistance, whatIsRunAble);
}
bool AboveGround()
{
return !Physics.Raycast(transform.position, Vector3.down, minJumpHeight, whatIsGround);
}
void StateMachine()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
if ((wallLeft || wallRight) && verticalInput > 0 && AboveGround() && !exitingWall)
{
if (Input.GetKeyDown(jumpKey))
{
WallJump();
}
}
if ((wallLeft || wallRight) && verticalInput > 0 && AboveGround() && !exitingWall)
{
if (!mc.wallRunning)
{
StartWallRun();
}
}
else if (exitingWall)
{
if (mc.wallRunning)
{
StopWallRun();
}
if (exitWallTimer > 0)
{
exitWallTimer -= Time.deltaTime;
}
if (exitWallTimer <= 0)
{
exitingWall = false;
}
}
else
{
if (mc.wallRunning)
{
StopWallRun();
}
}
}
void StartWallRun()
{
mc.wallRunning = true;
rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
if (wallRight)
{
cam.localRotation = Quaternion.Euler(0, 0, 10f);
}
if (wallLeft)
{
cam.localRotation = Quaternion.Euler(0, 0, -10f);
}
}
void WallRunMove()
{
rb.useGravity = useGravity;
Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal;
Vector3 wallForward = Vector3.Cross(wallNormal, transform.up.normalized);
if ((orientation.forward - wallForward).magnitude > (orientation.forward - -wallForward).magnitude)
{
wallForward = -wallForward;
}
rb.AddForce(wallForward * wallRunForce, ForceMode.Force);
/*if (!(wallLeft && horizontalInput > 0) && !(wallRight && horizontalInput < 0))
{
rb.AddForce(-wallNormal * 100, ForceMode.Force);
}
if (useGravity)
{
rb.AddForce(transform.up * gravityCounterForce, ForceMode.Force);
}*/
}
void StopWallRun()
{
mc.wallRunning = false;
cam.localRotation = Quaternion.Euler(0, 0, 0);
}
void WallJump()
{
exitingWall = true;
exitWallTimer = exitWallTime;
Vector3 wallNormal = wallRight ? rightWallHit.normal : leftWallHit.normal;
Vector3 forceToApply = transform.up * wallRunUpForce + wallNormal * wallRunSideForce;
rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
rb.AddForce(forceToApply, ForceMode.Impulse);
mc.doubleJump = !mc.doubleJump;
}
}
Thank you soooooooo much for any help
Related
I'm currently working on a FPS "Speedrun" game & I want to add "Sliding" to the players movement. I already added "Crouching", but currently I'm stuck at getting the sliding done. (I'm using the Character Controller) I've tried many things, but nothing really worked. Heres the current PlayerMovement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UIElements;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
private Rigidbody rb;
public Transform cameraTransform;
public HeadBobController headBobController;
[Header("Movement")]
private float speedMultiplier = 1f;
public float speed = 12f;
public float sprintSpeed = 20f;
public float slopeSpeed = 0.01f;
public float gravity = -9.81f;
public float jumpHeight = 3f;
public float sensitivity = 2f;
public float cameraRotationLimit = 85f;
[Header("Countermovement")]
public float counterMovement = 0.175f;
private float threshold = 0.01f;
public float maxSlopeAngle = 35f;
[Header("Sliding / Crouch")]
public float slideSpeed;
float originalHeight;
public float reducedHeight;
float targetHeight = 2f;
public float timeToCrouch = 0.25f;
float timeElapsed = 0;
bool canStopCrouching;
bool wantStopCrouch;
bool isRunning = false;
public bool isCrouching = false;
bool canUseHeadbob = true;
bool WillSlideOnSlopes = true;
bool IsSliding
{
get
{
if (controller.isGrounded && Physics.Raycast(transform.position, Vector3.down, out RaycastHit slopeHit, 3f))
{
hitPointNormal = slopeHit.normal;
return Vector3.Angle(hitPointNormal, Vector3.up) > controller.slopeLimit;
} else
{
return false;
}
}
}
[Header("Headbob")]
[SerializeField] private float walkBobSpeed = 14f;
[SerializeField] private float walkBobAmount = 0.05f;
[SerializeField] private float sprintBobSpeed = 18f;
[SerializeField] private float sprintBobAmount = 0.11f;
[SerializeField] private float crouchBobSpeed = 8f;
[SerializeField] private float crouchBobAmount = 0.025f;
private float defaultYPos = 0;
private float timer;
private Vector3 hitPointNormal;
[Header("Ground Check")]
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
public bool isGrounded;
[Header("Camera")]
float cameraRotationX = 0f;
float cameraRotationY = 0f;
public Camera camera;
public Transform orientation;
[Header("Other")]
public GameObject speedlines;
public ParticleSystem jumpParticle;
void Start()
{
rb = GetComponent<Rigidbody>();
controller = GetComponent<CharacterController>();
originalHeight = controller.height;
defaultYPos = camera.transform.localPosition.y;
//Cursor.lockState = CursorLockMode.Locked;
//Cursor.visible = false;
}
public 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;
move = Vector3.ClampMagnitude(move, 1f);
if (Input.GetKey(KeyCode.LeftShift) && !isCrouching)
{
controller.Move(move * sprintSpeed * Time.deltaTime);
isRunning = true;
headBobController.amplitude = 0.1f;
headBobController.frequency = 30f;
} else
{
controller.Move(move * speed * speedMultiplier * Time.deltaTime);
isRunning = false;
headBobController.amplitude = 0.0426f;
headBobController.frequency = 19.1f;
}
if (Physics.Raycast(camera.transform.position, Vector3.up, 1f))
{
canStopCrouching = false;
} else
{
canStopCrouching = true;
}
if (canStopCrouching && wantStopCrouch && !Physics.Raycast(camera.transform.position, Vector3.up, 1f))
{
wantStopCrouch = false;
StopCrouch();
}
if (Input.GetKeyDown(KeyCode.LeftControl) && isGrounded)
{
//controller.height = Mathf.Lerp(reducedHeight, originalHeight, timeElapsed);
StartCrouch();
} else if(Input.GetKeyUp(KeyCode.LeftControl) && isGrounded && !Physics.Raycast(camera.transform.position, Vector3.up, 1f))
{
//controller.height = Mathf.Lerp(originalHeight, targetHeight, timeElapsed);
StopCrouch();
} else if(Input.GetKeyUp(KeyCode.LeftControl) && isGrounded && Physics.Raycast(camera.transform.position, Vector3.up, 1f))
{
wantStopCrouch = true;
}
if (Input.GetKey(KeyCode.LeftControl) && isRunning && isGrounded)
{
//Sliding
}
if (canUseHeadbob && isGrounded)
{
if (Mathf.Abs(move.x) > 0.1f || Mathf.Abs(move.z) > 0.1f)
{
timer += Time.deltaTime * (isCrouching ? crouchBobSpeed : isRunning ? sprintBobSpeed : walkBobSpeed);
camera.transform.localPosition = new Vector3(camera.transform.localPosition.x, defaultYPos + Mathf.Sin(timer) * (isRunning ? sprintBobAmount : walkBobAmount), camera.transform.localPosition.z);
}
}
if(WillSlideOnSlopes && IsSliding)
{
move += new Vector3(hitPointNormal.x, -hitPointNormal.y, hitPointNormal.z) * slopeSpeed;
}
if (isRunning)
{
speedlines.active = true;
} else {
speedlines.active = false;
}
controller.Move(move * speed * speedMultiplier * Time.deltaTime);
if (Input.GetButtonDown("Jump") && isGrounded)
{
controller.Move(-transform.forward * 0.1f);
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
jumpParticle.Play();
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
// Rotate the player based on mouse input
float mouseX = Input.GetAxis("Mouse X") * sensitivity;
float mouseY = Input.GetAxis("Mouse Y") * sensitivity;
cameraRotationY += mouseX;
cameraRotationX -= mouseY;
cameraRotationX = Mathf.Clamp(cameraRotationX, -cameraRotationLimit, cameraRotationLimit);
cameraTransform.localEulerAngles = new Vector3(cameraRotationX, cameraRotationY, 0f);
transform.eulerAngles = new Vector3(0f, cameraRotationY, 0f);
}
private void StartCrouch()
{
controller.height = reducedHeight;
speedMultiplier = 0.5f;
isCrouching = true;
}
private void StopCrouch()
{
controller.height = originalHeight;
speedMultiplier = 1f;
isCrouching = false;
}
}
It would be very nice if anyone could try to explain me how to implement it into this code using the Character Controller! :)
I've tried multiple Youtube Tutorial solutions & a lot in Online Forums, nothing really worked for me for some reason. Often the system wouldn't even work (nothing happened). I want the player to have the crouching ability (which is implemented) & to slide when isRunning & when the player isGrounded
The main character from the Unity 3D tutorials that I followed, I believe not from the site, are producing a wobbly left foot. I did not put a foot IK because the issue is not placement. It seems like an origin point thing, but not sure so I turned here for help.
I tried to have the full range of motion of the Mecanim character but was unable to produce foot bones on the rig that seem to work even though I just imported the model and code.
Third Person Character code :
using System;
using System.Collections;
using UnityEngine;
namespace UnityStandardAssets.Characters.ThirdPerson
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Animator))]
public class ThirdPersonCharacter : MonoBehaviour
{
[SerializeField] float m_MovingTurnSpeed = 360;
[SerializeField] float m_StationaryTurnSpeed = 180;
[SerializeField] float m_JumpPower = 12f;
[Range(1f, 4f)][SerializeField] float m_GravityMultiplier = 2f;
[SerializeField] float m_RunCycleLegOffset = 0.2f;
[SerializeField] float m_MoveSpeedMultiplier = 1f;
[SerializeField] float m_AnimSpeedMultiplier = 1f;
[SerializeField] float m_GroundCheckDistance = 0.1f;
Rigidbody m_Rigidbody;
Animator m_Animator;
bool m_IsGrounded;
float m_OrigGroundCheckDistance;
const float k_Half = 0.5f;
float m_TurnAmount;
float m_ForwardAmount;
Vector3 m_GroundNormal;
float m_CapsuleHeight;
Vector3 m_CapsuleCenter;
CapsuleCollider m_Capsule;
bool m_Crouching;
void Start()
{
m_Animator = GetComponent<Animator>();
m_Rigidbody = GetComponent<Rigidbody>();
m_Capsule = GetComponent<CapsuleCollider>();
m_CapsuleHeight = m_Capsule.height;
m_CapsuleCenter = m_Capsule.center;
m_Rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
m_OrigGroundCheckDistance = m_GroundCheckDistance;
}
public void Move(Vector3 move, bool crouch, bool jump)
{
if (move.magnitude > 1f) move.Normalize();
move = transform.InverseTransformDirection(move);
CheckGroundStatus();
move = Vector3.ProjectOnPlane(move, m_GroundNormal);
m_TurnAmount = Mathf.Atan2(move.x, move.z);
m_ForwardAmount = move.z;
ApplyExtraTurnRotation();
if (m_IsGrounded)
{
HandleGroundedMovement(crouch, jump);
}
else
{
HandleAirborneMovement();
}
ScaleCapsuleForCrouching(crouch);
PreventStandingInLowHeadroom();
UpdateAnimator(move);
}
void ScaleCapsuleForCrouching(bool crouch)
{
if (m_IsGrounded && crouch)
{
if (m_Crouching) return;
m_Capsule.height = m_Capsule.height / 2f;
m_Capsule.center = m_Capsule.center / 2f;
m_Crouching = true;
}
else
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up * m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius * k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, crouchRayLength, Physics.AllLayers, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
return;
}
m_Capsule.height = m_CapsuleHeight;
m_Capsule.center = m_CapsuleCenter;
m_Crouching = false;
}
}
void PreventStandingInLowHeadroom()
{
if (!m_Crouching)
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up * m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius * k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, crouchRayLength, Physics.AllLayers, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
}
}
}
void UpdateAnimator(Vector3 move)
{
m_Animator.SetFloat("Forward", m_ForwardAmount, 0.1f, Time.deltaTime);
m_Animator.SetFloat("Turn", m_TurnAmount, 0.1f, Time.deltaTime);
m_Animator.SetBool("Crouch", m_Crouching);
m_Animator.SetBool("OnGround", m_IsGrounded);
if (!m_IsGrounded)
{
m_Animator.SetFloat("Jump", m_Rigidbody.velocity.y);
}
float runCycle =
Mathf.Repeat(
m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime + m_RunCycleLegOffset, 1);
float jumpLeg = (runCycle < k_Half ? 1 : -1) * m_ForwardAmount;
if (m_IsGrounded)
{
m_Animator.SetFloat("JumpLeg", jumpLeg);
}
if (m_IsGrounded && move.magnitude > 0)
{
m_Animator.speed = m_AnimSpeedMultiplier;
}
else
{
m_Animator.speed = 1;
}
}
void HandleAirborneMovement()
{
Vector3 extraGravityForce = (Physics.gravity * m_GravityMultiplier) - Physics.gravity;
m_Rigidbody.AddForce(extraGravityForce);
m_GroundCheckDistance = m_Rigidbody.velocity.y < 0 ? m_OrigGroundCheckDistance : 0.01f;
}
void HandleGroundedMovement(bool crouch, bool jump)
{
if (jump && !crouch && m_Animator.GetCurrentAnimatorStateInfo(0).IsName("Grounded"))
{
m_Rigidbody.velocity = new Vector3(m_Rigidbody.velocity.x, m_JumpPower, m_Rigidbody.velocity.z);
m_IsGrounded = false;
m_Animator.applyRootMotion = false;
m_GroundCheckDistance = 0.1f;
}
}
void ApplyExtraTurnRotation()
{
float turnSpeed = Mathf.Lerp(m_StationaryTurnSpeed, m_MovingTurnSpeed, m_ForwardAmount);
transform.Rotate(0, m_TurnAmount * turnSpeed * Time.deltaTime, 0);
}
public void OnAnimatorMove()
{
if (m_IsGrounded && Time.deltaTime > 0)
{
Vector3 v = (m_Animator.deltaPosition * m_MoveSpeedMultiplier) / Time.deltaTime;
v.y = m_Rigidbody.velocity.y;
m_Rigidbody.velocity = v;
}
}
void CheckGroundStatus()
{
RaycastHit hitInfo;
Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transform.position + (Vector3.up * 0.1f) + (Vector3.down * m_GroundCheckDistance));
if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, m_GroundCheckDistance))
{
m_GroundNormal = hitInfo.normal;
m_IsGrounded = true;
m_Animator.applyRootMotion = true;
}
else
{
m_IsGrounded = false;
m_GroundNormal = Vector3.up;
m_Animator.applyRootMotion = false;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Movement")]
private float moveSpeed;
public float walkSpeed;
public float sprintSpeed;
public bool sliding;
public bool sprinting;
public float groundDrag;
[Header("Jumping")]
public float jumpForce;
public float jumpCooldown;
public float airMultiplier;
bool readyToJump;
[Header("Crouching")]
public float crouchSpeed;
public float crouchYScale;
private float startYScale;
[Header("Keybinds")]
public KeyCode jumpKey = KeyCode.Space;
public KeyCode sprintKey = KeyCode.LeftShift;
public KeyCode crouchKey = KeyCode.LeftControl;
[Header("Ground Check")]
public float playerHeight;
public LayerMask whatIsGround;
bool grounded;
[Header("Slope Handling")]
public float maxSlopeAngle;
private RaycastHit slopeHit;
private bool exitingSlope;
[Header("Sliding")]
public float maxSlideTime;
public float slideForce;
private float slideTimer;
public float slideSpeed;
public float slideYScale;
[Header("References")]
public Transform orientation;
private Rigidbody rb;
[Header("Input")]
private float horizontalInput;
private float verticalInput;
Vector3 moveDirection;
public MovementState state;
public enum MovementState
{
walking,
sprinting,
crouching,
sliding,
air
}
private void Start()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
readyToJump = true;
startYScale = transform.localScale.y;
}
private void Update()
{
// ground check
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);
MyInput();
SpeedControl();
StateHandler();
if (Input.GetKeyUp(sprintKey) || Input.GetKeyUp(KeyCode.W))
sprinting = false;
// handle drag
if (grounded)
rb.drag = groundDrag;
else
rb.drag = 0;
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
if (Input.GetKeyDown(crouchKey) && sprinting)
StartSlide();
if (Input.GetKeyUp(crouchKey) && sliding)
StopSlide();
}
private void FixedUpdate()
{
MovePlayer();
if (sliding)
SlidingMovement();
}
private void MyInput()
{
horizontalInput = Input.GetAxisRaw("Horizontal");
verticalInput = Input.GetAxisRaw("Vertical");
// when to jump
if (Input.GetKey(jumpKey) && readyToJump && grounded)
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCooldown);
}
// start crouch
if (Input.GetKeyDown(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, crouchYScale, transform.localScale.z);
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
}
if (Input.GetKeyDown(crouchKey) && sprinting)
{
transform.localScale = new Vector3(transform.localScale.x, slideYScale, transform.localScale.z);
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
sliding = true;
moveSpeed = slideSpeed;
}
// stop crouch
if (Input.GetKeyUp(crouchKey))
{
transform.localScale = new Vector3(transform.localScale.x, startYScale, transform.localScale.z);
sliding = false;
}
}
private void StateHandler()
{
// Mode - Crouching
if (Input.GetKey(crouchKey))
{
state = MovementState.crouching;
moveSpeed = crouchSpeed;
}
// Mode - Sliding
if(Input.GetKey(crouchKey) && sprinting)
{
state = MovementState.sliding;
moveSpeed = slideSpeed;
}
// Mode - Sprinting
else if (grounded && Input.GetKey(sprintKey) && Input.GetKey(KeyCode.W))
{
state = MovementState.sprinting;
moveSpeed = sprintSpeed;
sprinting = true;
}
// Mode - Walking
else if (grounded)
{
state = MovementState.walking;
moveSpeed = walkSpeed;
}
// Mode - Air
else
{
state = MovementState.air;
}
}
private void MovePlayer()
{
// calculate movement direction
moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
// on slope
if (OnSlope() && !exitingSlope)
{
rb.AddForce(GetSlopeMoveDirection() * moveSpeed * 20f, ForceMode.Force);
if (rb.velocity.y > 0)
rb.AddForce(Vector3.down * 80f, ForceMode.Force);
}
// on ground
else if (grounded)
rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
// in air
else if (!grounded)
rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
// turn gravity off while on slope
rb.useGravity = !OnSlope();
}
private void SpeedControl()
{
// limiting speed on slope
if (OnSlope() && !exitingSlope)
{
if (rb.velocity.magnitude > moveSpeed)
rb.velocity = rb.velocity.normalized * moveSpeed;
}
// limiting speed on ground or in air
else
{
Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
// limit velocity if needed
if (flatVel.magnitude > moveSpeed)
{
Vector3 limitedVel = flatVel.normalized * moveSpeed;
rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
}
}
}
private void Jump()
{
exitingSlope = true;
// reset y velocity
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
private void ResetJump()
{
readyToJump = true;
exitingSlope = false;
}
private bool OnSlope()
{
if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, playerHeight * 0.5f + 0.3f))
{
float angle = Vector3.Angle(Vector3.up, slopeHit.normal);
return angle < maxSlopeAngle && angle != 0;
}
return false;
}
private Vector3 GetSlopeMoveDirection()
{
return Vector3.ProjectOnPlane(moveDirection, slopeHit.normal).normalized;
}
private void StartSlide()
{
sliding = true;
transform.localScale = new Vector3(transform.localScale.x, slideYScale, transform.localScale.z);
rb.AddForce(Vector3.down * 5f, ForceMode.Impulse);
slideTimer = maxSlideTime;
}
private void SlidingMovement()
{
Vector3 inputDirection = orientation.forward;
rb.AddForce(inputDirection.normalized * slideForce, ForceMode.Force);
slideTimer -= Time.deltaTime;
if (slideTimer <= 0)
StopSlide();
}
private void StopSlide()
{
sliding = false;
transform.localScale = new Vector3(transform.localScale.x, startYScale, transform.localScale.z);
}
}
I have been trying for a very long time to fix this, although I'm not the best at coding. I decided to come onto stack overflow for some help. Thank you to everyone who tries to solves this problem :D. As the titles states everything here works, excluding the crouching, when I press ctrl my moveSpeed does not change to my crouchSpeed...
I created a script to make the character dash to the left or to the right but no matter what I do the character won't get pushed horizontally, when I switch it so that the character is pushed upwards the vector does work.
at the vectors there are two different ways of using methods because i tried both to see if either would work but they didn't.
here's the script.
public float speed;
public float jumpForce;
public float inputHorizontal;
public Rigidbody2D rb;
public float checkRadius;
bool isGrounded;
public Transform groundCheck;
public LayerMask whatIsGround;
public float dashSpeed;
public float dashTimeValue;
private float dashTime;
int extraJumps;
public int extraJumpsValue;
private bool facingRight = true;
void Start()
{
rb = GetComponent<Rigidbody2D>();
dashTime = dashTimeValue;
}
void Update()
{
if(isGrounded == true)
{
extraJumps = extraJumpsValue;
}
if(Input.GetKeyDown(KeyCode.Space) && extraJumps > 0)
{
rb.velocity = new Vector2(0f, jumpForce);
extraJumps = extraJumps - 1;
}
if(Input.GetKeyDown(KeyCode.F))
{
if(dashTime == dashTimeValue && facingRight == true)
{
rb.velocity = new Vector2(dashSpeed, 1f);
Debug.Log("eh");
dashTime -= Time.deltaTime;
}else if(dashTime == dashTimeValue && facingRight == false)
{
rb.velocity = Vector2.left * dashSpeed;
Debug.Log("eh");
dashTime -= Time.deltaTime;
}
dashTime = dashTimeValue;
}
}
void FixedUpdate()
{
inputHorizontal = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(inputHorizontal * speed, rb.velocity.y);
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
if(facingRight == false && inputHorizontal > 0){
Flip();
}else if(facingRight == true && inputHorizontal < 0){
Flip();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
Recently I have been Frankensteining code I've found online together and I am struggling to implement the dash correctly. In its current state, whenever my character jumps and then uses his dash, he gets caught in the air as if the dash didn't move him. Obviously this inst intended and I was wondering how I could fix this. Also, how could I include a cool down system to my dash ability. I've tried using various sources for cool down scripts but they always seem to have a downside.
Thanks in advance!
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
//Player Movement
public float speed;
public float jumpForce;
public Transform feetPos;
public float checkRadius;
public LayerMask whatIsGround;
public float dashSpeed;
public float startDashTime;
private float timeStamp = 0;
public Animator animator;
private Rigidbody2D rb;
private float moveInput;
private bool isGrounded;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private float dashTime;
public int direction;
void Start()
{
animator.GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
dashTime = startDashTime;
}
void FixedUpdate()
{
moveInput = Input.GetAxisRaw("Horizontal");
if (direction < 1)
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
}
void Update()
{
// Moving
isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
if (moveInput > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
animator.SetBool("Moving", true);
}
else if (moveInput < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
animator.SetBool("Moving", true);
}
else
{
animator.SetBool("Moving", false);
}
// Jumping
if (isGrounded == true && Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("IsJumping");
isJumping = true;
jumpTimeCounter = jumpTime;
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKey(KeyCode.Space) && isJumping == true)
{
if (jumpTimeCounter > 0)
{
rb.velocity = Vector2.up * jumpForce;
jumpTimeCounter -= Time.deltaTime;
}
else
{
isJumping = false;
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
}
if (isGrounded == false)
{
animator.SetBool("Grounded", false);
}
if (isGrounded == true)
{
animator.SetBool("Grounded", true);
}
// Dashing
if (direction == 0)
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
if ((transform.rotation.eulerAngles.y == 180))
{
Dashleft();
}
else
{
DashRight();
}
}
}
else
{
if (dashTime <= 0)
{
direction = 0;
dashTime = startDashTime;
rb.velocity = Vector2.zero;
}
else
{
dashTime -= Time.deltaTime;
}
}
void Dashleft()
{
direction = 1;
rb.velocity = Vector2.left * dashSpeed;
}
void DashRight()
{
direction = 1;
rb.velocity = Vector2.right * dashSpeed;
}
}
}