My 2D Character is not jumping at all - c#

I am having an issue with my character which is not jumping at all. I am new to Unity, but I made sure to apply the script to the player and adjust the speed, I did not touch the Rigidbody 2D. If any one can help me figure our the issue, it will be much appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
public float moveSpeed;
public float jumpSpeed;
public bool grounded = false;
private Rigidbody2D rb;
void Start() {
rb = GetComponent<Rigidbody2D>();
}
void Update () {
transform.Translate (Input.GetAxisRaw ("Horizontal") * moveSpeed * Time.deltaTime, 0, 0);
if (grounded)
{
if (Input.GetButtonDown ("Jump"))
{
rb.AddForce (Vector2.up * jumpSpeed);
grounded = false;
}
}
}
void OnCollisionEnter2D (Collision2D coll){
if (coll.transform.tag == "Ground")
{
grounded = true;
}
}
}
Inspector window of the Player GameObject
Inspector window of the Ground GameObject

Your problem is you haven't tag the Ground GameObject as so. So in the OnCollisionEnter2D the character detects the collision, but the if (coll.transform.tag == "Ground") will never be true. So it means the character can't be grounded
Since to be grounded is the first condition to check if the player pressed the Jump key. It is impossible it will ever jump
if (grounded)
{
if (Input.GetButtonDown ("Jump"))
{
rb.AddForce (Vector2.up * jumpSpeed);
grounded = false;
}
}
To solve this issue: You need to tag the Ground GameObject as so. In case you are not sure how to do that, on the Tag menu, create (if it doesnt exist already) a new tag called Ground. Then assign in that same menu the Ground Tag to the Ground GameObject. Here you can learn how in case you need a visual reference:
https://docs.unity3d.com/Manual/Tags.html
Edit: You can try this script if everything fails. It should work. I used my self some time ago, I cleaned the code so to leave only what you need to move the character in the x and y axis. Hope to have included everything you need:
public class CharacterController2D : MonoBehaviour {
// LayerMask to determine what is considered ground for the player
public LayerMask whatIsGround;
// Transform just below feet for checking if player is grounded
public Transform groundCheck;
// store references to components on the gameObject
Transform transform;
Rigidbody2D rigidbody;
bool isGrounded = false;
float vy;
float vx;
public float jumpForce = 600f;
void Awake () {
transform = GetComponent<Transform> ();
rigidbody = GetComponent<Rigidbody2D> ();
}
void Update()
{
// determine horizontal velocity change based on the horizontal input
vx = Input.GetAxisRaw ("Horizontal");
vy = rigidbody.velocity.y;
// Check to see if character is grounded by raycasting from the middle of the player
// down to the groundCheck position and see if collected with gameobjects on the
// whatIsGround layer
isGrounded = Physics2D.Linecast(transform.position, groundCheck.position, whatIsGround);
if(isGrounded && Input.GetButtonDown("Jump")) // If grounded AND jump button pressed, then allow the player to jump
{
DoJump();
}
// Change the actual velocity on the rigidbody
rigidbody.velocity = new Vector2(_vx * MoveSpeed, _vy);
}
//Make the player jump
void DoJump()
{
// reset current vertical motion to 0 prior to jump
vy = 0f;
// add a force in the up direction
rigidbody.AddForce (new Vector2 (0, jumpForce));
}
}
So things to take into account:
Instead of tag the ground, you create a layer with everything you
consider ground. That will include possible platforms the character
may jump over. Pass as a parameter this layer to the script in the
inspector
You need to place an empty GameObject in the feet of the character.
You will drag and drop that GameObject in the editor onto the
groundCheck public variable.
Instead of OnTriggerEnter, you will use Physics2D.Linecast which
will trave a line from the position of the character to under its
feet (where you should have place the Transform mentioned in the
previous step) and if in the middle there is an element of the
groundLayer, it means the character will be grounded.
Let me know if anything is not clear or if you find some bug.

As mentioned your problem is deffinetly that your missing to tag your ground object :)
A tip: What i like to do when i have problems like this is to use the unitys Debug.Log() to locate where the problem is it. It will let you know easily in the console what code is run and which is not. Try do the following:
void Update () {
transform.Translate (Input.GetAxisRaw ("Horizontal") * moveSpeed * Time.deltaTime, 0, 0);
if (grounded)
{
Debug.Log("Is grounded");
if (Input.GetButtonDown ("Jump"))
{
Debug.Log("Jump clicked");
rb.AddForce (Vector2.up * jumpSpeed);
grounded = false;
}
}
}

Related

Unity 2D character keeps playing walking animation when colliding and raycasts don't work as expected

I have been working on a 2d top down rpg game and I have added walking animations etc, I want to stop the player from doing a walking animation when they hit a wall and currently I have a box collider with a ray cast, the ray cast originally hit the player box collider when walking down but after using a layermask this has stopped, however while walking left and right work perfectly two issues occur that I cannot seem to fix. First, when walking up or down into a tilemap that is on the collision layer (this tilemap has tilemap collider which will stop the player from walking through them) the animation still plays, and second the player will only collide once instead of repeatedly when hitting the tilemap when two tiles are placed back to back, here is my code for collision, the tiles that are for collision are on layer 6.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
public float moveSpeed;
private Animator ani;
private bool isMoving;
private Vector2 lastMove;
private Rigidbody2D body;
private Vector2 movement;
private LayerMask wallLayer = 1 << 6;
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody2D>();
ani = GetComponent<Animator>();
movement = Vector2.zero;
isMoving = false;
}
// Update is called once per frame
void Update() {
isMoving = false;
movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
RaycastHit2D ray = Physics2D.Raycast(body.position, movement, 0.6f, wallLayer);
if((movement.x != 0f || movement.y != 0f) && !(ray && ray.collider.tag == "wall")) {
isMoving = true;
lastMove = movement;
}
ani.SetFloat("MoveX", movement.x);
ani.SetFloat("MoveY", movement.y);
ani.SetFloat("LastX", lastMove.x);
ani.SetFloat("LastY", lastMove.y);
ani.SetBool("IsMoving", isMoving);
}
void FixedUpdate() {
body.MovePosition(body.position + movement * moveSpeed * Time.deltaTime);
}
}
The code looks fine. Most likely, the issue is with your configuration of the AnimatorController.
Do you have transitions in place for (for example) coming from the walk animation back to idle?

Destroy object when it touch Ground unity 2d

Hey I just want my bullet to destroy itself when it touch Ground i tried to destroy after 2 seconds but it has the same problem That's My Code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyBullet : MonoBehaviour
{
GameObject target;
public float speed;
Rigidbody2D bulletRB;
void Start()
{
bulletRB = GetComponent<Rigidbody2D>();
target = GameObject.FindGameObjectWithTag("Player");
Vector2 moveDir = (target.transform.position - transform.position).normalized * speed;
bulletRB.velocity = new Vector2(moveDir.x, moveDir.y);
Destroy(this.gameObject, 2);
}
}
Destroy the bullet object using the Destroy method.The bullet is destroyed after flying a certain distance.
public float speed;
public float destoryDistance;
private Rigidbody2D rg2d;
private Vector3 startPos;
// Start is called before the first frame update
void Start()
{
rg2d = GetComponent<Rigidbody2D>();
rg2d.velocity = transform.right * speed;
startPos = transform.position;
}
// Update is called once per frame
void Update()
{
float distance = (transform.position - startPos).sqrMagnitude;
if (distance > destoryDistance)
{
Destroy(gameObject);
}
}
Use OnCollisionEnter() to destroy to bullet
void OnCollisionEnter(Collision collider)
{
if (collider.GameObject.tag == "Ground")
{
Destroy (this.GameObject)
}
}
What's happening here is that this function gets called every time it collides with an object, so we put the destroy code here. It takes the collider as a parameter, and then checks if the GameObject has the tag "Ground", and if it does, destroy itself.
Note that you will also have to add a tag to your ground objects in the hiearchy. You can name them anything else too, but make sure to change "Ground" in the code when you do set the tag to anything other than it.
You will probably also have other colliders like walls in your game so you should make a universal tag that destroys bullets and name it something like "Destroy Projectiles" or something.
Edit: You can have multiple functions that destroy the GameObject.

Make an enemy walk around a rectangular platform, like in Metroid

I'm new to Unity, so probably this is a dumb question but I have several days trying to figure it out. I have an enemy walking from one side of a platform to the other. I'm using Raycasting to check if there´s no ground below and turn to the other way.
What I want is for the enemy to walk AROUND the platform (Just like the enemies in Metroid). I set the gravity of the enemy to 0 so it will not fall down, but I don´t know how to make it rotate and keep walking around the platform. I know it could be done with raycasting but I have not clue how to do it.
I will enormously appreciated if anyone can help me with the piece of code I'm missing. Thanks in advance!
public class BlobController : MonoBehaviour {
private Rigidbody2D myRigidBody;
public float moveSpeed;
public LayerMask groundMask;
float myWidth;
// Use this for initialization
void Start ()
{
myRigidBody = GetComponent<Rigidbody2D>();
myWidth = GetComponent<SpriteRenderer> ().bounds.extents.x;
}
// Update is called once per frame
void Update ()
{
}
void FixedUpdate()
{
//Check to see if there's ground in front before moving forward
Vector2 lineCasPos = transform.position - transform.right * myWidth;
Debug.DrawRay (lineCasPos, Vector2.down,Color.red);
bool isGrounded = Physics2D.Raycast (lineCasPos, Vector2.down, 2, groundMask);
//If there's no ground, turn around
if (!isGrounded)
{
Vector3 currRot = transform.eulerAngles;
currRot.y += 180;
transform.eulerAngles = currRot;
}
//Always move forward
Vector2 myVel = myRigidBody.velocity;
myVel.x = -transform.right.x * moveSpeed;
myRigidBody.velocity = myVel;
}
}

How do I make my player with a Rigidbody move with isKinematic checked?

My game is a topdown zombie shooter and whenever the zombies get to the player they bunch up underneath them, to the point where the player can just walk over the zombies. I noticed that when I check isKinematic on the Rigidbody the zombies cant push the player up to go underneath him, so they just run into him(which is what I want). Despite this I am then unable to move. How can i fix this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMoving1 : MonoBehaviour {
public float moveSpeed;
private Rigidbody myRigidbody;
private Vector3 moveInput;
private Vector3 moveVelocity;
private Camera mainCamera;
public GunController theGun;
void Start () {
myRigidbody = GetComponent <Rigidbody>();
mainCamera = FindObjectOfType<Camera>();
}
// Update is called once per frame
void Update () {
moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput * moveSpeed;
Ray cameraRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
float rayLength;
if(groundPlane.Raycast(cameraRay,out rayLength))
{
Vector3 pointToLook = cameraRay.GetPoint(rayLength);
transform.LookAt(new Vector3(pointToLook.x,transform.position.y,pointToLook.z));
}
if (Input.GetMouseButtonDown(0))
theGun.isFiring = true;
if (Input.GetMouseButtonUp(0))
theGun.isFiring = false;
}
void FixedUpdate(){
myRigidbody.velocity = moveVelocity;
}
}
With isKinematic == true You can't change object position through rigidbody, You can only change transform.position.
I think it could be better, if You set isKinematic to false and add stopping distance to enemies, so they can't get too close to player.
Being that your player can no longer be effected by the physics engine, you'd have to manipulate the object's transform manually. Your script isn't ideally setup for it currently, but if I was to hack it into it and try to make it work it would look something like this:
(you can change it from fixedUpdate to update if you're no longer utilizing the physics engine)
void update(){
float x = Input.GetAxisRaw("Horizontal")* Time.Deltatime;
float z = Input.GetAxisRaw("Vertical") * Time.Deltatime;
transform.position = new Vector3(transform.position.x+x,0,transform.position.z+z);
Another way of doing this is to lock the position of Y for the player (assuming Y is the positive "up" direction). isKinimatic is best when you want to move the player or objects around yourself.
I would say upping the mass is better in this case, and you can keep isKinematic unchecked in this case then too. Also apply the lock for Y movement (again if it is the "up" direction from the plane)
Let me know what your solution is regardless, I've had some issues in the past as well with these types of events happening

Use AddForce to knock back Player after contact with Enemy

I'm working on my very first Unity game. It's still in prototype and will be very simple anyways, consisting of a cube as the player and spheres as enemies.
I'm trying to write a code with AddForce to knock the player a pretty good distance in an arc in the direction opposite of the enemy when they come in contact, but I still have a primitive understanding of how to use AddForce and can't seem to get force applied in any direction at all. The player just moves through the enemy.
Here's the only thing I could manage to scrap together and it is obviously insufficient:
if (other.gameObject.tag == "Enemy")
{
playerDead = true;
Rigidbody rigidbody = other.GetComponent<Rigidbody> ();
rigidbody.AddForce (transform.forward * 100);
}
I can post a screenshot if it helps.
Instead of transform.forward, use a more tailored direction depending on the position of both units
public float speed = 100;
if (other.gameObject.tag == "Enemy")
{
playerDead = true;
Vector3 direction = (transform.position - other.transform.position).normalized;
other.GetComponent<Rigidbody>().AddForce (direction * speed);
}
Edit: You must make sure that the rigidbody is on the game object calling the OnCollisionEnter function, it cant just be on any of the objects involved in the collision.
I cannot comment so I must make an answer.
You have an isTrigger set up apparenty. Be sure to turn isTrigger OFF or your player will walk through the enemy collider.
[SerializeField]
private float speed = 100;
private bool playerDead;
OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Enemy")
{
playerDead = true;
Vector3 direction = (transform.position - collision.transform.position).normalized;
collision.GetComponent<Rigidbody>().AddForce (direction * speed,0,0);
//AddForce is a vector3 apparently and requires (x,y,z)
// Also note that I'm getting errors with the "collision.GetComponent<>"
// You're going to want to remove "collision"
// I think the smarter approach maybe to declare a public Rigidbody variable ( Up Top )
[SerializeField]
private Rigidbody playerRidg;
playerRidg = GetComponent<Rigidbody>().AddForce(direction * speed,0,0);
}
}
My solution using coroutine which toggles a bool "spikes":
Player collision:
private void OnTriggerEnter2D(Collider2D collision){
if (collision.gameObject.tag == "Spike" )
{
StartCoroutine(Knockback());
}
}
Coroutine:
IEnumerator Knockback()
{
spikes = true;
yield return new WaitForSecondsRealtime(0.3f);
spikes = false;
}
Whenever the spikes bool is true player will be moved
void FixedUpdate()
{
if (spikes ==true)
{
Vector2 NewPosition = new Vector2(10.0f, 10.0f);
moveCharacter(NewPosition);
}
}

Categories

Resources