Update won't detect my jump input correctly - c#

I'm following some guides and from what I've seen using the update function is a good thing for the jump action, but when I do it the update sends me to a different location.
Jump Related Function:
void Update(){
if(dead == false){
if(Input.GetKeyDown(KeyCode.Space)){
if(OnGround == true){
r.velocity = new Vector2(r.velocity.x, jumpForce * time.deltaTime);
}
}
}
}
From an internet search I found the following, but they didnt help me so much option1 and option2
Mostly it moves me to a different location or jumps me too much high or too much low, never a good proper jump, I really have no idea what to do, any ideas?

You should not be using Time.deltaTime when you're assigning velocities directly. The value of Time.deltaTime depends on the frame rate, which is expected to jitter, which gets inherited into your jump so that you get a quasi random velocity and jump height.
if(!dead && Input.GetKeyDown(KeyCode.Space) && OnGround){
r.velocity = new Vector2(r.velocity.x, jumpForce);
}
typically the AddForce function is used for jumps, which is technically the "correct" way to go about it, but I know plenty of people that prefer your method. In any case I'll just put it here for reference.
if(!dead && Input.GetKeyDown(KeyCode.Space) && OnGround){
r.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}

While your code is correct, I suggest using Rigidbody.AddForce(Vector3 force); or in case you are using rigidbody 2d Rigidbody2D.AddForce(Vector2 force); instead of using r.velocity=.... To make it easier to debug - you can create a public variable for the force and tweak it while in play mode until you get satisfactory results.

Related

How can I balance a cube with a rigidbody in unity

I am trying to have a cube rotate itself back to its orginal rotaion whenever the palyer bumbs in the cube but I don't want it to snap back instantly, I am trying to let it balance itself out and make it look jiggly but I do not how how to make it. I tried differnt ways but none of them work. This is my last try and I know that it is just checking one axis and so but I am clueless so can anybody tell me how to do this.
if(transform.rotation.z > 10)
{
transform.rotation = Quaternion.Slerp(transform.rotation, StartRot, TimeCount);
TimeCount = TimeCount + Time.deltaTime;
print("Go");
}
I would suggest looking at this first, and there are plenty of tutorials like this though that one is about a punching bag the concept is similer.

Background jitter with v-sync off in standalone build (high fps/300+ fps)

So the last 2 months I had been reworking my PlayerController to be rigidbody based for the sake of having more interactions with rigidbodies i.e. pushing objects. This went all pretty well, until I started testing my game in a standalone build. I immediately noticed strange jitter/stutter in the background (the player runs smooth) when v-sync is turned off (with v-sync is turned off my computer runs the game at 300fps+). At first I thought it had something to do with Cinemachine, I'm using CinemachineFreeLook, but to be honest as of now I'm unsure if Cinemachine is what's causing the jitter/stutter. Something worth noting is that the jitter/stutter is not constant, while the fps seems constant the jitter/stutter might go away for like 20 seconds and come back after. I have obviously done alot of research the past week and have been reading plenty of posts about FixedUpdate vs. Update, but unfortunately without any luck.
I tried to add as much information as possible to this post to give a good understanding of my project, but first the stuff I already tried;
Changing the Fixed Timestep from 0,02 to 0,01. (This kind of works,
but I would like to prevent changing the Fixed Timestep)
Turning on interpolate/extrapolate. (Now there is jitter with both
v-sync turned on and off)
Changing the CinemachineBrain Update Method to FixedUpdate/LateUpdate
instead of SmartUpdate.
Deconstructing the scene and removing some heavy on performance stuff
like Volumetric Lighting and Planar Reflections.
Creating a really barebones PlayerController with only the code to
move the player.
Removing the library folder of my project. (Read this somewhere
online, but no luck)
Turning of my Xbox One controller, to make sure there is only one
input in use.
Swithed the building from Windowed Fullscreen to Exclusive
Fullscreen.
Turned off one monitor while testing.
Move all my code to FixedUpdate.
Added these 3 scripts and changed the Script Execution Order
(Couldn't get this to work)
Put the input logic in FixedUpdate.
Below you can see both my movement scripts, one is part of my actual PlayerController, while the other was the one I wrote for the barebones Player.
void FixedUpdate() {
_isGrounded = Physics.CheckSphere(_groundChecker.position, GroundDistance, Ground, QueryTriggerInteraction.Ignore);
_inputs = Vector3.zero;
_inputs.x = Input.GetAxis("Horizontal");
_inputs.z = Input.GetAxis("Vertical");
_inputs.Normalize();
if (_inputs != Vector3.zero)
transform.forward = _inputs;
_body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
}
This is the script I wrote for the barebones player controller.
void FixedUpdate() {
if (pushControllerScr._pushBlocker) {
input = Vector3.zero;
} else {
input = new Vector3(InputManager.MainHorizontal(), 0, InputManager.MainVertical());
}
RunAxis();
inputDir = input.normalized;
inputDir.Normalize();
// Makes the player able to move, while not landing or being dead
if (!landState && !climbManagerScr.isClimbing) {
Move(inputDir, running);
}
}
void Move(Vector3 inputDir, bool running) {
if (inputDir != Vector3.zero) {
float targetRotation = Mathf.Atan2(inputDir.x, inputDir.z) * Mathf.Rad2Deg + cameraT.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));
}
float targetSpeed = ((running) ? runSpeed : movementSpeed) * inputDir.magnitude;
stateInfoBaseLayer = _anim.GetCurrentAnimatorStateInfo(0);
if (stateInfoBaseLayer.IsTag("Climbing") || stateInfoBaseLayer.IsTag("Standing")) {
currentSpeed = 0f;
} else {
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
}
if (stateInfoBaseLayer.IsTag("AirIdle") && currentSpeed > walkSpeed) {
currentSpeed = walkSpeed;
}
velocity = transform.forward * currentSpeed + Vector3.up * _rb.velocity.y;
if (_capsuleCol.enabled) {
_rb.MovePosition(_rb.position + velocity * Time.deltaTime);
}
}
This is what I actually use in my PlayerController Script
Below you can see some footage of the jitter/stutter. It was quite hard to capture it, since using any recording software like OBS dropped the fps in my game to a point where the jitter/stutter was disappearing. Sorry for the phone recording, but this was honestly the only way.
Footage of my game showcasing the jitter/stutter especially noticable around the yellow ship.
And finally here's an album with some relevant settings in the inspector. Imgur Album
Looking at your recording, it looks as if the player is smooth and everything else.
From my experience 99% of the time means the jitter comes from the camera not being synced up correctly to the player.
It seems you have done the right things, and usually combining the following should work fine:
CinemachineBrain should update on FixedUpdate
Use interpolate/exrapolate on your player's Rigidbody (we chose extrapolate)
Apply forces/changes to physics objects solely in FixedUpdate
If you do all 3 together, this should work smoothly regardless of vsync, frame rate, fixed delta time, etc
Obviously your specific project might have something else that's messing it up; but I've seen this issue countless times and usually these combined steps should solve it.

Moving a RigidBody2D a specific amount of units

In my 2D side-scrolling game I move my character using the built-in physics engine by manipulating the rigidbody.velocity.
I would like to add some sort of dodge (roll) ability, where the character moves 3 units in its direction.
Here is the code I used:
void FixedUpdate() {
if (Input.GetKeyDown(KeyCode.A) ) {
Vector2 pos = rb.position;
pos.x -= 5;
rb.MovePosition (pos);
}
}
This method works but the character kind of jumps to the position rather than moving to it (Lerping?) and also doesn't detect collisions despite the body type being dynamic.
Then I tried this:
if (Input.GetKeyDown(KeyCode.A)) {
rb.AddForce(new Vector2(-50, 0));
}
I found the AddForce way isn't accurate at all.
Is there a proper way of doing this?
Maybe you could change the Transform.pos inside Vector2.Lerp to make it look smooth? (Sorry, not enough experience with 2D in unity.)
Just increase rigibody.velocity for a set time. Your chararter object could then play a fitting aniamtion. If The player should not be able to cancle midrole jsut block the controls for that time.

Unity 2D scripted friction equation

I am working on the friction for a square object for after it is done being pushed by the player. The block's movements are controlled purely through script using transform.Translate(velocity) each frame and only a boxcollider2D. I am speculating that because i am controlling the block's movements each frame manually is the reason i can't seem to get the boxcolliders2D's physics material 2D friction to work.
Basically, I am trying to recreate the built in physics similar to rigidbodies by using transform.translate, or use the built in physics if possible. So far, i've landed on something like this
newVelocity.x -= ( 1 / (newVelocity.x * newVelocity.x));
In an attempt to reduce the velocity.x each frame until it hits 0 and shorts out. Obviously, this falls apart when the velocity.x becomes a decimal number. I'm stumped on what i should be doing to achieve a friction similar to rigid bodies where it slows down a little at first and then much faster towards the end as it stops. Any and all help appreciated, thanks in advance!
You could compare the signs of the velocity before and after calculating the change in velocity, and set the velocity to zero when the sign changes, like so:
newVelocity.x -= ( 1 / (newVelocity.x * newVelocity.x));
if(Mathf.Sign(previousVelocity.x) != Mathf.Sign(newVelocity.x)) {
newVelocity.x = 0f;
}
One thing, though, is that normal friction is not calculated using the above equation, it's calculated as follows:
newVelocity.x -= frictionCoefficient*Time.fixedDeltaTime;
And with this, you wouldn't need to compare the velocity to the previous velocity as you can just say if the velocity is low, it's zero. You could still compare the previous velocity sign stuff if you wanted to though, but this is probably more efficient
if(newVelocity.x < 0.01f) {
newVelocty.x = 0f;
}

Unity 3D Move object over specific time on GetButtonDown

I've got an empty game object filled with all my player components, within it is a model which animates itself when the controls are pressed which are instantiated by GetButtonDown. Currently everything in the player game object moves instantly to the next point (basically teleports there with no transition). Is there a way I can get it all to move over say 1 second rather than going there instantly? Here's what happens on GetButtonDown
if (Input.GetButtonDown ("VerticalFwd"))
{
amountToMove.y = 1f;
transform.Translate (amountToMove);
}
I've tried transform.Translate (amountToMove * Time.deltaTime * randomint);
and all sorts of ways to use Time
however that doesn't seem to work even though it seems the most logical way. I'm guessing because the GetButtonDown only "runs" when it is pressed and has no update function to "time" the move every frame? Any ideas?
amountToMove is saved as a Vector3 aswell.
The first formula is wrong. The correct formula would be:
this.transform.position += (Distance/MoveTime) * time.deltatime
Try .Lerp, it runs as a coroutine interpolating a value over some amount of time Vector3.Lerp(Vector3 start, Vector3 end, float time)
See documentation here
This should give you a rough idea of whats going on
Vector3 Distance = End - Start;
// this will return the difference
this.transform.position += Distance/time.deltatime * Movetime
// this divides the Distance equal to the time.deltatime.. (Use Movetime to make the movement take more or less then 1 second
IE: If the Distance is 1x.1y.1z, and time.deltatime is .1 and Movetime is 1.... you get a movement of .1xyz per tick, taking 1 second to reach the end point
FYI: transform.Translate works as a fancy .position +=, for this purpose you can use them interchangeably
EDIT
Here are a few solutions
Easy ::
Vector3 amountToMove = new Vector3(0,1,0); // Vector3.up is short hand for (0,1,0) if you want to use that instead
if (Input.GetButtonDown ("VerticalFwd"))
{
transform.position = Vector3.Lerp(transform.position ,transform.position + amountToMove, 1);
}
Hard and probably unnecessary ::
Write a Coroutine that does a kind of Linear interpolation for your specific application See documentation here

Categories