# Confused about Time.deltaTime

So I’m trying to make a sort of target that appears in front of the player, to show how long the kick will be. But it keeps stopping at different positions, and I’m pretty sure it has something to do with Time.deltaTime but I don’t know how I’d go about fixing it. Any help would be immensely appreciated. Below is the code for the target.

``````using UnityEngine;
using System.Collections;

public class PlayerKickEffect : MonoBehaviour {

public PlayerMovement player;
public bool beforeKick;

void Start () {
GetComponent<SpriteRenderer>().enabled = false;
}

void Update () {

if (Input.GetKeyDown (KeyCode.X) && !beforeKick && !player.kick)
GetComponent<SpriteRenderer>().enabled = true;

if (Input.GetKey (KeyCode.X))
beforeKick = true;

if (Input.GetKeyUp (KeyCode.X))
{
beforeKick = false;
GetComponent<SpriteRenderer>().enabled = false;
transform.localPosition = new Vector2 (0, 0);
}

if (beforeKick && player.kickLength > 0 && player.kickLength < 10)
{
if (player.transform.localScale.x > 0)
transform.Translate (4 * Time.deltaTime, 0, 0);
if (player.transform.localScale.x < 0)
transform.Translate (-4 * Time.deltaTime, 0, 0);
}

if (Input.GetKeyDown (KeyCode.A))
Debug.Log (transform.localPosition);
}
}
``````

Why do you use Time.deltaTime? Multiplying the translate movement by Time.deltaTime will stop the movement after “The time in seconds it took to complete the last frame…”. If the last frame took, 1/100 of a second to complete, the movement will stop after 1/100 of a second and, most probably, never complete.

(At least, that’s how I understand it.)

not exactly Update is called every frame, deltatime is the time it takes a frame to update in seconds, so multiply his -4 * deltaTime, is scaling his -4 down, so the action of translating -4 units on the x happens over 1 full second.

1 Like

I use Time.deltaTime so that the character won’t move different distances depending on the framerate… But clearly I haven’t managed to accomplish that task.

Okay… so let me start by saying that Time.Delta is not your problem here. I just think it’s application is in the wrong place.

So if what I’m understanding is correct you have a player character. Lets say at 10,10,0. And when they hold X the strength of the kick builds up to a max of 10. Depending on the strength you want to show a target of where letting go of X would do at that given moment.

There are two key pieces of information here that you want to not be different if their frame varies. How fast the player moves and how fast the kick strength builds up.

But not necessarily where you’re rendering the sprite for the target.

Your approach in this regard is a little off. You should start by just assuming that the kick power will always be 5. And work out how you would like to calculate what distance 5 power means for the kick. Then you can have holding X increase the kick power by a certain amount affected by time delta. This way X goes up by 1 ever real world second. And not 1 every 30 frames. Otherwise, someone running at 60 FPS would get double the kicking power which could lead to balancing issues.

Consider the following (Keep in mind this won’t directly work for your case, its just an example):

``````float currentKickingPower = 0;
SpriteRenderer sprite;

void Start(){
sprite = GetComponent<SpriteRenderer>();
}

void Update(){

if (Input.GetKeyDown(KeyCode.X)){
sprite.enabled = true;
currentKickingPower += 1.0f * Time.deltaTime;

// Determine where the player is
Vector3 targetLocation = player.transform.localPosition;

// Move forward our kicking power
targetLocation += player.transform.forward * currentKickingPower;

// Set our location there
transform.localPosition = targetLocation;

}
else{
sprite.enabled = false;
currentKickingPower = 0;
}

}
``````
1 Like

Thank you for the detailed answer, this is more to take in than I imagined so I’ll wait until tomorrow, when I’m not so tired. I’ll let you know if I get it to work!

Well, thanks for the precision; I apparently didn’t understand and I understand less now. Not your fault, of course.

more or less multiply anything that happens in update by deltaTime, and instead of it doing what you told it to do over 1 frame update, it does it over 1 second.
Translate(-4, 0, 0) would move you -4 units every Update, while Translate(-4f * Time.deltaTime, 0, 0) would move you -4 units every second.

1 Like

The easiest way to think of Delta time is in the scope of 1 Second real world time and the float value of 1.0f

If you have a script that you want to run every frame and move a character 1 unit every second then you can utilize Time.deltaTime

So for instance, if your script runs 30 times because the program is rendering at 30 FPS then you would want the value to be 1/30 each time the script ran. Because if you add 1/30 30 times it comes out to 1. However, if you actually set your value to 1/30 and the program actually runs at 60 FPS now you’re going to have moved 2 units after a second has passed. So by multiplying TIme.deltaTime by 1.0f you get the mathematical equivalent of what the fraction of that value should be for the number of frames that will render until a second has passed.

1 Like

Okay. My first understanding of Time.deltaTime was “Time.deltaTime = 1 second”. So -4 * Time.deltaTime would translate in current language into “-4 per second”. How is that?

yes correct

The value of time.deltaTime changes based on your framerate, it doesn’t represent 1 second, it represents how long a frame takes to update and is equal to 1 divided by your framerate.

If you are running at 60fps time.deltaTime is equal to 1/60, and 1/30 for 30fps etc.

@hawksprite explained it well

1 Like

Ah, now I understand! Thank you!

I had noticed that translations movement happened way too fast for my liking when set by script; so, now I use animations instead; they allow me to control the duration of the movement.

Well, I made it work! I just needed to change my approach a bit. Thank you so much for helping me out, without you I’d probably still think it was Time.deltaTime I was having trouble with.

2 Likes

I am having a similar issue, when I don’t use Time.deltaTime, my characters move freely, but when I put it on they walk and run in place while barely jumping. The following is from a tutorial on YouTube by IheartGameDev so please do not ask me why things are used the way they are. My main problem is trying to get the jump animation to work like the walking and running do. When I take off TdT the character lifts in the air but doesn’t animate, so I put TdT back in the code to try and fix this, but like I said the character just runs and walks in place.

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class AnimationAndMovementController : MonoBehaviour
{

PlayerInput playerInput;
CharacterController characterController;
Animator animator;

int isWalkingHash;
int isRunningHash;

Vector2 currentMovementInput;
Vector3 currentMovement;
Vector3 currentRunMovement;
bool isMovementPressed;
bool isRunPressed;

float rotationFactorPerFrame = 15.0f;
float runMultiplier = 3.0f;
int zero = 0;
float gravity = -9.8f;
float groundedGravity = -.05f;

bool isJumpPressed = false;
float initialJumpVelocity;
float maxJumpHeight = 4.0f;
float maxJumpTime = .75f;
bool isJumping = false;
int isJumpingHash;
bool isJumpAnimating = false;

void Awake()
{
playerInput = new PlayerInput();
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();

isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
isJumpingHash = Animator.StringToHash("isJumping");

playerInput.CharacterControls.Move.started += onMovementInput;
playerInput.CharacterControls.Move.canceled += onMovementInput;
playerInput.CharacterControls.Move.performed += onMovementInput;
playerInput.CharacterControls.Run.started += onRun;
playerInput.CharacterControls.Run.canceled += onRun;
playerInput.CharacterControls.Jump.started += onJump;
playerInput.CharacterControls.Jump.canceled += onJump;

setupJumpVariables();
}

void setupJumpVariables()
{
float timeToApex = maxJumpTime / 2;
gravity = (-2 * maxJumpHeight) / Mathf.Pow(timeToApex, 2);
initialJumpVelocity = (2 * maxJumpHeight) / timeToApex;
}

void handleJump()
{
if (!isJumping && characterController.isGrounded && isJumpPressed)
{
animator.SetBool("isJumpingHash", true);
isJumpAnimating = true;
isJumping = true;
currentMovement.y = initialJumpVelocity * 1.5f;
currentRunMovement.y = initialJumpVelocity * 1.5f;
}
else if (!isJumpPressed && isJumping && characterController.isGrounded)
{
isJumping = false;
}
}

void onJump(InputAction.CallbackContext context)
{
Debug.Log(isJumpPressed);
}

void onRun(InputAction.CallbackContext context)
{
}

void handleRotation()
{
Vector3 positionToLookAt;

positionToLookAt.x = currentMovement.x;
positionToLookAt.y = 0.0f;
positionToLookAt.z = currentMovement.z;
Quaternion currentRotation = transform.rotation;

if (isMovementPressed)
{
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame);
}
}

void onMovementInput(InputAction.CallbackContext context)
{
currentMovement.x = currentMovementInput.x;
currentMovement.z = currentMovementInput.y;
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}

void handleAnimation()
{
bool isWalking = animator.GetBool(isWalkingHash);
bool isRunning = animator.GetBool(isRunningHash);

if (isMovementPressed && !isWalking)
{
animator.SetBool(isWalkingHash, true);
}

else if (!isMovementPressed && isWalking)
{
animator.SetBool(isWalkingHash, false);
}

if ((isMovementPressed && isRunPressed) && !isRunning)
{
animator.SetBool(isRunningHash, true);
}

else if ((!isMovementPressed || !isRunPressed) && isRunning)
{
animator.SetBool(isRunningHash, false);
}
}

void handleGravity()
{
bool isFalling = currentMovement.y <= 0.0f || !isJumpPressed;
float fallMultiplier = 2.0f;

if (characterController.isGrounded) {
if (isJumpAnimating) {
animator.SetBool("isJumpingHash", false);
isJumpAnimating = false;
}
currentMovement.y = groundedGravity * Time.deltaTime;
currentRunMovement.y = groundedGravity * Time.deltaTime;
}else if (isFalling) {
float previousYVelocity = currentMovement.y;
float newYVelocity = currentMovement.y + (gravity * fallMultiplier * Time.deltaTime);
float nextYVelocity = (previousYVelocity + newYVelocity) * .5f;
currentMovement.y = nextYVelocity;
currentRunMovement.y = nextYVelocity;

} else {
float previousYVelocity = currentMovement.y;
float newYVelocity = currentMovement.y + (gravity);
float nextYVelocity = (previousYVelocity + newYVelocity) * .5f;
currentMovement.y = nextYVelocity;
currentRunMovement.y = nextYVelocity;
}
}

// Update is called once per frame
void Update()
{
handleRotation();
handleAnimation();

if (isRunPressed)
{
characterController.Move(currentRunMovement * Time.deltaTime);
}
else
{
characterController.Move(currentMovement * Time.deltaTime);
}
handleGravity();
handleJump();
}

void OnEnable()
{
playerInput.CharacterControls.Enable();
}

void OnDisable()
{
playerInput.CharacterControls.Disable();
}
}
``````

Please don’t necro threads like this. Also, don’t cross-post: help with Time.deltaTime