Unity 3D Timer seems to be running too fast - c#

When the user presses a button fwdi is set to 1 which starts this if statement. It seems logical to me that if I reduce fwdi by 0.1 every update and move the player 0.1 every update then everything should be done by the 1 second mark however the movement is much quicker than 1 second. I have an animation that also plays which takes 1 second and they don't match up.
EDIT
void Update ()
{
if (fwdi > 0.0f)
{
fwdi = fwdi - 1.0f * Time.deltaTime;
amountToMove.y = 1.0f * Time.deltaTime;
transform.Translate (amountToMove);
if (fwdi == 0.0f)
{
amountToMove.y = 0.0f;
fwdi = 0.0f;
}
}
}

All you should need to do in compensate for frametime (IE: at 60fps, update is called 60times per second)
void Update ()
{
if (fwdi > 0)
{
amountToMove.y = 0.1f*Time.deltaTime;
transform.Translate (amountToMove);
fwdi = fwdi - amountToMove.y;
//This code bellow looks redundant, and probably unnecessary
if (fwdi == 0)
{
amountToMove.y = 0;
fwdi = 0f;
}
}
}
Also consider putting movement on FixedUpdate. Fixed update works similarly to update with a few key differents:
-Fixedupdate has priority over the normal update function,
-unity default call cap for fixed update is 20 times per second
It's commonly suggested that you put, lightweight processes that benefit from predictable update intervals on fixed update, like movement and physics.
Note:: its still a good idea to multiply everything in FixedUpdate by Time.fixedDeltaTime, just in case Fixedupdate fails to reach its 20 tick per second count.

Time.timeScale
Frame rate
Time.deltaTime
Now I know almost nothing about Unity, so this may not be close to an answer. Normally you would make things in games frame rate independent by calculating a factor, say if you wan't to move 1 distance in one second, you calculated time passed and apply a multiplication. E.g. "timepassed-factor * amounttomove"
From what I can gather you need to use Time.deltaTime which would give you the actual time passed between frames, where as timeScale really just is for slow motion etc...
So... amountToMove.y = 1f * Time.deltaTime * ???;

Related

Why Isn't My Jumping Frame Rate Independent in My 2D Unity Game

For some reason I jump at a different height according to frame rate. Why is this happening even though I am using delta time to(try) make it frame rate independant. This is in 2D in case ye needed to know.
void Jump()
{
// Set Delta Time(Time Between Frames)
float dT = Time.deltaTime;
// Counting In Seconds
secondForGravity += dT;
// Check For Input and Jump
if (canJump && Input.GetKeyDown(KeyCode.Space))
{
// Add Jump Height to Velocity
velocity.y += jumpHeight;
// Reset Can Jump
canJump = false;
// Resets Second For Gravity to 0 so You Can't Fall
secondForGravity = 0;
}
// Fall With Gravity
if (!canJump)
{
if(velocity.y > 0)
{
// Rising Metres Per Second * Per Second & Make it Frame Rate Independent
velocity.y -= riseGravity * secondForGravity * dT;
}
else if(velocity.y < 0)
{
// Falling Metres Per Second * Per Second & Make it Frame Rate Independent
velocity.y -= fallGravity * secondForGravity * dT;
// Sets Velocity.y To Max Gravity if Exceeding Max Gravity
if (velocity.y < -maxGravity)
velocity.y = -maxGravity;
}
else
{
// Rising Metres Per Second * Per Second & Make it Frame Rate Independent
velocity.y -= riseGravity * secondForGravity * dT;
}
}
}
void Move()
{
// Move
rb.AddForce(velocity, ForceMode2D.Force);
}
I was wondering if there was anyway I could fix it.
What you’re doing with secondForGravity doesn’t seem to make sense. The effect of gravity will become stronger and stronger as secondForGravity is increased each frame.
It looks to me as if you should take it out completely and just multiply by deltaTime which represents the fraction of a second that passed since the previous frame (i.e. 1 * deltaTime should come out to 1 per second apart from slight floating point imprecision).
I found a solution by adding velocity to my current position and using this code in the Move() function:
rb.MovePosition(velocity + new Vector2(transform.position.x, transform.position.y));
Instead of this code:
rb.AddForce(velocity, ForceMode2D.Force);
Now whatever frame rate my game is running at the character is moving at a constant pace. I am still usuing the

Movement is dependent to frame-rate. How can i make it independent from frame-rate

i am pretty new to coding. till now i searched lots of things yet i still couldn't solve my problem. I am trying to make a gameObject follow a line/graph. i tried to give him a negative-Y velocity and adding small numbers(something like; update{mybody.velocity += 0.005}) each update to make it move. but i encountered a problem which is at low frame-rate my object is taking a super wide path and at higher frame-rate it take super tight path. how can i make my movement independent.
private float curve = 0;
private float curvemax = 2.3f;
[SerializeField]
private float curveupdate = 0.05f;
if (tracking.found && !hareketeBaşlandı)
{
curve = -(curvemax);
triggered1 = true;
hareketeBaşlandı = true;
print(curve);
}
if (transform.position.y != y1-curvemax && tracking.found)
{
curve += curveupdate;
print(curve+"Curving");
}
if (curve >= (curvemax))
{
curve = 0;
y2 = transform.position.y;
transform.position = new Vector3(transform.position.x, y1, transform.position.z);
tracking.found = false;
tracking.shouldsearch = false;
StartCoroutine("trackCD");
print("track off");
myBody.velocity = new Vector2(myBody.velocity.x, curve);
hareketeBaşlandı = false;
}
Note that using DateTime.Now and TimeSpan calculations as in this answer are quite expensive ... especially if you use it every frame just to calculate a delta in seconds.
This is actually exactly what Unity already provides in Time.deltaTime the time in seconds passed since last few was rendered .. so why calculate it complicated if we already know the value ;)
curve += curveupdate * Time.deltaTime;
In simple words multiplication by Time.deltaTime converts any value from "value per frame" into a frame-rate independent "value per second"
Instead of thinking about "rate of change," you must think about "rate of change per unit of time".
For example, you seem to be updating curve based on curveupdate = 0.05f;, which has a rate of change of 0.05f. You need to be thinking about how much rate of change per second. Assuming you currently get 0.05f change per frame, and let's say 10 frames per second, that means your rate of change per second is 0.5f (ten times higher) per second.
You then apply this amount multiplied by the number of seconds elapsed. Here's how to do it.
First when you kick off the animation, you need to remember when it started:
var lastUpdateTime = DateTime.Now;
Then change this:
curve += curveupdate;
To this:
DateTime currentTime = DateTime.Now;
float secondsElapsed = (float)(currentTime - lastUpdateTime).TotalMilliseconds / 1000F;
curve += (curveupdate * secondsElaped);
lastUpdateTime = currentTime;
This way, the amount of change scales depending on how much time has passed. If no time has passed, it will scale all the way down to 0, and if hours have passed, it will end up very very large. To an end user, the rate of change should seem consistent over time as a result.

Smooth, Fast Coroutines?

So I have a bunch of Coroutines running/working fine in my game.
However, one of them is for a power meter, and here's the issue...
You press the button, the power meter uses the coroutine to start filling up the power meter. (represented by the width of a red panel)
The goal is to make the meter fill up fast enough, as to where you can't just get "full power" every time. However, it also has to be smooth, and look nice.
The problem I'm facing is that my coroutine is maxed out on speed, and can't go any faster, and the meter is moving too slowly. So to "speed up" the meter, I have to use larger width increasing increments on the red panel.
It works, but, this causes 2 problems.
It doesn't look smooth. (It looks choppy and jittery)
It misses a whole bunch of values/possibilities. (e.g. The bar has to increase by a unit of "50" to make it fast enough to be difficult. But that's dumb, because that makes only 12 possibilities when stopping the meter. And there could be up to 600!)
Has anyone faced this before? If so, what's the best approach to making a fast, but smooth power meter, that can still hit a full range of value possibilities?
Thanks,
Ben
Here is my Code:
public static IEnumerator StartPitchMeter(Player.Guy guy, float duration)
{
var dur = 0.01f;
do
{
yield return new WaitForSeconds(dur);
PlayerControls.PitchMeter += 50f;
if (PlayerControls.PitchMeter > 600) PlayerControls.PitchMeter = 0f;
PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, 50);
} while (!PlayerControls.stopPitch);
}
If you're using a coroutine to update something for graphical purposes, you want to update on every available render frame (same as how often Update methods are called). So, instead of waiting for a set amount of time to pass, use yield return null and then move the meter according to Time.deltaTime, the time elapsed since the last frame in seconds. In this case, you can multiply Time.deltaTime by how many units per second you would like the meter to fill:
public static IEnumerator StartPitchMeter(Player.Guy guy, float duration)
{
do
{
yield return null;
// Fill 50 units per second.
float fillThisFrame = Time.deltaTime * 50f;
PlayerControls.PitchMeter += fillThisFrame;
if (PlayerControls.PitchMeter > 600) PlayerControls.PitchMeter = 0f;
PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, 50);
// Not sure what the 50 is doing here so it might be this instead:
// PlayerControls.pitchMeter.sizeDelta = new Vector2(PlayerControls.PitchMeter, fillThisFrame);
} while (!PlayerControls.stopPitch);
}

Change movement speed in Vector.Lerp Unity 5.6

I am using Vector3.Lerp in unity game to simply move a gameobject from one position to other smoothly. Below is my code:
public class playermovement : MonoBehaviour {
public float timeTakenDuringLerp = 2f;
private bool _isLerping;
private Vector3 _startPosition;
private Vector3 _endPosition;
private float _timeStartedLerping;
void StartLerping(int i)
{
_isLerping = true;
_timeStartedLerping = Time.time ; // adding 1 to time.time here makes it wait for 1 sec before starting
//We set the start position to the current position, and the finish to 10 spaces in the 'forward' direction
_startPosition = transform.position;
_endPosition = new Vector3(transform.position.x + i,transform.position.y,transform.position.z);
}
void Update()
{
//When the user hits the spacebar, we start lerping
if(Input.GetKey(KeyCode.Space))
{
int i = 65;
StartLerping(i);
}
}
//We do the actual interpolation in FixedUpdate(), since we're dealing with a rigidbody
void FixedUpdate()
{
if(_isLerping)
{
//We want percentage = 0.0 when Time.time = _timeStartedLerping
//and percentage = 1.0 when Time.time = _timeStartedLerping + timeTakenDuringLerp
//In other words, we want to know what percentage of "timeTakenDuringLerp" the value
//"Time.time - _timeStartedLerping" is.
float timeSinceStarted = Time.time - _timeStartedLerping;
float percentageComplete = timeSinceStarted / timeTakenDuringLerp;
//Perform the actual lerping. Notice that the first two parameters will always be the same
//throughout a single lerp-processs (ie. they won't change until we hit the space-bar again
//to start another lerp)
transform.position = Vector3.Lerp (_startPosition, _endPosition, percentageComplete);
//When we've completed the lerp, we set _isLerping to false
if(percentageComplete >= 1.0f)
{
_isLerping = false;
}
}
}
}
The code works fine and the gameobject moves smoothly between two points. But it takes about 1 sec to reach destination. I want to make it move faster. I have tried decreasing the value of float timeTakenDuringLerp but the speed isn't affected. I have followed this tutorial and the explanation there also says to change timeTakenDuringLerp variable in order to change speed but its not working here.
Any Suggestions please?
H℮y, thanks for linking to my blog!
Decreasing timeTakenDuringLerp is the correct solution. That reduces the time it takes for the object to move from start to finish, which is another way of saying "it increases the speed".
If there is a specific speed you want the object to move at, you'll need to make timeTakenDuringLerp a variable rather than a constant, and set it to distance/speed. Or better yet, don't use Lerp at all, and instead set the object's velocity and let Unity's physics engine take care of it.
Multiplying percentageComplete by a constant, as suggested by #Thalthanas, is incorrect. That causes the lerping updates to continue occurring after the lerping has completed. It also makes the code hard to understand because timeTakenDuringLerp is no longer the time taken during the lerp.
I've double-checked with my code and it does indeed work, so the problem you are experiencing must be elsewhere. Or maybe you accidentally increased the time, which would decrease the speed?
The solution is to
multiply percentageComplete value with a speed value like,
transform.position = Vector3.Lerp (_startPosition, _endPosition, percentageComplete*speed);
So when you increase speed, it will go faster.

When using transform.Translate in Unity3D outside of an update loop, how can I perform collision detection?

So I'm writing a small multiplayer game. For this, I'm using basic cube colliders for the players. At the moment, set to isKinematic.
Each player is moved from the main loop, using an offset timer to account for lag/latency. This works fine. However, with this method, collisions are a problem.
I do NOT want to use Force if I can avoid it - a previous attempt proved that to be a big issue. transform.Translate() works best or so it seems, but it does not account for anything hitting meshes. isKinematic disables OnCollisionEnter. I would love to use rigidbody.velocity, but it needs to account for rotation, not four-way movement.
This is my tick code at the moment:
public void FixedStep(double T)
{
if (Last == 0.0) Last = T;
double Offset = System.Math.Min(T - Last, 5000);
for (double X = 0.0; X < Offset; X++)
{
transform.Translate(Vector3.up * Speed * -mInput.y * Time.deltaTime);
//mRigidBody.velocity = (Vector3.forward * Speed * mInput.y);
transform.Rotate(Vector3.forward * TurnSpeed * mInput.x * Time.deltaTime);
}
Last = T;
}
I remember there used to be tutorials that combined forward movement and rotation for rigidbody.velocity, but for the life of me, I can't find them. Does anyone have advice on collisions with this method?
Okay, I feel stupid. It's been long enough since I've done a ...somewhat conventional game that I completely forgot the proper method of using rigidbody.velocity.
mRigidBody.velocity = transform.forward * Speed * -mInput.y;

Categories