making an fps controller script
everything works however my headbobbing gives weird results.
the setup is
player(charactercontroller)as root and then a child Cameraroot(empty actor) ,then headbob(emptyActor) and last child is the maincamera
i think it has to do with not getting the correct localvelocity. but im not sure
i used ValuesSum because flax doesnt have magnitude of a Vector3?(i might be wrong)
float velocitySize = velocity.ValuesSum;//magnitude?
the bobbing works but i get sometimes extreme results and sometimes very minimal.
using System;
using System.Collections.Generic;
using FlaxEngine;
namespace Game
{
/// Player Script.
public class Player : Script
{
public Actor camRoot;
public Actor headBob;
private float rotationX;
public float lookSpeed = 10f;
private CharacterController controller;
private Vector3 targetVelocity = Vector3.Zero;
private Vector3 targetDirection = Vector3.Zero;
private Vector3 moveDirection = Vector3.Zero;
public float normalSpeed = 6f;
public float runSpeed = 12f;
public float crouchSpeed = 2f;
private float speed = 0f;
private float wantedSpeed = 0f;
public float jumpHeight = 8f;
public float runJumpHeight = 12f;
public float jumpInterval = 1f;
private float nextJump = 1.2f;
public float Gravity = 20f;
private bool prevGrounded;
//footsteps and headbob
public float headBobFrequency = 1.5f;
public float headBobHeight = .35f;
private float headBobSwayAngle = .5f;
public float headBobSideMovement = .075f;
public float bobHeightSpeedMultiplier = .35f;
public float bobStrideSpeedLengthen = .35f;
public float jumpLandMove = 2f;
public float jumpLandTilt = 35f;
public float springElastic = 1.25f;
public float springDampen = .77f;
private float springPos, springVelocity, headBobFade;
private float headBobCycle;
private float xPos;
private float yPos;
private float xTilt;
private float yTilt;
private float xVelocity = 0.0f;
private Vector3 prevVelocity, prevPosition;
private Vector3 bobStartPosition;
private Quaternion bobStartRotation;
public override void OnStart()
{
speed = normalSpeed;
Screen.CursorVisible = false;
Screen.CursorLock = CursorLockMode.Locked;
controller = Actor as CharacterController;
bobStartPosition = headBob.LocalPosition;
bobStartRotation = headBob.LocalOrientation;
}
public override void OnEnable()
{
// Here you can add code that needs to be called when script is enabled (eg. register for events)
}
/// <inheritdoc/>
public override void OnDisable()
{
// Here you can add code that needs to be called when script is disabled (eg. unregister from events)
}
public override void OnFixedUpdate()
{
Vector3 forward = camRoot.Transform.Forward;
Vector3 right = new Vector3(forward.Z,0f,-forward.X);
//inputmovement
bool isRunning = Input.GetAction("Run");
bool isCrouching = Input.GetAction("Crouch");
var hor = Input.GetAxis("Horizontal");
var ver = Input.GetAxis("Vertical");
Vector3 velocity = controller.Velocity;
Vector3 localVelocity = Transform.WorldToLocalVector(velocity);
bool isMovingForward = localVelocity.Z > 0.5f;
targetDirection = (hor * right) + (ver * forward);
targetDirection = targetDirection.Normalized;
targetVelocity = targetDirection;
if (controller.IsGrounded)
{
if (Input.GetAction("Jump") && Time.GameTime > nextJump)
{
nextJump = Time.GameTime + jumpInterval;
if (isRunning)
{
moveDirection.Y = runJumpHeight;
}
else
{
moveDirection.Y = jumpHeight;
}
//feetaudio.PlayJumpingSound();
//playjumpsound here
}
}
else
{
//not grounded
//airTime += Time.DeltaTime;
moveDirection.Y -= Gravity * Time.DeltaTime;
nextJump = Time.GameTime + jumpInterval;
}
if (isRunning && isMovingForward)
{
speed = runSpeed;
}
else if (isCrouching)
{
speed = crouchSpeed;
}
else
{
speed = normalSpeed;
}
wantedSpeed = Mathf.Lerp(wantedSpeed, speed, 2f * Time.DeltaTime);
targetVelocity *= wantedSpeed;
moveDirection.Z = targetVelocity.Z;
moveDirection.X = targetVelocity.X;
controller.Move(moveDirection);
//playerrotation
rotationX += Input.GetAxis("Mouse Y") * lookSpeed * Time.DeltaTime;
rotationX = Mathf.Clamp(rotationX, -85f, 85f);
camRoot.LocalOrientation = Quaternion.Euler(rotationX, 0f, 0f);
Actor.Orientation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeed * Time.DeltaTime, 0f);
doHeadBob();
/*if (prevGrounded == false && controller.isGrounded)
{
feetaudio.PlaylandingSound();
nextStep = headcontroller.headBobCycle + stepInterval;
}
if (headcontroller.headBobCycle > nextStep)
{
nextStep = headcontroller.headBobCycle + stepInterval;
if (controller.isGrounded || climbladder)
{
feetaudio.playfootsound();
}
}
*/
prevGrounded = controller.IsGrounded;
}
public override void OnUpdate()
{
// Here you can add code that needs to be called every frame
}
public void doHeadBob()
{
Vector3 velocity = (Actor.Position - prevPosition) / Time.DeltaTime;
Vector3 deltaVelocity = velocity - prevVelocity;
prevPosition = Actor.Position;
prevVelocity = velocity;
Vector3 localvelocity = Actor.Transform.WorldToLocalVector(velocity);
//Debug.Log(localvelocity);
/*if (climbladder == false)
{
velocity.Y = 0f;
}
*/
velocity.Y = 0f;
springVelocity -= deltaVelocity.Y;
springVelocity -= springPos * springElastic;
springVelocity *= springDampen;
springPos += springVelocity * Time.DeltaTime;
springPos = Mathf.Clamp(springPos, -.32f, .32f);
if (Mathf.Abs(springVelocity) < .05f && Mathf.Abs(springPos) < .05f)
{
springVelocity = springPos = 0f;
}
float velocitySize = velocity.ValuesSum;//magnitude?
float flatVelocity = velocitySize;
/*
if (Controller.climbladder)
{
flatVelocity *= 4f;
}
else if (Controller.climbladder == false && charactercontrol.isGrounded == false)
{
flatVelocity /= 4f;
}
*/
float strideLengthen = 1f + flatVelocity * bobStrideSpeedLengthen;
headBobCycle += (flatVelocity / strideLengthen) * (Time.DeltaTime / headBobFrequency);
float headBobCyclePi = headBobCycle * Mathf.Pi * 2f;
float bobFactor = Mathf.Sin(headBobCyclePi);
float bobSwayFactor = Mathf.Sin(headBobCyclePi + Mathf.Pi * .5f);
bobFactor = 1f - (bobFactor * .5f + 1f);
bobFactor *= bobFactor;
headBobFade = Mathf.Lerp(headBobFade, (velocitySize < .1f) ? 0f : 1f, Time.DeltaTime);
headBobFade = Mathf.Abs(headBobFade);
float speedHeightFactor = 1f + (flatVelocity * bobHeightSpeedMultiplier);
xPos = -headBobSideMovement * bobSwayFactor * headBobFade;
yPos = springPos * jumpLandMove + bobFactor * headBobHeight * headBobFade * speedHeightFactor;
xTilt = springPos * jumpLandTilt;
yTilt = bobSwayFactor * headBobSwayAngle * headBobFade;
float zTilt = Mathf.SmoothDamp(headBob.LocalPosition.X , localvelocity.X, ref xVelocity, Time.DeltaTime / 0.5f);
Quaternion wantedrotation = Quaternion.Euler(xTilt, yTilt, -zTilt);
Vector3 wantedposition = new Vector3(xPos, yPos, 0f);
headBob.LocalPosition = bobStartPosition + wantedposition;
headBob.LocalOrientation = bobStartRotation * wantedrotation;
}
}
}