I have a game where my player need to move forward without stopping, sometimes he stop moving at Z = 990 and if i move him on editor a little bit he start moving again.
EX: https://youtu.be/A0FB595AdHI
void FixedUpdate () {
if(forwardSpeed < maxSpeed)
{
forwardSpeed += Time.deltaTime * speedIncrementor;
}
rb.velocity = new Vector3(0, rb.velocity.y, forwardSpeed * Time.deltaTime);
if (forwardSpeed > maxSpeed)
{
forwardSpeed = maxSpeed;
}
}
Time.deltaTime is NOT the physics timestep.
Time.deltatime (duration of last frame) should only be used in once per frame calls e.g. Update() calls.
Time.fixedDeltaTime should only be used in FixedUpdate(), since it the sample time of the physics loop
If this does not fix the issue u can simply use the logic of restarting the terrain logic . That means it will start start running from the point your game object start moving
Related
I am trying to add a delay before the player can jump again if they fall from a height greater than for example 5.0f. Currently, there's no delay no matter what, which should not be the case.
// Player jumping
if (Input.GetButtonDown("Jump") && isGrounded && Time.time > canJump)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
if (!Physics.Raycast(transform.position, Vector3.down, out var hit)) return;
if (hit.distance > 5.0f)
{
canJump = Time.time + 1.0f; // Delay next jump
}
}
I have an empty game object called 'groundCheck' that sits directly below my player with a layer mask attached called 'Ground' which I use for my regular jumping and movement and all my terrain/objects have the 'Ground' layer. I tried to create an if statement so that if my player fell from at least 5.0f, they would have a very brief jump delay, but that didn't work and I'm now having issues with my raycast.
Currently it is my script for movement the player to the around the scene. How can i make it smoothly move?
void FixedUpdate()
{
bool running = Input.GetKey(KeyCode.LeftShift);
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
bool isWalking = Mathf.Abs(h) + Mathf.Abs(v) > 0;
movement = ((running) ? runSpeed : walkSpeed) * new Vector3(h, 0.0f, v).normalized;
if (isWalking)
{
transform.position += movement * Time.fixedDeltaTime;
transform.LookAt(transform.position + movement);
}
}
Create a velocity vector:
Vector3 velocity = Vector3.zero;
Add your movement vector to velocity:
velocity += movement;
Add velocity to the actual position:
transform.position += velocity;
Smooth out velocity by reducing it over time:
velocity *= 0.975f;
The FixedUpdate() function is ran every fixed interval as defined by Time.fixedDeltaTime (which you can either set via the TimeManager (Fixed Timestep) or at runtime by directly setting Time.fixedDeltaTime to a new value.
Because you are moving the character position and rotation on a fixed interval, depending on framerate the character will either move a lot with a lower framerate or only move every few frames with a higher framerate.
For example with a fixed timescale of 0.02 seconds and the game running at a framerate of 30 frames per second (aka rendering every 0.033 seconds) your game will be doing this:
- [Time: 0.020s] Character position += 0.02
- [Time: 0.033s] Render frame with character at position 0.02
- [Time: 0.040s] Character position += 0.02
- [Time: 0.060s] Character position += 0.02
- [Time: 0.066s] Render frame with character at position 0.06
- [Time: 0.080s] Character position += 0.02
- [Time: 0.099s] Render frame with character at position 0.08
- [Time: 0.100s] Character position += 0.02
- [Time: 0.120s] Character position += 0.02
- [Time: 0.133s] Render frame with character at position 0.12
So in this example you can see how the character would jump forward at different amounts per frame and you can't guarantee what framerate the game will be running at either so it could end up being worse.
There are a few ways to make your character move smoothly though.
Put your code in an Update() loop instead of a FixedUpdate() loop, this will move the position of the character each rendered frame. Along with this you can multiply the movement speed by Time.deltaTime which is the time since the previous frame was rendered (aka time since Update() was last ran and the character was moved)
Use Vector3.Lerp(..)/Quaterion.Lerp(..) or Vector3.MoveTowards(..)/Quaternion.RotateToward(..) using a time/step value multiplied by Time.deltaTime to interpolate the character movement keeping it moving smoothly in relation to the game framerate.
If your character has a rigidbody component then you can simply just set the rigidbody interpolation to interpolate then move your character by calling:
characterRigidbody.MovePosition(wantedPosition);
characterRigidbody.MoveRotation(wantedRotation);
As a replacement to your existing transform movements (keeping your code inside of the FixedUpdate() loop)
But note that continuing to have your Input.* calls inside a FixedUpdate() is polling them more than needed so you might want to move them over into an Update() splitting the movement code and input listening code if you decide to do this. (I develop android games so maybe on PC this isn't worth worrying about as much, but probably still worth changing)
A direct code block answer to the question though could be to just try this, which is a combination of explanation 1 and 2:
// How long in seconds will it take the lerps to finish moving into position
public float lerpSmoothingTime = 0.1f;
private Vector3 targetPosition;
private Quaternion targetRotation;
void Update()
{
bool running = Input.GetKey(KeyCode.LeftShift);
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
bool isWalking = Mathf.Abs(h) + Mathf.Abs(v) > 0;
movement = ((running) ? runSpeed : walkSpeed) * new Vector3(h, 0.0f, v).normalized;
if (isWalking)
{
targetPosition += movement * Time.deltaTime;
targetRotation = Quaternion.LookRotation(targetPosition - transform.position);
}
// Always lerping as if we suddenly stopped the lerp as isWalking became false the stop would be sudden rather than smoothly moving into position/rotation
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime / lerpSmoothingTime);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime / lerpSmoothingTime);
}
If you want to read up in more detail about smoothly moving objects, learning about lerps or just want more examples then check out this guide on how to fix movement stutter in Unity.
First of all you need to put your code into Update() method if u want it to execute each frame. FixedUpdate is called at fixed intervals depend on project settings (you can change it in Edit -> Project Settings -> Time -> Fixed Timestep). Usualy FixedUpdate() is used for physics related stuff.
Moving it in FixedUpdate should be very smooth. Sure, Vector3.Lerp could help with your movement, but why in the first place isn't it smooth?
I can only guess that you have your Camera in a normal Update Script or that there is some Rigidbody interpolation. All that you need to know about smooth motion is explained here:
http://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8
You can use Vector3.Lerp(...).
Try this code:
float smoothTime = 0.125f;
Vector3 newPos;
...
void FixedUpdate()
{
bool running = Input.GetKey(KeyCode.LeftShift);
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
movement = ((running) ? runSpeed : walkSpeed) * new Vector3(h, 0.0f, v).normalized;
//Set the new position
if(movement.magnitude > 0)
newPos = transform.position + movement;
// Use Vector3.Lerp(...)
transform.position = Vector3.Lerp(transform.position, newPos, smoothTime);
transform.LookAt(transform.position);
}
I hope it helps you.
I'm Making a movement script with vector 2 and Rigidbody.velocity. I want my gameobject to move until a certain x pos and then return to the initial pos, all of that while moving continiously. I achieved the first part, it goes backwards when it reaches a certain point but then the backwards movement never stops:
public float spawnPos;
public float currentPos;
public float constantSpeed = 3;
public float speed = 0;
KeyInput scriptBeholderKI;
Rigidbody2D squadRigidBody;
//Comprovation of spawnposition and KeyInput
//Script adquisition
void Start () {
spawnPos = transform.position.x;
scriptBeholderKI = gameObject.GetComponent <KeyInput> ();
squadRigidBody = gameObject.GetComponent <Rigidbody2D> ();
}
void FixedUpdate () {
//Movement
squadRigidBody.velocity = new Vector2 (constantSpeed + speed , 0);
//key inputs
if (Input.GetKeyDown (scriptBeholderKI.forward)) {
StopAllCoroutines ();
StartCoroutine (RightMovement(0f));
}
if (Input.GetKeyDown (scriptBeholderKI.backwards)) {
StopAllCoroutines ();
StartCoroutine (LeftMovement (0f));
}
}
//Speed values (Right, Left)
IEnumerator RightMovement (float Rloop) {
while (transform.position.x < constantSpeed * Time.time + spawnPos + 14) {
speed = 10f;
yield return new WaitForSeconds (Rloop);
}
if (transform.position.x> constantSpeed * Time.time + spawnPos + 14) {
StopAllCoroutines ();
StartCoroutine (LeftMovement (0f));
}
}
IEnumerator LeftMovement (float Lloop) {
while (transform.position.x > constantSpeed * Time.time + spawnPos) {
speed = -7f;
yield return new WaitForSeconds (Lloop);
}
}
If you also see anything that could be improved pls make me note c:
edit:
when I press the forward input my gameobject moves until it reaches a point, when I press the bacwards one it moves to the left nonstop.
also the thing is that I want my target to move at the constantspeed of the gameobject, thats why I use Time.time. the movements I do with the inputs are more properly said accelerations. I want my target to be always at the same relative distance from the gameobject, since the game starts. At least the maxium reach to the right is the one I want...
And I also tried to remove the stop all coroutines block and nothing, I but my intention was to be able to cancel the movement whenever I want (I removed the one in the RightMovement coroutine, however. It wasn't neecesary after all)
one last thing: I changed "FixedUpdate" for "Update" because it gave me problems with my inputs response, I don't know if it's relevent but just in case.
I think you are mistaking the Time.time variable. Just like yes mentions in his comment
Time.time is the time in seconds since the start of the game.
This means, as time moves by, so will your target, which will slowly but surely move away.
Instead of Time.time you could however use Time.deltaTime
Time.deltaTime is the time in seconds it took to complete the last frame
This is most often used for movement.
When you multiply with Time.deltaTime you essentially express: I want to move this object 10 meters per second instead of 10 meters per frame, if the multiplication is 10.
Unity docs: Time.deltaTime
I'm currently working on a simple baseball game. What I'm trying to do is have the player be able to swing the bat backwards to "charge up" power, so to speak, and then when a button is released he will swing the bat forward at a speed equal to the amount of power stored up.
This is all well and good, but my problem is I need to stop the motion of the bat when he reach a certain point on the y-axis, and I'm a bit unsure how to go about doing this as I cannot just tell it to stop rotating after a set time as the bat won't reach the front point at the same time every time due to the difference in speed each swing might have.
What I'm trying to do basically is something like if(reached 266 on the y-axis stop rotating), but I'm unsure of how to do this.
Anyway here is the code I've written so far:
public int rotateSpeed = 50;
public float AmountOfPowerChargedUp = 0;
void Update()
{
if (Input.GetMouseButton(0))
{
AmountOfPowerChargedUp += 5f;
transform.Rotate(Vector3.up * rotateSpeed * Time.deltaTime);
Debug.Log(AmountOfPowerChargedUp);
}
if (!Input.GetMouseButton (0))
{
transform.Rotate(Vector3.down * AmountOfPowerChargedUp * Time.deltaTime);
}
}
private void OnGUI()
{
GUI.Label (new Rect (50, 15, 250, 25), "AmountOfPowerChargedUp: " + AmountOfPowerChargedUp);
}
if your rotating a certain amount of degrees, you should use a Slerp or RotateTowards
Vector3 targetDir = (target.position - transform.position).normalized;
// The step size is equal to speed times frame time.
float step = speed * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(transform.up, targetDir, step, 0.0);
transform.rotation = Quaternion.LookRotation(newDir)
I made sprite and applied rigidbody 2d component, it's working fine as it should, now i wrote this piece of code but, when i start playing the game it working for some period of time but after that, gravity seems be null, means my rigidbody does not come down when i leave the keys
// Update is called once per frame
void Update () {
if (Input.GetKey (KeyCode.LeftArrow)) {
posX--;
} else if (Input.GetKey (KeyCode.RightArrow)) {
posX++;
}
if (Input.GetKey (KeyCode.UpArrow)) {
posY++;
} else if (Input.GetKey (KeyCode.DownArrow)) {
posY--;
}
angle -= Input.GetAxis ("Horizontal");
angle = Mathf.Clamp (angle, -10, 10);
}
void FixedUpdate()
{
transform.eulerAngles = new Vector3 (0,0,angle);
transform.position = new Vector2 (posX * Time.deltaTime, posY * Time.deltaTime);
}
}
what i want to do is move the helicopter left right up and down(which user can control) but when user is not interacting, i want gravity to work as default and helicopter will come down due to gravity, how to achieve that?
You are overwriting the position on every frame, so it doesn't meter what Unity calculates on its physics, you overwrite when you do this:
transform.position = new Vector2 (posX * Time.deltaTime, posY * Time.deltaTime);
I don't know what you want to achieve, but maybe it will work if after this you re-apply a gravity force with traforme.AddForce(), using the object's mass and the gravity acceleration constant.
You should use AddForce instead of Changing x and Y axes.
You can see the example here,
AddFource Example