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.
Related
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
I have a game in a 3D space, and rigidbody comp. to a player. I have implemented a jump mechanic that is not working at intended, with this code:
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public bool Travel;
public Rigidbody rb;
public Transform tf;
public bool Grounded;
public float speed;
int OnRail = 2;
void Update ()
{
float speed = 1f * Time.deltaTime;
if (Input.GetKeyDown("d") && OnRail < 3)
{
tf.Translate(5.4f, 0f, 0f);
OnRail++;
}
else if (Input.GetKeyDown("a") && OnRail > 1)
{
tf.Translate(-5.4f, 0f, 0f);
OnRail--;
}
}
void FixedUpdate ()
{
if (Travel)
{
rb.velocity = new Vector3(0, 0, speed * Time.deltaTime);
}
if (Input.GetKeyDown("space") && Grounded)
{
Grounded = false;
rb.AddForce(new Vector3(0, 500000f * Time.deltaTime, 0));
}
if ((tf.position.y == 2f || tf.position.y == 10f) && rb.velocity.y == 0 && !Grounded)
{
Grounded = true;
}
}
}
The player is supposed to jump into the air, but only jumps almost no distance. The 2 and 10 Y positions are preset floors (I really don't need these 2 Y-coordinates. unless someone has a substitution for floor detection).
This is because GetKeyDown only occurs for one frame, meaning you are only applying a force upwards for that single frame. Additionally, Time.deltaTime is the amount of time it took to complete the last frame (a very small value), meaning you are applying a very small force upward. If you only want a single force applied on spacebar, there is no need to use Time.deltaTime here. Just do:
rb.AddForce(Vector3.up * 100f); // or some other reasonable multipliier
Hi for those that land on this looking for more information on their rigidbodies not behaving the way that they expected, I extracted bit of relevant information from Unity ForceMode's. Happy Developing.
//Here, switching modes depend on button presses in the Game mode
switch (m_ModeSwitching)
{
//This is the starting mode which resets the GameObject
case ModeSwitching.Start:
//This resets the GameObject and Rigidbody to their starting positions
transform.position = m_StartPos;
m_Rigidbody.transform.position = m_StartForce;
//This resets the velocity of the Rigidbody
m_Rigidbody.velocity = new Vector3(0f, 0f, 0f);
break;
//These are the modes ForceMode can force on a Rigidbody
//This is Acceleration mode
case ModeSwitching.Acceleration:
//The function converts the text fields into floats and updates the Rigidbody’s force
MakeCustomForce();
//Use Acceleration as the force on the Rigidbody
m_Rigidbody.AddForce(m_NewForce, ForceMode.Acceleration);
break;
//This is Force Mode, using a continuous force on the Rigidbody considering its mass
case ModeSwitching.Force:
//Converts the text fields into floats and updates the force applied to the Rigidbody
MakeCustomForce();
//Use Force as the force on GameObject’s Rigidbody
m_Rigidbody.AddForce(m_NewForce, ForceMode.Force);
break;
//This is Impulse Mode, which involves using the Rigidbody’s mass to apply an instant impulse force.
case ModeSwitching.Impulse:
//The function converts the text fields into floats and updates the force applied to the Rigidbody
MakeCustomForce();
//Use Impulse as the force on GameObject
m_Rigidbody.AddForce(m_NewForce, ForceMode.Impulse);
break;
//This is VelocityChange which involves ignoring the mass of the GameObject and impacting it with a sudden speed change in a direction
case ModeSwitching.VelocityChange:
//Converts the text fields into floats and updates the force applied to the Rigidbody
MakeCustomForce();
//Make a Velocity change on the Rigidbody
m_Rigidbody.AddForce(m_NewForce, ForceMode.VelocityChange);
break;
}
I am trying to move object in unity along the x axis and in the direction of swipe while remaining inside of the screen. It should move as much as distance as the user swipes (much like Ketchapp's rush hero).
Here is my code so far in update:
if (Input.touchCount > 0)
{
if (Input.GetTouch (0).phase == TouchPhase.Began) // Get initial Position
{
playerPos = transform.position;
//playerPos = Camera.main.ScreenToWorldPoint (playerPos);
touchPos = Input.GetTouch (0).position;
touchPos = Camera.main.ScreenToWorldPoint (touchPos);
distance = 0f;
}
else if (Input.GetTouch (0).phase == TouchPhase.Moved)
{
Vector3 pos = Input.GetTouch (0).position;
pos = Camera.main.ScreenToWorldPoint (pos);
distance = pos.x - touchPos.x;
transform.position = new Vector3 (transform.position.x + distance, transform.position.y, transform.position.z);
}
}
This doesn't work properly and I am a rookie in unity. Any help would be appreciated.
The problem here is that TouchPhase.Moved happens more than once (every frame during the gesture until it ends). But your code assumes that it is only called once.
You have two options here.
Option 1: Reset the starting point
Add touchPos = Input.GetTouch (0).position; as the last line of your TouchPhase.Moved block. This will effectively indicate "this distance was already handled, next frame treat the move as a new move and this is where to start from."
Option 2: Use absolute offsets
Change the last line of your TouchPhase.Moved block to transform.position = new Vector3 (distance, transform.position.y, transform.position.z);. This will treat every frame as if every move is treated as an offset from the original starting point and set the X value accordingly. However, this assumes that the object starts at 0 and will always start at 0 along the X-axis.
Depending on your use-case you may prefer one method over the other.
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 making a 2D platformer and I followed a tutorial to build my character. This character works fine except that when jumping, it doesn't allow for changing direction midair. How can I add to this to make my character able to change direction mid-jump?
The code used for the basic movement is below:
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
float rotation = Input.GetAxis("Horizontal");
if(controller.isGrounded)
{
moveDirection.Set(rotation, 0, 0);
moveDirection = transform.TransformDirection(moveDirection);
//running code
if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held
{ running = true; }
else
{ running = false; }
moveDirection *= running ? runningSpeed : walkingSpeed; //set speed
//jump code
if(Input.GetButtonDown("Jump"))
{
jump();
}
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
EDIT: Forgot to include the code for jump(), that's probably kind of important...
void jump()
{
moveDirection.y=jumpHeight;
transform.parent=null;
}
You are updating the moveDirection vector only when the character is grounded:
if(controller.isGrounded)
when player jumps isGrounded is set to false, so moveDirection won't be updated (except for gravity).
I suppose you don't want to affect the velocity of the character while is jumping (unless it is supposed to fly or walk in the air). I guess you want to change its orientation while it's jumping, so you can directly modify transform making it rotate accordingly to your input.
Something like:
else
{
float amountOfRotation = Input.GetAxis("...") * rotationScaleFactor;
transform.RotateAround(transform.position, transform.up, Time.deltaTime * amountOfRotation);
}
EDIT
I've never used it but I think CharacterController is designed for being moved only when the object is grounded. So if you want to move it while it's on the air, don't use the Move method but edit directly the transform of your GameObject:
else
{
float additionalForwardSpeed = Input.GetAxis("...") * speedScaleFactor;
transform.Translate(transform.forward * Time.deltaTime * additionalForwardSpeed ); //translate
}
the code above should increase the speed of your object in local forward direction.