I just started using Unity am trying to make a simple 3D platformer, before I can get to that, I need to get movement down. My problem comes in when the player jumps. When they jump, they can jump in the air as much as they want. I want it to only jump once. Can anybody help?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Playermovement : MonoBehaviour
{
public Rigidbody rb;
void Start ()
}
void Update()
{
bool player_jump = Input.GetButtonDown("DefaultJump");
if (player_jump)
{
rb.AddForce(Vector3.up * 365f);
}
}
}
}
You can use a flag to detect when the player is touching the ground then only jump the player is touching the floor. This can be set to true and false in the OnCollisionEnter and OnCollisionExit functions.
Create a tag named "Ground" and make the GameObjects use this tag then attach the modified code below to the player that is doing the jumping.
private Rigidbody rb;
bool isGrounded = true;
public float jumpForce = 20f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
bool player_jump = Input.GetButtonDown("DefaultJump");
if (player_jump && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce);
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
}
}
Sometimes, using OnCollisionEnter and OnCollisionExit may not be fast enough. This is rare but possible. If you run into this then use Raycast with Physics.Raycast to detect the floor. Make sure to throw the ray to the "Ground" layer only.
private Rigidbody rb;
public float jumpForce = 20f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
bool player_jump = Input.GetButtonDown("DefaultJump");
if (player_jump && IsGrounded())
{
rb.AddForce(Vector3.up * jumpForce);
}
}
bool IsGrounded()
{
RaycastHit hit;
float raycastDistance = 10;
//Raycast to to the floor objects only
int mask = 1 << LayerMask.NameToLayer("Ground");
//Raycast downwards
if (Physics.Raycast(transform.position, Vector3.down, out hit,
raycastDistance, mask))
{
return true;
}
return false;
}
Related
I have the problem with collision. Beginning creating the 3D game, I noticed that Player (gameObject) when moving in case of collision either falls down, or passes through the object, or repels from the object if it is inside it. I want to Player in case of collision couldn't pass through objects. Objects have colliders, Player has both collider, and Rigidbody with Physic Material. I'm beginner, so I don not know how to solve this problem. What is wrong?
Below script Player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] public int speed;
public bool ground;
public float jumpPower = 2500f;
public Rigidbody rb;
void Start()
{
rb= GetComponent<Rigidbody>();
}
void Update()
{
GetInput();
}
private void GetInput()
{
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
transform.position += transform.forward * speed * Time.deltaTime;
}
// Movement Player...
if (Input.GetKeyDown(KeyCode.Space))
{
if (ground == true)
{
rb.AddForce(transform.up * jumpPower);
}
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Ground")
{
ground = true;
}
if (collision.gameObject.tag == "Gem")
{
Destroy(collision.gameObject);
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.tag == "Ground")
{
ground = false;
}
}
}
Describe the problem: So my player is stuck to the wall when he jumps and moves to the right side at the same time. Watch the video below to imagine it better.
Watch the video for better illustration: HERE
If there is anything to do with code, here is the PlayerMovement script:
public class PlayerMovement : MonoBehaviour
{
Vector2 vector2Move;
Rigidbody2D rb2D;
[SerializeField] float playerSpeed;
bool isGrounded;
Collider2D playerCollider;
float theCurrentGravityScale;
private void Awake()
{
rb2D = GetComponent<Rigidbody2D>();
playerCollider = GetComponent<Collider2D>();
}
void Start()
{
theCurrentGravityScale = rb2D.gravityScale;
}
void Update()
{
Run();
}
void OnJump(InputValue value)
{
if (playerCollider.IsTouchingLayers(LayerMask.GetMask("Ground")) && value.isPressed)
{
rb2D.velocity += new Vector2(0f, jumpForce);
animatorPlayer.SetBool("isIdling", false);
}
}
void OnMove(InputValue value)
{
vector2Move = value.Get<Vector2>();
}
void Run()
{
animatorPlayer.SetBool("isRunning", true);
Vector2 playerMovement = new Vector2(vector2Move.x * playerSpeed, rb2D.velocity.y);
rb2D.velocity = playerMovement;
}
private void OnCollisionEnter2D(Collision2D collision)
{
animatorPlayer.SetBool("isGrounded", true);
}
It seems to me like the player collider is getting stuck with the tilemap collider, you can create a new physics material 2D (Assets > Create > 2D > Physics Material 2D) and set the friction to 0
Then you need to assign the material to the Rigid Body of the player, how many colliders do you have on the player?
I need help my animation is not returning back to idle this is for my enemy. I have the transitions set up in the animator and i have a bool parameter for true and false and no I don't want to use unity built in ai thing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BossMovement : MonoBehaviour
{
public Animator anim;
public float distance;
public Transform target;
public float speed = 4f;
Rigidbody rig;
// Start is called before the first frame update
void Start()
{
rig = GetComponent<Rigidbody>();
}
private void Update()
{
whento();
transform.LookAt(target);
}
// Update is called once per frame
void followPlayer()
{
Vector3 pos = Vector3.MoveTowards(transform.position, target.position, speed * Time.fixedDeltaTime);
rig.MovePosition(pos);
transform.LookAt(target);
}
void whento()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, distance))
{
if (hit.transform.tag == "Player")
{
followPlayer();
anim.SetBool("isMoving", true);
}
else if (hit.transform.tag != "Player")
{
anim.SetBool("isMoving", false);
}
}
}
}
Try replacing the last else if Statement to just an else Statement. This way your code works regardless if you hit something or not.
I'm making a simple platformer with a rolling ball that rolls around and collects coins to win each level. I'm using Unity's System input from Unity's package manager to help me with controls and key binding and have successfully gotten my ball to roll around with ease and collect coins with a nice UI setup. However, I would like to implement harder levels where the ball jumps. I can not figure out how to make the ball jump. I know there are others ways to go about this but I just can't figure out how to make it work in the system inputs.
(I know an if statement is needed to test if the ball is grounded however again I'm new and still learning)
Gameplay | OnJump in player input is for jumping | KeyBindings
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class PlayerController: MonoBehaviour
{
public float speed = 0;
public bool isGrounded;
public float jumpForce;
public TextMeshProUGUI countText;
public GameObject winTextObject;
private Rigidbody rb;
private int count;
private float movementX;
private float movementY;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
SetCountText();
winTextObject.SetActive(false);
}
private void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
private void onJump(InputValue value)
{
}
void SetCountText()
{
countText.text = "Count: " + count.ToString();
if(count >= 12)
{
winTextObject.SetActive(true);
}
}
private void FixedUpdate()
{
Vector3 movement = new Vector3(movementX, 0.0f, movementY);
rb.AddForce(movement * speed);
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.CompareTag("PickUp"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetCountText();
}
}
}
Make sure you create a new tag called Ground and put it on everything you want your player to be able to jump on (the ground).
public float jumpHeight = 5f;
public bool isGrounded;
void Update()
{
if (isGrounded)//Checks if is on ground
{
if (Input.GetButtonDown("Jump"))//If the space is pressed
{
rb.AddForce(Vector3.up * jumpHeight)
}
}
}
void OnCollisionEnter(Collision other)//If touch other object
{
if (other.gameObject.tag == "Ground")//If other object has Ground tag
{
isGrounded = true;
}
}
void OnCollisionExit(Collision other)
{
if (other.gameObject.tag == "Ground")
{
isGrounded = false;
}
}
You can also do if (Input.GetButtonDown("Jump")) as
if (Input.GetKeyDown("space"))
or
if (Input.GetKeyDown(KeyCode.Space))
I am making my first Game and now I have a problem: I have a jump button when i press it I am jumping but when I am in the air I can press it again and jump in the air again. How can fix that, so I can jump only on the ground. Here is my Code:
using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class Move2D : MonoBehaviour
{
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
public void Jump()
{
rigidBody.AddForce(transform.up * jumpSpeed, ForceMode2D.Impulse);
}
// Update is called once per frame
}
Here is the Code
public class Move2D : MonoBehaviour
{
public bool isGrounded = false;
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody2D>();
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "Ground") //you need to add a tag to your Ground, like "Ground"
{
isGrounded = true;
}
}
public void Jump()
{
rigidBody.AddForce(transform.up * jumpSpeed, ForceMode2D.Impulse);
isGrounded = false;
}
void Update()
{
if (Input.GetButtonDown("Jump") && isGrounded == true)
{
isGrounded = false;
Jump();
}
}
}
first of all you need a boolean (isGrounded). Then you have to check the collision between the player and the ground with
private void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "Ground") //you need to add a tag to your Ground, like "Ground"
{
isGrounded = true;
}
}
And then in the Update method add this code:
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
isGrounded = false;
Jump();
}