Why object has a weird behavior in case of collision? - c#

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;
}
}
}

Related

unity onCollisionEnter2D is not working, how can I get it to work?

my bird is colliding with the clouds but it only moves them and doesn't trigger it
my character
public float jumpForce = 5f;
public float gravity = -9.81f;
public GameObject gus;
public Transform rotation_checker;
public Transform chekced;
float velocity;
void Start()
{
}
// Update is called once per frame
void Update()
{
gameObject.transform.eulerAngles = new Vector2(0,0);
velocity += gravity * Time.deltaTime;
if (Input.GetKeyDown(KeyCode.W))
{
velocity = jumpForce;
}
rotation_checker.position = chekced.position;
transform.Translate(new Vector2(0, velocity) * Time.deltaTime);
}
private void OnTriggerExit2D(Collider2D collider)
{
Debug.Log(collider.gameObject);
if(collider.gameObject.name == "skybluscene")
{
Destroy(gameObject);
}
}
private void onCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "cloud")
{
Destroy(gameObject);
}
}
the cloud
float x = -4f;
void Start()
{
}
// Update is called once per frame
void Update()
{
gameObject.transform.Translate(new Vector2(x, 0) * Time.deltaTime);
}
void OnTriggerExit2D(Collider2D collider)
{
if ( collider.gameObject.tag == "scene")
{
Destroy(gameObject);
}
}
cloud works just fine, it destroys itself when it leaves the scene but bird doesn't destroy itself when it collides with the cloud
both bird and cloud have dynamic rigidbody2d and a collider
First of all: On your character script, your onCollisionEnter2D is misspelled. It needs to start with a capital letter.
Second: all your other methods use tags to identify what GameObject they collided with, but "skybluscene" (which also looks like a typo) is identified by its gameObject name.
Third: I'm not sure, but I find it odd that you're using both triggers and collisions in the same script.

System Inputs - How to make my game object jump?

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))

Fix Jumping in the air (Unity2D)

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();
}

Unity C# - When having both OnTriggerExit and OnTriggerEnter, only OnTriggerExit gets called

Okay, so I can't see where is my problem. I used OnTriggerEnter for my moving platform. it has rigid body component and the box collider is set to isTrigger on both the platform and player, but for some reason when my platform is triggered by the player, only the OnTriggerExit gets called out . My player is tagged as player in unity... I don't know what to do.
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Moving_Platform : MonoBehaviour
{
[SerializeField]
private float _speed = 1.0f;
[SerializeField]
private Transform _A, _B;
private bool _direction = false;
void FixedUpdate()
{
if(transform.position==_A.position)
{
_direction = false;
}
else if(transform.position== _B.position)
{
_direction = true;
}
if (_direction == false)
{
transform.position = Vector3.MoveTowards(transform.position, _B.position, _speed * Time.deltaTime);
}
if(_direction==true)
{
transform.position = Vector3.MoveTowards(transform.position, _A.position, _speed * Time.deltaTime);
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
other.transform.parent = this.transform;
}
}
private void OnTriggerExit(Collider other)
{
Debug.Log("OMFG");
if (other.tag == "Player")
{
Debug.Log("But why!");
other.transform.parent = null;
}
}
}
All Inspectors
It seems that updating to a newer version (2020.x) made the trick.
Thanks for trying.

Jump once only until character lands

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;
}

Categories