i'm beginner on unity and game development. i'm trying to make a platformer game with unity, and i want to play a animation when the player is moving right or left, but the problem is that the isMoving variable for some reason is true animation is playing for a few moments (less than a second) and then is going to false again and the idle animation is playing.
My Animator (Exit time is disabled for all transitions):
My Movement script:
public class PlayerMovement : MonoBehaviour
{
private bool canPlayerJump;
private float horizontalInput;
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && canPlayerJump)
{
GetComponent<Rigidbody>().AddForce(Vector3.up * 5, ForceMode.VelocityChange);
}
if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.A))
{
animator.SetBool("isMoving", true);
} else
{
animator.SetBool("isMoving", false);
}
horizontalInput = Input.GetAxis("Horizontal");
}
private void FixedUpdate()
{
GetComponent<Rigidbody>().velocity = new Vector3(horizontalInput * 5, GetComponent<Rigidbody>().velocity.y, 0);
}
private void OnCollisionEnter(Collision collision)
{
canPlayerJump = true;
Debug.Log(collision.gameObject.name);
}
private void OnCollisionExit(Collision collision)
{
canPlayerJump = false;
}
}
You using Update loop function that means this code will be executed each frame by unity. Similar to FixedUpdate, LateUpdate etc...
You can read more here: HERE
Once you pressing down you IF statement will be executed because you listening for BTN DOWN event. This means that TRUE will be returned only in one frame when you press actually button next frame it will return false. and your animations stops.
Try to change bool to Trigger
Or handle in another way bool var state.
Input.GetKeyDown
is only true in the one frame the button went down.
Returns true during the frame the user starts pressing down the key identified by the key KeyCode enum parameter.
You rather want to use Input.GetKey which stay true as long as the key stays pressed.
Returns true while the user holds down the key identified by the key KeyCode enum parameter
alternatively in order to not have redundant accesses you could also simply use
horizontalInput = Input.GetAxis("Horizontal");
animator.SetBool("isMoving", !Mathf.Approximately(horizontalInput, 0));
And as a general note: Cache the component references and don't use GetComponent over and over again!
[SerializeField] private Rigidbody _rigidbody;
private void Awake ()
{
if(!_rigodbody) _rigidbody = GetComponent<Rigidbody>();
}
then later everywhere use _rigidbdoy instead of GetComponent<Rigidbody>()
Related
So, I'm still not the best at this but I'm trying to use this script for 2D movement but the jumping isn't working for some reason. It keeps saying that the OnCollisionEnter function "is declared but never used". Can someone tell me what im doing wrong? Thanks
If I remove the (Collision col) part it says that "void cannot be used in this context".
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RonyWalking : MonoBehaviour
{
Rigidbody2D rigid;
SpriteRenderer sprite;
public bool isJumping;
public float spd = 2.0f;
// Start is called before the first frame update
void Start()
{
rigid = GetComponent<Rigidbody2D>();
sprite = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
if(Input.GetKey("d")){rigid.velocity = new Vector2(spd, 0);}
else if(Input.GetKey("a")){rigid.velocity = new Vector2(-spd, 0);}
if(Input.GetKeyDown("w") && isJumping == false)
{
rigid.velocity = new Vector2(0, 5);
isJumping = true;
}
void OnCollisionStay(Collision col)
{
isJumping = false;
}
}
}
When using 2D physics, you need to use the 2D lifecycle methods;
void OnCollisionStay2D(Collision2D col)
{
isJumping = false;
}
And you shouldn't put this method inside your Update method... It should be on class level:
public class RonyWalking
{
void Update()
{
// ...
}
void OnCollisionStay2D(Collision2D col)
{
// ...
}
}
Don't worry about "Is declared but never used", this may be because you don't have specific code referencing the method, but Unity will raise events that calls it, "automagically"
Another thing that I can see while reading your code, that may be unintentional behaviour for you, is that when clicking left/right, you set velocity UP to 0, and when clicking up you set LEFT/RIGHT velocity to 0; this will result in freezing the movement mid-air if you jump, then move while in air:
Click D; velocity = 2, 0
Click W; velocity = 0, 5
Character will now move upwards until another input is given
Click D; velocity = 2, 0 and the character will continue moving while in air because when moving sideways the up/down velocity is set to 0
To solve this, either set the other to existing velocity or make the inputs manipulate a Vector that you then apply at the end of the movement code:
Vector2 existingMovement = rigid.velocity;
if (Input.GetKey(KeyCode.D))
existningMovement.x = spd;
else if (Input.GetKey(KeyCode.A))
existningMovement.x = -spd;
if (Input.GeyKeyDown(KeyCode.W) && !isJumping)
{
existningMovement.y = 5f;
isJumping = true;
}
Furthermore, I think you may have some unexpected behaviour with OnCollisionStay; it will fire every frame that you're colliding with the ground, I assume. But I think it may also fire a frame or two AFTER you've jumped since the physics of your character will not INSTANTLY leave the collision, so isJumping will be set to false even after your jump, letting you jump while in the air one more time.
I would recommend that you use OnCollisionExit2D(Collision2D col) to set isJumping = true instead, or OnCollisionEnter2D(Collision2D col) and set it to isJumping = false, depending on the functionality you desire (if you want the ability to jump after walking out of a cliff)
I'm creating shooting in Unity, I've set up everything but the problem is that I want the animation to play only on single click but in my script it plays animation infinitely while holding the button. Check the script below. Thanks.
public GameObject bulletPrefab;
public Transform firePoint;
private Animator anim;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);
anim.SetBool("isShooting", true);
}
if (Input.GetKeyUp(KeyCode.Space))
{
anim.SetBool("isShooting", false);
}
}
Set 2 States with just Keys on time = 0 the end position Shooting and the end position idle. From idle to shooting with a trigger parameter. From shooting to idle just a time transition. Ps shooting can be done with multiple frames too. Hope it helps.
So basically, after hours of torment trying to create basic movement script for simple platformer game I succeeded, but not quite. Square character is able to move around and jump just ok, but sometimes it won't jump, usually while moving on short distances or, rarely, standing in place and trying to jump. I can't figure out how to fix that. Here is entire script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
private Rigidbody2D rgdb2;
public float movementSpeed;
public float jumpHeight;
private bool isJumping = false;
// Use this for initialization
void Start ()
{
rgdb2 = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis("Horizontal");
HandleMovement(moveHorizontal);
if (Input.GetKeyDown(KeyCode.Space) && isJumping == false)//by typing Space player jumps, cant double-jump
{
rgdb2.AddForce(new Vector2(rgdb2.velocity.x, 1 * jumpHeight), ForceMode2D.Impulse);
isJumping = true;
Debug.Log("jumped");
}
}
private void HandleMovement(float moveHorizontal)//applying player horizontal controls and customing player's speed by movementSpeed variable
{
rgdb2.velocity = new Vector2(moveHorizontal * movementSpeed, rgdb2.velocity.y);
}
private void OnCollisionEnter2D(Collision2D coll)
{
if (coll.transform.tag == "Platform") //if player is touching object with Platform tag, he can jump
{
Debug.Log("on ground bitch");
isJumping = false;
}
}
}
It may not be that important, but I want to polish this game as much as possilble, even if I don't need to, since it's basically my first game made in Unity3d with C#.
An important thing to keep in mind: Unity3D Engine's inputs are only updated during the time the engine calls Update() methods for your GameObjects.
What this means is that you should not read any type of input in the FixedUpdate() method. Methods like GetKeyDown() and other methods from the Input class which read keyboard/mouse/axis buttons/values should not be called during FixedUpdate(), as their returned values are unreliable.
Due to this, what is probably causing your jump implementation to fail is that the GetKeyDown() method you're calling in FixedUpdate() is returning inconsistent/invalid (false) results, when the user presses the jump key.
Fixing this can be quite simple. I suggest you keeping a boolean variable which keeps track of whether the jump key has been pressed, and gets its value updated during Update(). This should fix your problem.
bool jumpKeyPressed;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
jumpKeyPressed = true;
else if (Input.GetKeyUp(KeyCode.Space))
jumpKeyPressed = false;
}
private void FixedUpdate()
{
/* Update "moveHorizontal", call HandleMovement(...) here, as you've already done. */
if (jumpKeyPressed && isJumping == false)
{
// IMPORTANT: this prevents the "jump force" from being applied multiple times, while the user holds the Space key
jumpKeyPressed = false;
/* Remaining jumping logic goes here (AddForce, set "isJumping", etc) */
}
}
It's because your logic for jumping is inside FixedUpdate()
When you use GetKeyDown to register input make sure to use Update instead because if you press the key using FixedUpdate it may or may not run during that frame, test it with Update instead.
You already have in comments how Update works, it is called every frame but FixedUpdate according to Unity documentation: This function is called every fixed framerate frame
void Update ()
{
float moveHorizontal = Input.GetAxis("Horizontal");
HandleMovement(moveHorizontal);
if (Input.GetKeyDown(KeyCode.Space) && isJumping == false)//by typing Space player jumps, cant double-jump
{
rgdb2.AddForce(new Vector2(rgdb2.velocity.x, 1 * jumpHeight), ForceMode2D.Impulse);
isJumping = true;
Debug.Log("jumped");
}
}
I am new to unity so i am unable to figure out this , I have dolphin in my game when it collides it dies so it has two animations one is its moving changes to dead body and second animation is bubbles which are dolphin's child object , the second trigger it fires is to stop bubbles , the first trigger is working that is its moving body changes to dead body , but the second trigger doesn't work that is its bubbles are still coming out, i dot know whats wrong.
public class Dolphin : MonoBehaviour
{
private bool IsDead=false;
private Rigidbody2D rb2d;
public float upforce = 200f;
private Animator anim;
// Use this for initialization
void Start ()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update ()
{
if (IsDead == false)
{
if (Input.GetMouseButtonDown(0))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(new Vector2(0, upforce));
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
IsDead = true;
anim.SetTrigger("Die");
anim.SetTrigger("StopBubble");
Debug.Log("rigger");
}
}
You should set the second trigger to your bubble game object Animator (Not to Dolphin Animator)
Only change your script to this:
private void OnCollisionEnter2D(Collision2D collision)
{
IsDead = true;
anim.SetTrigger("Die");
transform.GetChild(0).GetComponent<Animator>().SetTrigger("StopBubble");
Debug.Log("rigger");
}
(Note: Your bubble game object is the first child of dolphin game object. By using transform.GetChild(0) you can access to it)
I hope it helps you
I'm trying to test out a fish that will jump out of the water. My script seems fine except when I press the key nothing happens. I was following a simple tutorial and it seems to work for everyone. What am I doing wrong and how can I make this more simple for when referencing it in my capture script later without key down. This is because the fish will jump on its own later.
public bool onGround;
private Rigidbody rb;
// Use this for initialization
void Start ()
{
onGround = true;
rb = GetComponent<Rigidbody> ();
}
// Update is called once per frame
void update ()
{
if (onGround)
{
if (Input.GetKeyDown ("a"))
{
rb.velocity = new Vector3 (0f, 5f, 0f);
onGround = false;
}
}
}
}
Actually, the more likely thing is that your update function is not correctly setup
Change it to
void Update()