Question by
hejlskov · Nov 09, 2020 at 12:56 PM ·
movementcharactercontrollerfps controllerjitter
Frustrating Problem with Character Controller in FPS
I am trying to make an FPS using the character controller based on a simplified version of the MicroFPS project with wall running etc, but I have run into a frustrating problem. When moving around, the charatcer suddenly starts jittering and zig-zagging, both on ground and when in the air. I have attached the two scripts below. PLEASE HELP!
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class WallRun : MonoBehaviour
{
public float wallSpeedMultiplier = 1.25f;
public float wallBouncing = 3.0f;
public float maximumAngleRoll = 20.0f;
public float jumpDuration = 1.0f;
private PlayerCharacterController playerCharacterControllerComponent;
private Camera cameraComponent;
private Vector3[] directions;
private RaycastHit[] raycastHits;
private Vector3 lastWallPosition = Vector3.zero;
private Vector3 lastWallNormal = Vector3.zero;
private bool isWallRunning = false;
private bool isJumping = false;
private float elapsedTimeSinceJump = 0.0f;
public bool IsWallRunning() => isWallRunning;
// Start is called before the first frame update
private void Start()
{
playerCharacterControllerComponent = GetComponent<PlayerCharacterController>();
cameraComponent = GetComponentInChildren<Camera>();
directions = new Vector3[] { Vector3.right, Vector3.right + Vector3.forward, Vector3.forward, Vector3.left + Vector3.forward, Vector3.left };
}
// Update is called once per frame
private void Update()
{
}
private void LateUpdate()
{
isWallRunning = false;
if (!playerCharacterControllerComponent.IsGrounded() && playerCharacterControllerComponent.GetJumpInputDown())
{
isJumping = true;
}
if (CanAttach())
{
raycastHits = new RaycastHit[directions.Length];
for (int i = 0; i < directions.Length; i++)
{
Vector3 direction = transform.TransformDirection(directions[i]);
Physics.Raycast(transform.position, direction, out raycastHits[i], 1.0f);
if (raycastHits[i].collider != null)
{
Debug.DrawRay(transform.position, direction, Color.green);
}
else
{
Debug.DrawRay(transform.position, direction, Color.red);
}
}
if (CanWallRun())
{
raycastHits = raycastHits.ToList().Where(h => h.collider != null).OrderBy(h => h.distance).ToArray();
if (raycastHits.Length > 0)
{
OnWall(raycastHits[0]);
lastWallPosition = raycastHits[0].point;
lastWallNormal = raycastHits[0].normal;
}
}
}
}
private bool CanWallRun()
{
if (playerCharacterControllerComponent != null)
{
return !playerCharacterControllerComponent.IsGrounded() && playerCharacterControllerComponent.GetMovementInput().z > 0;
}
return false;
}
bool CanAttach()
{
if (isJumping)
{
elapsedTimeSinceJump += Time.deltaTime;
if (elapsedTimeSinceJump > jumpDuration)
{
elapsedTimeSinceJump = 0.0f;
isJumping = false;
}
return false;
}
return true;
}
private void OnWall(RaycastHit raycastHit)
{
if (Vector3.Dot(raycastHit.normal, Vector3.up) >= -0.1f && Vector3.Dot(raycastHit.normal, Vector3.up) <= 0.1f)
{
isWallRunning = true;
Vector3 targetVelocity = Vector3.Cross(raycastHit.normal, Vector3.up);
if (Vector3.Dot(transform.TransformDirection(Vector3.forward), targetVelocity) < 0.0f)
{
targetVelocity *= -1.0f;
}
targetVelocity *= 10.0f * wallSpeedMultiplier;
playerCharacterControllerComponent.characterVelocity = targetVelocity;
}
}
private float CalculateSide()
{
if (isWallRunning)
{
return Vector3.Dot(Vector3.Cross(transform.forward, (lastWallPosition - transform.position)), transform.up);
}
return 0.0f;
}
public float CameraRoll()
{
float currentAngle = cameraComponent.transform.eulerAngles.z;
float targetAngle = 0.0f;
if (CalculateSide() != 0.0f)
{
targetAngle = Mathf.Sign(CalculateSide()) * maximumAngleRoll;
}
return Mathf.LerpAngle(currentAngle, targetAngle, Time.deltaTime * 5.0f);
}
public Vector3 GetWallJumpDirection()
{
if (isWallRunning)
{
return lastWallNormal * wallBouncing + Vector3.up;
}
print("HI");
return Vector3.zero;
}
}
AND
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using UnityEngine;
public class PlayerCharacterController : MonoBehaviour
{
[HideInInspector] public Vector3 characterVelocity = Vector3.zero;
public float speedOnGround = 10.0f;
public float movementSharpnesOnGround = 15.0f;
public float sprintSpeedMultiplier = 2f;
public float jumpForce = 4.0f;
public float gravityDownForce = 10.0f;
private CharacterController characterControllerComponent;
private bool isGrounded = false;
private bool canDoubleJump = false;
public float rotationSpeed = 5.0f;
private Camera cameraComponent;
private float cameraVerticalRotation = 0.0f;
//private bool isGrappling = false;
//private Vector3 grapplePoint = Vector3.zero;
//private GameObject grappleAnchor;
//private LineRenderer lineRendererComponent;
//private float targetFieldOfView = 0.0f;
private WallRun wallRunComponent;
public bool IsGrounded() => isGrounded;
// Start is called before the first frame update
private void Start()
{
characterControllerComponent = GetComponent<CharacterController>();
cameraComponent = GetComponentInChildren<Camera>();
//lineRendererComponent = GetComponent<LineRenderer>();
wallRunComponent = GetComponent<WallRun>();
//lineRendererComponent.enabled = false;
//targetFieldOfView = 60.0f;
}
// Update is called once per frame
private void Update()
{
isGrounded = false;
isGrounded = characterControllerComponent.isGrounded;
HandleMovement();
}
private void HandleMovement()
{
cameraVerticalRotation -= GetLookInputVertical() * rotationSpeed;
cameraVerticalRotation = ClampAngle(cameraVerticalRotation, -60.0f, 60.0f);
if (wallRunComponent == null)
{
cameraComponent.transform.localEulerAngles = new Vector3(cameraVerticalRotation, 0.0f, 0.0f);
}
else
{
cameraComponent.transform.localEulerAngles = new Vector3(cameraVerticalRotation, 0.0f, wallRunComponent.CameraRoll());
}
transform.Rotate(new Vector3(0.0f, ClampAngle(GetLookInputHorizontal() * rotationSpeed, -360.0f, 360.0f), 0.0f), Space.Self);
bool isSprinting = GetSprintInputHeld();
float speedModifier = isSprinting ? sprintSpeedMultiplier : 1.0f;
Vector3 worldSpaceMoveInput = transform.TransformVector(GetMovementInput());
if (isGrounded || (wallRunComponent != null & wallRunComponent.IsWallRunning()))
{
if (isGrounded)
{
Vector3 targetVelocity = worldSpaceMoveInput * speedOnGround * speedModifier;
characterVelocity = Vector3.Lerp(characterVelocity, targetVelocity, movementSharpnesOnGround * Time.deltaTime);
}
if ((isGrounded || (wallRunComponent != null && wallRunComponent.IsWallRunning())) && GetJumpInputDown())
{
if (isGrounded)
{
characterVelocity = new Vector3(characterVelocity.x, 0.0f, characterVelocity.z);
characterVelocity += Vector3.up * jumpForce;
}
else
{
characterVelocity = new Vector3(characterVelocity.x, 0.0f, characterVelocity.z);
characterVelocity += wallRunComponent.GetWallJumpDirection() * jumpForce;
}
isGrounded = false;
}
}
else
{
if (wallRunComponent == null || (wallRunComponent != null & !wallRunComponent.IsWallRunning()))
{
//characterVelocity += worldSpaceMoveInput * 25.0f * Time.deltaTime;
characterVelocity += Vector3.down * gravityDownForce * Time.deltaTime;
}
}
characterControllerComponent.Move(characterVelocity * Time.deltaTime);
}
private float ClampAngle (float angle, float minimum, float maximum)
{
if(angle < -360.0f)
{
angle += 360.0f;
}
else if (angle > 360.0f)
{
angle -= 360.0f;
}
return Mathf.Clamp(angle, minimum, maximum);
}
public float GetLookInputHorizontal()
{
return Input.GetAxisRaw("Mouse X");
}
public float GetLookInputVertical()
{
return Input.GetAxisRaw("Mouse Y");
}
public Vector3 GetMovementInput()
{
Vector3 movementInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0.0f, Input.GetAxisRaw("Vertical"));
movementInput = Vector3.ClampMagnitude(movementInput, 1.0f);
return movementInput;
}
public bool GetSprintInputHeld()
{
return Input.GetKey(KeyCode.LeftShift);
}
public bool GetJumpInputDown()
{
return Input.GetButtonDown("Jump");
}
}
Comment
Your answer
Follow this Question
Related Questions
Moving left to right and after the level ends move character right to left 1 Answer
Ghost car movement jitters when replaying previous race 1 Answer
try to rotate a character controller when translating on z only 0 Answers
Jump logic issues 0 Answers
how to make player movement be based on direction its facing 1 Answer