How do i avoid MidAir jumps in Unity using c# - c#

I want to create a jumping Script, i got so far, the problem is that i do not want the gameObject to jump midair
I tried using OnCollisionStay/Enter together with OnCollisionExit to generate a bool which gets checked together with Input before jumping, this worked the best but unity is missing triggers
I cant check for position with gameObject.transform.position.y because i have differently elevated platforms.
isGrounded works with a different code but it interferes with my other movements (which are implemented by AddForce on Input)
I can't wrap my head around why this code doesn't work, i hope someone can help me understand.
using UnityEngine
public class PlayerMovement : MonoBehaviour
{
private CharacterController controller;
public Rigidbody rb;
public Transform PPos;
public float jumpForce = 10f;
}
public void Update()
{
if(controller.isGrounded && Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(0, jumpForce, 0);
Debug.Log("Jump Executed");
}
}
I don't get a Syntax Error

Edit
You need to set the controller.isGrounded whenever your character has the ability to jump.
PlayerScript
void OnCollisionEnter(collision other)
{
controller.isGrounded = other.gameObject.CompareTag("Ground");
}
Original
If you want to jump in mid-air, you're going to have to remove the condition that your character controller is on the ground.
if(Input.GetKeyDown(KeyCode.Space))

Related

Player Sprite Doesn't Move (Unity, C#)

I was attempting to make a top down 2D shooter using Unity. My code contains no errors that I could see, RigidBody2D and PlayerMovement (code for the player to move) have been added to the sprite, and RigidBody2D has been added to the PlayerMovement. My move speed is set to 5. Please let me know what I can do to fix this issue!
Code:
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rb;
Vector2 movement;
void Update()
{
MovementInput();
}
private void FixedUpdate()
{
rb.velocity = movement * moveSpeed;
}
void MovementInput()
{
float mx = Input.GetAxisRaw("Horizontal");
float my = Input.GetAxisRaw("Vertical");
movement = new Vector2(mx, my).normalized;
}
}
Use your character sprite as the mouse cursor instead to write a code to make the player follow the mouse pos
If you really want to move your player via script this video will help you https://www.youtube.com/watch?v=0Qy3l3VuF_o
Have a good day :)
Check if your rigidbody2D's Body type is set to static, If it is then set it to kinematic or dynamic.
Also where did you import the script to?
Your code is not the problem, I tested it myself! Although you could move MovementInput(); to the FixedUpdate. Its not required though.
Edit: Image of the inspector as i have it if it helps

Why does this not stop my character from jumping unlimited times?

My character just jumps continuously even in the air, I'm not sure why the boolean does not stop it and I cannot figure it out. This is what I have so far:
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
public Rigidbody rb;
bool spacePressed = false;
float upForce = 200f;
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Obstacle")
{
spacePressed = false;
}
}
void Update()
{
if (Input.GetKey("space") && spacePressed == false)
{
spacePressed = true;
rb.AddForce(0, upForce * Time.deltaTime, 0, ForceMode.VelocityChange);
}
}
}
My guess is that 'space pressed' is never or instantly set to false. So a first step on debuging it can be to watch the boolean. You can do that with 'public ...'. Then you should just observe when it's set to true/false.
There is also the possiblilty of this being a totally different kind of issue. For instance that one of the colliders could be of the wrong size (too big/small)
And to complete the holy trinity: There is a free 2D platformer example in the unity hub. I think they use a different approche by using an empty GO as a 'isGrounded' checker. One of the first things I learned as a hobbist is not to be ashamed to copy code of example projects.
Good luck.
It is likely that the collider is hitting Obstacle as it makes its first jump. OnCollisionEnter is very unreliable when checking if an object is beside/on another object. This can be checked if you use Debug.Log and check to see how much times it randomly activates OnCollisionEnter.
To reliably check if an object is beside another object use raycasts or boxcasts instead.
This is some code that should work that uses raycasts:
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
public Rigidbody rb;
public Collider collider;
public float extraCheckHeight = 0.1f;
float upForce = 200f;
bool isGrounded(){
Physics2D.Raycast(collider.bounds.center, Vector3.down, collider.bounds.extents.y + extraCheckHeight);
}
void Update()
{
if (Input.GetKey("space") && isGrounded)
{
rb.AddForce(0, upForce, 0, ForceMode.VelocityChange);//Time.deltaTime is should not be here because it should be the same force regardless of the time between frames
}
}
}
This should do the trick but I recommend researching about unity raycasts and boxcasts.
Here is a video on Ground Checking that I found useful when I was approached with a similar problem: Ground Check

My Unity 2D player controller script won't make my character flip when he moves to a different direction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed;
public float jumpForce;
private float moveInput;
private Rigidbody2D rb;
private bool facingRight = true;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
}
void FixedUpdate()
{
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
if(facingRight == false && moveInput > 0)
{
Flip();
}
else if(facingRight == true && moveInput < 0)
{
Flip();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
}
I'm made a c# 2D player controller script to use in unity, but when I hit play, my player won't flip and face a different direction when he moves a different direction. Can anyone spot what's wrong in my script?
Nevermind. Was just a dumb bug. I put an outdated AND updated script component into my player. Yes I know I'm stupid.
Unity seems a good choice to developp your game but due to the simplicity of your game, i think it will be easier to create it using Android Studio, it is more easier to handler Character Sprite and Animation. All depend of what kind of game you want to create.
"""For instances guys, i create a simple SkaterBoard game using simple gravity physics with Android Studio, I would really appreciate if you could left a review on it."""
(Android Link) Skater Soldier Game: https://play.google.com/store/apps/details?id=com.fight.exempleclass
Always make sure you double check settings, values, and where you attached scripts : )
I've heard a couple people advise against flipping via scale and instead prefer :
transform.Rotate(0f, 180f, 0f);
Or depending on the gameplay / utility needed using SpriteRenderer.flipX
In case you'd like alternatives.

Run code on every frame two colliders are in contact

im trying to make it so that if my character continues to touch a gameobject with a damage script the player continuesly gets damaged. instead of this result i only get damaged once when touching the gameobject. there are no error messages. ive tried to replace the if with a while loop and it ended up crashing my game. is there any way to loop a if statement preferably with a way to time it.
if (other.tag == "Player")
{
healthScript.healthPoints -= damage;
}
this is the if statement im trying to loop.
First, I am under the assumption you are using Colliders as triggers with the Is Trigger attribute selected. I am also assuming this is a 2D game. If not, this same approach will work, you will just have to change the methods from 2D to 3D.
You will want to add the OnTriggerEnter2D() and OnTriggerExit2D() methods to your player health script. These will allow us to detect when the player is standing on the damaging object. From here, we will start a coroutine which can be used to deal damage in a timed manner.
using System.Collections;
using UnityEngine;
public class HealthScript : MonoBehaviour
{
public float healthPoints = 100f;
public float damage = 5f;
public bool OnDamagingObject = false;
IEnumerator DealDamage()
{
while (OnDamagingObject)
{
healthPoints -= damage;
yield return new WaitForSeconds(1f);
}
}
void OnTriggerEnter2D(Collider2D hitInfo)
{
GameObject collider = hitInfo.gameObject;
if (collider.tag == "DamagingObject")
{
OnDamagingObject = true;
StartCoroutine(DealDamage());
}
}
void OnTriggerExit2D(Collider2D hitInfo)
{
GameObject collider = hitInfo.gameObject;
if (collider.tag == "DamagingObject")
{
OnDamagingObject = false;
}
}
}
For those who wish to use OnTriggerStay(), I will also provide a solution for that. This time, we will keep the script on the damaging object, following the structure the question asker is using.
using UnityEngine;
public class DamageScript : MonoBehaviour
{
public HealthScript healthScript;
public float damage = 5f;
void OnTriggerStay2D(Collider2D hitInfo)
{
GameObject other = hitInfo.gameObject;
if (other.CompareTag("Player"))
{
healthScript.healthPoints -= damage;
}
}
}
As mentioned in the comments of my other answer, implementing both OnTriggerEnter() and OnTriggerExit() allow more control over dealing damage to the player. One of the downsides to using OnTriggerStay() is I am unsure how to deal the damage in a timed manner. Additionally, OnTriggerStay() limits how you can deal damage to the player. If in the future you wanted to give 5 damage to the player when they first touch the damaging object but 2 damage for every second thereafter while touching it, it is not possible to do so using OnTriggerStay().

How can I make a game object jump when I press a key (preferably space)?

I have this C# script attached to my main camera game object which also has a capsule collider attribute. However, it doesn't seem to do anything. How should I modify/add to this to make the camera "jump" and fall down to the ground again?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Jump : MonoBehaviour {
[HideInInspector] public bool jump = false;
public float jumpForce = 1000f;
public Transform groundCheck;
private bool grounded = false;
private Rigidbody rb;
// Use this for initialization
void Awake ()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update ()
{
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if (Input.GetButtonDown("Jump") && grounded)
{
jump = true;
}
}
void FixedUpdate()
{
if (jump)
{
rb.AddForce(new Vector2(0f, jumpForce));
jump = false;
}
}
}
Also, I would like to have the key for this be the spacebar if possible, but whatever key works or is there already is fine. I am still learning C#, so please forgive me if the solution is obvious.
This line is most likely causing the problem:
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));`
There are 2 reason that it wont produce proper results:
You haven't setup your ground tiles or the place where you character moves to the "Ground" layer. You wont have this by default but you can add it from the Project Settings->Tags and Layers menu.
Your colliders are not close enough to the ground thus not causing collision.
Besides that it should work fine.

Categories