I'm learning Unity, and I'm doing a character move, but the animation of the jump has a delay for the character to literally jump, a 0.30s until it picks up, how do I add this delay in the code?
Like, I thought of doing somehow that when you hit "Space" release the animation, count 0.20s and make the jump. it's viable? How can I do this?
In short, the character jumps before the animation.
Animation Video:
https://imgur.com/a/LgzkSKi
public class PlayerController : MonoBehaviour {
public float moveSpeed;
public float jumpForce;
public CharacterController controller;
private Vector3 moveDirection;
public float gravityScale;
public Animator animator;
void Start() {
controller = GetComponent<CharacterController>();
}
void Update() {
float yStore = moveDirection.y;
moveDirection = (transform.forward * Input.GetAxis("Vertical")) + (transform.right * Input.GetAxis("Horizontal"));
moveDirection = moveDirection.normalized * moveSpeed;
moveDirection.y = yStore;
jump();
controller.Move(moveDirection * Time.deltaTime);
animator.SetFloat("Speed", (Mathf.Abs(Input.GetAxis("Vertical"))));
}
void jump() {
if (controller.isGrounded) {
moveDirection.y = 0f;
if (Input.GetButtonDown("Jump")) {
moveDirection.y = jumpForce;
Debug.Log("jump");
}
}
moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale * Time.deltaTime);
animator.SetBool("isGrounded", controller.isGrounded);
}
}
In your jump() function don't apply the jump force. Instead, set the next time the character is supposed to jump.
float nextJumpTime;
bool todoJump;
void jump() {
if (!todoJump && Input.GetButtonDown("Jump")) {
// Remember we have to jump and when
nextJumpTime = Time.time + 0.2f;
todoJump = true;
}
// Execute the jump
if (todoJump && Time.time >= nextJumpTime) {
todoJump = false;
moveDirection.y = jumpForce;
}
}
Either that or read on coroutines. Start a coroutine on input, yield return new WaitForSecond(0.2f); in the coroutine and then execute the jump.
To what One Man Mokey Squad suggest I think you should also consider to get a new jump animation or trim the current animation.
I think it's not a great idea to create a custom code for that broken jump animation because you will not be able to reuse your script.
Related
Like the title says when i walk into a wall i start to vibrate. It doesn't affect gameplay just graphics i believe. The game is a 2D platformer using rigidbody 2D. I am new to game dev so what you fixed could you please tell me how you fix it. Thank you.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float MovementSpeed = 1;
public float JumpForce = 1;
private Rigidbody2D _rigidbody;
private float coyoteTime = 0.2f;
private float coyoteTimeCounter;
private float jumpBufferTime = 0.05f;
private float jumpBufferCounter;
[SerializeField] private Rigidbody2D rigidbody2D;
[SerializeField] private Transform groundCheck;
[SerializeField] private LayerMask groundLayer;
private bool isGrounded()
{
return Physics2D.OverlapCircle(groundCheck.position, 0.2f, groundLayer);
}
private void Start()
{
_rigidbody = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (isGrounded())
{
coyoteTimeCounter = coyoteTime;
}
else
{
coyoteTimeCounter -= Time.deltaTime;
}
if (Input.GetButtonDown("Jump"))
{
jumpBufferCounter = jumpBufferTime;
}
else
{
jumpBufferCounter -= Time.deltaTime;
}
var movement = Input.GetAxis("Horizontal");
transform.position += new Vector3(movement, 0, 0) * Time.deltaTime * MovementSpeed;
if (coyoteTimeCounter > 0f && jumpBufferCounter > 0f)
{
_rigidbody.velocity = new Vector2(_rigidbody.velocity.x, JumpForce);
jumpBufferCounter = 0f;
}
if (Input.GetButtonUp("Jump") && _rigidbody.velocity.y > 0f)
{
_rigidbody.velocity = new Vector2(_rigidbody.velocity.x, _rigidbody.velocity.y * 0.5f);
coyoteTimeCounter = 0f;
}
}
}
Sorry if the code is sort of sloppy. I am using multiple tutorials to make the movement perfect for me.
Ah! I have had this problem before.
The reason the vibration is happening, is because you are adding a force manually through rigidbody.velocity. The better (And more efficient) way to do it is through rigidbody.AddForce(). This should allow for the rigidbody to calculate physics much smoother.
The only issue that may arise is if you plan for the player to have a constant speed. If you AddForce(1000) with no other arguments, the character will start accelerating, instead of moving at a constant speed.
If you need the player to move at a constant speed, you can append a ForceMode to! I am not sure what one you would use, but that my idea. One example would be rigidbody.AddForce(1000, ForceMode.VelocityChange),
So I want to check if there is ground under my character
here is the code
public class move2d : MonoBehaviour
{
public float moveSpeed = 7f;
public float distanceGround;
public bool isGrounded = false;
// Start is called before the first frame update
void Start()
{
distanceGround = GetComponent<Collider2D>().bounds.extents.y;
}
// Update is called once per frame
void Update()
{
if (Physics2D.Raycast(transform.position, -Vector2.up, distanceGround + 0.1f))
{
}
else
{
isGrounded = true;
Jump();
}
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
transform.position += movement * Time.deltaTime * moveSpeed;
}
void Jump()
{
if (Input.GetButtonDown("Jump") )
{
gameObject.GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, 8f), ForceMode2D.Impulse);
}
}
}
but it doesn't work and I don't understand why it never enter else statement even there my character is on ground.
When dealing with rigidbody you shouldn't use transform.position not for getting and not for setting values. Rather use Rigidbody2D.position for getting and Rigidbody2D.MovePosition in FixedUpdate for setting.
Also shouldn't it be the other way round? You most probably are grounded if the raycast hits something .. not if it doesn't?
// Already reference these via the Inspector
[SerializeField] private RigidBody2D rigidBody2D;
[SerializeField] private Collider2D _collider2D;
public float moveSpeed = 7f;
public float distanceGround;
private Vector2 movement;
private bool jumped;
private void Awake ()
{
// Alternately get it once on runtime
if(! rigidBody2D) rigidBody2D = GetComponent<RigidBody2D>();
if(!_collider2D) _collider2D = GetComponent<Collider2D>();
}
private void Start()
{
// Micro performance improvement by calculating this only once ;)
distanceGround = _collider2D.bounds.extents.y + 0.1f;
}
// Get user Input every frame
private void Update()
{
// Directly check for the button
if (Input.GetButtonDown("Jump"))
{
// if button presed set the jump flag
jumped = true;
}
// store user input
movement = Vector3.right * Input.GetAxis("Horizontal");
}
// Apply physics in the physics update
private void FixedUpdate()
{
// If jump flag is set
if(jumped)
{
// You are grounded when you hit something, not the other way round
if (Physics2D.Raycast(rigidBody2D.position, Vector2.down, distanceGround))
{
rigidbody2D.AddForce(Vector2.up * 8f, ForceMode2D.Impulse);
}
// reset the flag
jumped = false;
}
// apply the normal movement without breaking the physics
rigidBody2D.MovePosition(rigidBody2D.position + movement * Time.deltaTime * moveSpeed);
}
I have a problem where the player moves in the direction but the animation of the charcter stays the same. So if i click "w" key the player runs forward the animation works. But when i click "s" for backwards the character does not rotate around to the direction it just moves/slides back with the character facing forward and no animation. Please help!!
public class Player : MonoBehaviour {
private Animator anim;
private CharacterController controller;
public float speed = 600.0f;
public float turnSpeed = 400.0f;
private Vector3 moveDirection = Vector3.zero;
public float gravity = 20.0f;
private Vector3 curLoc;
void Start () {
controller = GetComponent <CharacterController>();
anim = gameObject.GetComponentInChildren<Animator>();
}
void Update (){
if (Input.GetKey ("w")) {
anim.SetInteger ("AnimationPar", 1);
} else {
anim.SetInteger ("AnimationPar", 0);
}
if (Input.GetKey("s"))
{
anim.SetInteger("Condition", 1);
}
else
{
anim.SetInteger("Condition", 0);
}
if (controller.isGrounded){
moveDirection = transform.forward * Input.GetAxis("Vertical") * speed;
}
float turn = Input.GetAxis("Horizontal");
transform.Rotate(0, turn * turnSpeed * Time.deltaTime, 0);
controller.Move(moveDirection * Time.deltaTime);
moveDirection.y -= gravity * Time.deltaTime;
if (Input.GetKey(KeyCode.S))
{
}
}
}
You need to show Animator, how animations are playing and transitioning. Just open animator when game is playing and check if animation is playing where "Condition" parameter is passes. Check the animation transitions too. Also, I'd suggest you to change value "AnimationPar" to 0 when "s" is pressed.
if (Input.GetKey("s"))
{
anim.SetInteger ("AnimationPar", 0);
anim.SetInteger("Condition", 1);
}
Okay im trying to make my object (player) to jump everything is okay until i go against a wall and keep going against (still W is down) i cant jump wen im hitting a wall if i stop walking he will be enable to jump i tried making the walls on touch to make the player to have velocity = zero but it does not work,
i tried to add rigid body to the walls and freezing them in place, trying to make them kinematic does not work too .
I wish wen i go against walls and keep walking against them to be enable to jump.
If you know how i can do that please share thanks .
Here is the move script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveScript : MonoBehaviour {
private float speed;
private float jumpHight;
private float straffeSpeed;
private float fallMultiplier;
private Rigidbody rig;
private Collider coll;
// Use this for initialization
private void Awake()
{
rig = GetComponent<Rigidbody>();
coll = GetComponent<Collider>();
straffeSpeed = 1.5f;
fallMultiplier = 2.5f;
speed = 10f;
jumpHight = 4f;
}
void Start () {
GroundCheck();
}
// Update is called once per frame
void Update () {
Move();
GroundCheck();
BetterFall();
}
private void Move()
{
float hAxis = Input.GetAxis("Horizontal") * straffeSpeed;
float vAxis = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(hAxis, 0, vAxis) * speed * Time.deltaTime;
rig.MovePosition(transform.position + movement);
if (Input.GetKey(KeyCode.Space) && GroundCheck())
{
rig.velocity = Vector3.up * jumpHight;
}
}
private bool GroundCheck()
{
return Physics.Raycast(transform.position, -Vector3.up, coll.bounds.extents.y + 0.2f);
}
private void BetterFall()
{
if(rig.velocity.y < 0)
{
rig.velocity += Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
}
}
if (Input.GetKeyDown(KeyCode.Space) && GroundCheck())
{
rig.velocity = Vector3.up * jumpHight;
}
I don't think you are doing this quite right. Try this:
if (Input.GetKeyDown(KeyCode.Space) && GroundCheck())
{
rig.AddForce(Vector3.up * jumpHight, ForceMode.Impulse);
}
:-)
Hello guys!
I have a problem with my UNITY 5 code.
My character can jump but he jumps instantly and too fast.
It looks really weird.
I would greatly appreciate your feedback on my code!
using UnityEngine;
using System.Collections;
public class Gravity : MonoBehaviour {
private float inputDirection;
private float VerticalSpeed;
private float gravity = -2f;
private float speedmultiplier = 5f;
private bool jump;
private Vector3 moveVector;
private CharacterController controller;
// Use this for initialization
void Start () {
controller = GetComponent<CharacterController> ();
}
// Update is called once per frame
void Update () {
inputDirection = Input.GetAxis ("Horizontal");
moveVector = new Vector3 (inputDirection, VerticalSpeed, 0) * speedmultiplier;
controller.Move (moveVector * Time.deltaTime);
if (controller.isGrounded) {
VerticalSpeed = 0.0f;
jump = true;
} else {
VerticalSpeed = gravity;
jump = false;
}
if (Input.GetKey(KeyCode.X)) {
if(jump == true) {
VerticalSpeed += 25f;
}
}
}
}
You can try changing the vertical speed in your else to reflect a change over time.
Perhaps something like:
VerticalSpeed += gravity * Time.deltaTime
Instead of just setting it to gravity. You may need to play with your initial jump speed to get it to feel better, but this should start your jump fast-ish, slow down as you reach the top of the jump, and speed back up as you fall.