Headbob script not working right

Discuss coding questions, pull requests, and implementation details.
User avatar
MeteoricDragon
Posts: 141
Joined: Mon Feb 12, 2018 8:23 pm

Headbob script not working right

Post by MeteoricDragon » Sun Mar 25, 2018 4:35 am

This is my first unity script function and it doesn't work right. I'm trying to get the player's head to bob when walking.

I think that Time.deltaTime gives me time since last frame was rendered but I think I need actual time to test it.

private void BobCheck()
{
// TODO: add toggle variable for setting Head bobbing on/off
//if (HeadBobSetting == false)
// return;

float movementPerFrame = new Vector2(moveDirection.x, moveDirection.z).magnitude;
float horizontalVelocity = movementPerFrame / Time.deltaTime;

if (grounded && (horizontalVelocity > 0))
{
float bobOscillate = Mathf.Sin(Time.deltaTime * horizontalVelocity * (2 * Mathf.PI) );
bobOscillate = Mathf.Clamp(bobOscillate, 0.0f, 1.0f);

Debug.Log("bobOscillate = " + bobOscillate);

float headPos = eyeHeight;
headPos += bobOscillate;
Vector3 pos = mainCamera.transform.localPosition;
pos.y = (standingHeight / 2) - headPos;
mainCamera.transform.localPosition = pos;
controller.height = standingHeight;

}
}

User avatar
Interkarma
Posts: 5188
Joined: Sun Mar 22, 2015 1:51 am

Re: Headbob script not working right

Post by Interkarma » Sun Mar 25, 2018 5:27 am

Without going too deeply into rest of script, Time.deltaTime should be a multiplier (e.g. change = speed * Time.deltaTime).

But you're using it as a divisor in the first case (horizontalVelocity = movementPerFrame / Time.deltaTime) and then as a multiplier in the second (Time.deltaTime * horizontalVelocity). This is the same as just feeding movementPerFrame straight into your sin function without using deltaTime at all.

By all means experiment without using deltaTime. Work out the waveform sampling and changing camera position first, then work out making it frame-rate independent. It can be helpful as a learning exercise to further break down the problems like this until none remain.

User avatar
MeteoricDragon
Posts: 141
Joined: Mon Feb 12, 2018 8:23 pm

Re: Headbob script in progress

Post by MeteoricDragon » Mon Mar 26, 2018 2:33 am

Hey! Thanks! I got it working kind of! The head does bob, but it needs adjustments. And it.. breaks crouching and riding

In order to allow it to work with crouching, cart riding, and horseback riding, I need to change the bobPosition variable I set to the current position of the player camera. Look at the line I bolded below in code. I set the player's initial bob position to the same position that the players head gets set to when he is standing.

private void BobCheck()
{
float bobbingSpeed = 0.18f;
float bobbingAmount = 0.16f;
float bobPosition = (standingHeight / 2) - eyeHeight;

float waveslice = 0.0f;
//float horizontal = Input.GetAxis("Horizontal");
//float vertical = Input.GetAxis("Vertical");
float horizontalVelocity = new Vector2(moveDirection.x, moveDirection.z).magnitude;

Vector3 pos = mainCamera.transform.localPosition;

if (horizontalVelocity == 0)
{
bobTimer = 0.0f;
}
else
{
waveslice = Mathf.Sin(bobTimer);
bobTimer += bobbingSpeed;
if (bobTimer > Mathf.PI * 2)
{
bobTimer -= (Mathf.PI * 2);
}
//Debug.Log("waveslice = " + waveslice + ", eyePosition = " + eyePosition + ", TimeDelta = " + Time.deltaTime + ", Bob: " + bobbingSpeed + ", Timer: " + bobTimer);
}
if (waveslice != 0)
{
float changeAmount = waveslice * bobbingAmount;

horizontalVelocity = Mathf.Clamp(horizontalVelocity, 0.0f, 1.0f);
changeAmount = horizontalVelocity * changeAmount;
pos.y = bobPosition - changeAmount;
}
else
{
pos.y = bobPosition;
}

mainCamera.transform.localPosition = pos;
controller.height = standingHeight;

}

User avatar
Interkarma
Posts: 5188
Joined: Sun Mar 22, 2015 1:51 am

Re: Headbob script not working right

Post by Interkarma » Mon Mar 26, 2018 2:54 am

One possibility is to watch TransportManager.TransportMode (the TransportManager component is on Player object and available through GameManager.Instance) then change your base height depending on mode player is currently in.

A better idea might be to check PlayerMotor .isRiding / .isCrouching / .isClimbing etc. and adjust base height or disable bob as appropriate.

Also something to keep in mind is that PlayerMotor is scheduled for a major refactor in 0.5 at some point. This will be to clean up, improve design, and allow for moddable player movement states. Most of the current motor code will be thrown out or rewritten at this point. If you would like to submit your work on headbob as a PR later, please design to be a standalone MonoBehaviour if possible rather than edit into existing PlayerMotor script. This will allow headbob to be enabled/disabled independently and improve changes of making transition into motor refactor.

Keep it up! :)

User avatar
MeteoricDragon
Posts: 141
Joined: Mon Feb 12, 2018 8:23 pm

Re: Headbob script not working right

Post by MeteoricDragon » Mon Mar 26, 2018 4:00 am

I like your suggestion of extending the headbobber from MonoBehavior. also, your other suggestions I like as well. I'm busy the next few days but will try those suggestions as I get time. Thanks!

User avatar
MeteoricDragon
Posts: 141
Joined: Mon Feb 12, 2018 8:23 pm

Re: Headbob script not working right

Post by MeteoricDragon » Mon Mar 26, 2018 9:44 pm

Upon re-reading your post, what does PR stand for? Here in America it often stands for Public Relations, but that wouldn't make sense in this context :D

EDIT: nevermind, I figured it out. Public Release.

User avatar
Jay_H
Posts: 3147
Joined: Tue Aug 25, 2015 1:54 am

Re: Headbob script not working right

Post by Jay_H » Mon Mar 26, 2018 9:49 pm

Pull Request. It's a tool in github to transfer work from one user to another :)
Come join Lysandus' Tomb, a Daggerfall Unity fan Discord.
See the Daggerfall Unity Wiki on the UESP.

User avatar
MeteoricDragon
Posts: 141
Joined: Mon Feb 12, 2018 8:23 pm

Re: Headbob script not working right

Post by MeteoricDragon » Mon Mar 26, 2018 10:36 pm

Since I'm developing a class for Headbobber which extends MonoBehavior, how can I use that class's methods in DFU?

Do I call simply call them by instantiating a Headbobber instance in the playermotor class and calling methods from the instance there? or is there an easier way? If there's an update method in the headbobber class, does the instance I create in Playermotor simply start executing after being instantiated?

User avatar
Interkarma
Posts: 5188
Joined: Sun Mar 22, 2015 1:51 am

Re: Headbob script not working right

Post by Interkarma » Mon Mar 26, 2018 11:12 pm

What Jay said. :) PR in context of source repositories is a pull request where you send code to the master repository for the caretakers to check and merge when happy. You'll need to fork the main source code, create a branch of your own, add new work to that branch, then issue PR to my master when done. I might merge PR into a branch of its own on my end first for testing before it's merged to master. But no need to worry about that right now, it all comes at the end when you're ready to send changes my way.

Here's a high-level overview of executing that code in Unity.
  1. Create a new MonoBehaviour-derived class called HeadBobber (or whatever makes sense).
  2. Attach this component to PlayerAdvanced prefab (which will in turn add it to player instance in scene). The script will become active with player when game runs.
  3. In your headbob script Start() method, use GetComponent<PlayerMotor>() to cache a reference to the peered motor component on the player object.
  4. Then implement headbob logic and check the available fields & properties of playerMotor reference.
Let us know how you go!

User avatar
MeteoricDragon
Posts: 141
Joined: Mon Feb 12, 2018 8:23 pm

Re: Headbob script not working right

Post by MeteoricDragon » Tue Mar 27, 2018 5:22 am

Great news.

I got the headbob script working correctly for crouch, walk, run, and horse. I have different amplitude and frequency settings for all 4, the side-to-side parabolic bob for each movement type can be tweaked independently of the up and down parabolic bob for each movement speed. The bobbing speed is synchronized to the player's footsteps(even when crouching). It also does some linear interpolation to transition smoothly between head bobbing and not bobbing and vice versa. It's separated into several virtual methods for mod overriding of the algorithm for the head bob. It's all in a separate class called HeadBobbing.

Next to allow user toggling of this. I should find out how to un-shade the headbobbing checkbox on the menu screen and allow player to click there if I can figure out what files need to be modified.

Post Reply