Ive been trying for the past 2 days to get a headbob script going, but i keep getting stuck at checking the controller velocity, which keeps returning zero. I have 2 scripts, playermotor, that moves the character, and headbob script, which calculates and applies headbob based on controller velocity, which both on the player object, and when i use controller.velocity in headbob script it returns always 0,0,0, but when i use it in playermotor script it work fine. Is the order of scripts causing this issue? Ive done it 1:1 with the tutorials, and the only difference is i made the camera and motor scripts slightly different.
Here are the scripts:
Player Motor script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMotor : MonoBehaviour
{
private CharacterController controller;
private Vector3 playerVelocity;
private PlayerLook look;
private float speed = 5f;
public float crouchSpeed = 2.5f;
public float walkSpeed = 5f;
public float sprintSpeed = 8f;
public float jumpHeight = 0.6f;
private float crouchTimer = 1f;
public float gravity = -9.8f;
private float standingHeight = 2;
private float crouchingHeight = 1;
private float targetHeight = 2;
private bool isGrounded;
private bool crouching= false;
private bool sprinting = false;
private bool lerpCrouch=false;
Vector3 initialCameraPosition;
void Start()
{
controller = GetComponent<CharacterController>();
look = GetComponent<PlayerLook>();
initialCameraPosition = look.cam.transform.localPosition;
}
// Update is called once per frame
void Update()
{
isGrounded = controller.isGrounded;
if(lerpCrouch)
{
crouchTimer += Time.deltaTime;
float p = crouchTimer / 1;
p *= p;
if(controller.height<standingHeight && targetHeight == standingHeight)
{
var castOrigin = transform.position + new Vector3(0, controller.height / 2, 0);
if (Physics.Raycast(castOrigin, Vector3.up, out RaycastHit hit, 0.2f))
{
var distanceToCeiling = hit.point.y - castOrigin.y;
targetHeight = Mathf.Max (controller.height + distanceToCeiling -0.1f,crouchingHeight);
}
}
controller.height = Mathf.Lerp(controller.height, targetHeight, p);
if(p>1)
{
lerpCrouch = false;
crouchTimer = 0f;
}
}
}
public void ProcessMove(Vector2 input)
{
Vector3 moveDirection = Vector3.zero;
moveDirection.x = input.x;
moveDirection.z = input.y;
controller.Move(transform.TransformDirection(moveDirection)*speed*Time.deltaTime);
playerVelocity.y += gravity * Time.deltaTime;
if(isGrounded &&playerVelocity.y <0)
{
playerVelocity.y = -2f;
}
if (!Mathf.Approximately(targetHeight, controller.height))
{
var halfHeightDifference = new Vector3(0, (standingHeight - controller.height) / 2, 0);
var newCameraPosition = initialCameraPosition - halfHeightDifference;
look.cam.transform.localPosition = newCameraPosition;
}
controller.Move(playerVelocity*Time.deltaTime);
}
public void Jump()
{
if(isGrounded)
{
playerVelocity.y = Mathf.Sqrt(jumpHeight*-3.0f * gravity);
}
}
public void Crouch()
{
crouching = !crouching;
sprinting = false;
if (crouching)
{
targetHeight = crouchingHeight;
speed = crouchSpeed;
}
else
{
targetHeight = standingHeight;
speed = walkSpeed;
}
crouchTimer = 0;
lerpCrouch = true;
}
public void Sprint()
{
if(!crouching)
{
sprinting = !sprinting;
if (sprinting)
{
speed = sprintSpeed;
}
else
{
speed = walkSpeed;
}
}
}
}
Headbob script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeadBobController : MonoBehaviour
{
[SerializeField] private bool _enable = true;
[SerializeField, Range(0, 0.1f)] private float _amplitude = 0.015f;
[SerializeField, Range(0, 30)] private float _frequency = 10.0f;
[SerializeField] private Transform _camera = null;
[SerializeField] private Transform _cameraHolder = null;
private float _toggleSpeed = 3.0f;
private Vector3 _startPos;
private CharacterController _controller;
private void Awake()
{
_controller = GetComponent<CharacterController>();
_startPos = _cameraHolder.localPosition;
}
private void Update()
{
if (!_enable)
return;
CheckMotion();
ResetPosition();
_camera.LookAt(FocusTarget());
}
private void CheckMotion()
{
float speed = new Vector3(_controller.velocity.x, 0, _controller.velocity.z).magnitude;
Debug.Log(_controller.velocity.magnitude);
if (speed < _toggleSpeed)
return;
if (!_controller.isGrounded)
return;
PlayMotion(FootStepMotion());
}
private void PlayMotion(Vector3 motion)
{
_camera.localPosition += motion;
}
private Vector3 FootStepMotion()
{
Vector3 pos = Vector3.zero;
pos.y += Mathf.Sin(Time.time * _frequency) * _amplitude;
pos.x += Mathf.Cos(Time.time * _frequency / 2) * _amplitude * 2;
return pos;
}
private void ResetPosition()
{
if (_camera.localPosition == _startPos)
return;
_camera.localPosition = Vector3.Lerp(_camera.localPosition, _startPos, 1 * Time.deltaTime);
}
private Vector3 FocusTarget()
{
Vector3 pos = new Vector3(transform.position.x, transform.position.y + _cameraHolder.localPosition.y, transform.position.z);
pos += _cameraHolder.forward * 15.0f;
return pos;
}
}
Ive tried multiple methods, but this method of headbobing is the closest to what i want.
Spooky_REX is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.