Collisions and Colliders not working properly - c#

I have a collision script that's attached to my player (mainCamera) and bullet prefab.
void onCollisionEnter(Collision collision)
{
Debug.Log("Collision running");
if(collision.gameObject.tag == "Enemy" && this.gameObject.tag == "MainCamera")
{
Debug.Log("Hit Enemy");
if (Controller.Health > 0)
{
Controller.Health -= .2f;
}
} else if (collision.gameObject.tag == "Scenary" && this.gameObject.tag == "Bullet")
{
Debug.Log("Bullet hits Scenary");
Destroy(this.gameObject);
} else if (collision.gameObject.tag == "Enemy" && this.gameObject.tag == "Bullet")
{
Debug.Log("Bullet hits Enemy");
Destroy(this.gameObject);
EnemyScript.Health-=.2f;
}
}
None of my debug logs are being set off. I have proper tags for all of the objects, a rigidbody and sphere collider on the sphere bullet, a sphere collider on the camera, mesh colliders on scenary, and box collider on the enemy which is a cube. None of my is Triggers are ticked. The bullet also has gravity, and it falls after a certain point. It can collide with the box and stop; however when it hits the wall plane or the floor plane, the bullet falls or goes through sometimes, but also sometimes works and hits the wall and stops or hits the floor and stays there until it gets destroyed. Not entirely sure where the problem is.

The problem with the wall or floor is that unity check for physics in fixed Updates , so if you don't put your moving , etc logic in fixed updates this problem occurs.
also try this , add a physic material to your bullet.

Related

Collision detection in Unity 2d

I'm working on my first Unity project. It's a little game where you have to move your planet to dodge incoming asteroids.
I have set up a simple collision detection system but it's not working at this moment and I'm not entirely sure why.
These are the lines of codes, they're on the movement script for the planet, attached to my gameobject planet:
private void OnTriggeredEnter2D(Collider2D collision)
{
if (collision.tag == "Asteroid")
{
restartPanel.SetActive(true);
}
}
The asteroids are a prefab spawned dynamically in this manner in a script attached to an invisible gameobject:
void Update()
{
float interval = Time.deltaTime;
random = Random.Range(0f, 1f);
Debug.Log(interval);
Debug.Log(random);
if (interval > random) {
GameObject newAsteroid = Instantiate(asteroidPrefab, GetRandomPosition(), Quaternion.identity);
newAsteroid.GetComponent<Gravity>().planet = planet;
}
}
Nothing happens when planet collides with any asteroid, or when asteroids collide with each other, if that matters, and I'm not entirely sure why.
Thank you for your help.
The method name was not correct, I messed up, it should have been OnTriggerEnter2D, not OnTriggeredEnter2D.
Yikes.

How to follow the unit when you click the mouse

I need my unit to move to the enemy when i clicking mouse on enemy and destroy when my unit touch him
For moving i use navmesh and raycast hit
All units have navmesh agent
Enemies moving by points
Lot of ways to do that: i give you the global idea and you adapt to your script
i have set layer for enemy to "enemy" just to be sure to chase a clicked enemy. layer enemy = 8 in my sample
3 phases:
First phase: Click detection and trap the gameobject clicked
private bool chasing = false;
public Transform selectedTarget;
if (Input.GetMouseButtonDown(0))
{
//Shoot ray from mouse position
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit[] hits = Physics.RaycastAll(ray);
foreach (RaycastHit hit in hits)
{ //Loop through all the hits
if (hit.transform.gameObject.layer == 8)
{ //Make a new layer for targets
//You hit a target!
selectedTarget = hit.transform.root;
chasing = true;//its an enemy go to chase it
break; //Break out because we don't need to check anymore
}
}
}
Second phase: chase the enemy. so you have to use colliders and at least one rigidbody, you have plenty of tutorial which explains how to detect collision.
if (chasing)
{
// here i have choosen a speed of 5f
transform.position = Vector3.MoveTowards(transform.position, selectedTarget.position, 5f * Time.deltaTime);
}
Destroy on Collision with OnCollisionEnter (or InTriggerEnter)
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "enemy")
{
Destroy(col.gameObject);
}
}
The given code is for 3d game, if you are using a 2d game, just adapt the code to 2D, no difficulties to do that .

How to hit an uncollidable (invisible) object

So, i have a Player and a End object. The End has no Mesh renderer, but it has a Box Collider with a Slippary. So its invisible in the game, i tagged it with "End" and write this Script (in the Player).
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.tag == "End")
{
Time.timeScale = 0f;
}
}
But when i hit the invisible object called End, the Player goes ahead. I want to fix this problem because my Player moves on when i finish the game and the coordinates influence the reached points. So it has really to stop (the Playermovement is anytime activated)

Check if object is not colliding with anything

Is there a way to detect if the collider on the player (with a rigidbody) object is not colliding with any other collider in a 2D environment?
Not per se, but there are two ways you can get the information. It's easiest to keep an int counter, and increment it in OnCollisionEnter and decrement in OnCollisionExit. When the counter is 0, there are no collisions.
Another way, which will tell you which colliders are overlapping but not necessarily if they are touching, is to use a physics function. Note which type of collider you have--sphere, capsule, box. Knowing the size/shape/position of the collider, you can call Physics.OverlapBox, Physics.OverlapCapsule, or Physics.OverlapSphere. Give the function the same shape as your collider, and it will return the colliders that overlap that space. (For 2D colliders, you can use the Physics2D.Overlap* functions.)
/edit - actually piojo's idea with counters is better, just use int instead of bool.
One way would be to add an int to your script called collisions and set it to 0. Then if at any point the collider fires OnCollisionEnter just increment it, and in OnCollisionExit decrement it.
Something like this should work for 3D:
public int collisions = 0;
void OnCollisionEnter(Collision collision)
{
collisions++;
}
void OnCollisionExit(Collision collision)
{
collisions--;
}
https://docs.unity3d.com/ScriptReference/Collider.OnCollisionEnter.html
https://docs.unity3d.com/ScriptReference/Collider.OnCollisionExit.html
I don't understand what's with all the number keeping. I just did this for when my character jumps or falls off the edge and it works great.
Both my player and terrain have colliders. I tagged my terrain with a "Ground" tag.
Then check if I am currently in contact with the collider with OnCollisionStay()
void OnCollisionStay(Collision collision)
{
if (collision.collider.tag == "Ground")
{
if(animator.GetBool("falling") == true)
{
//If I am colliding with the Ground, and if falling is set to true
//set falling to false.
//In my Animator, I have a transition back to walking when falling = false.
animator.SetBool("falling", false);
falling = false;
}
}
}
void OnCollisionExit(Collision collision)
{
if (collision.collider.tag == "Ground")
{
//If I exit the Ground Collider, set falling to True.
//In my animator, I have a transition that changes the animation
//to Falling if falling is true.
animator.SetBool("falling", true);
falling = true;
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.collider.tag == "Obstacle")
{
//If I collide with a wall, I want to fall backwards.
//In my animator controller, if ranIntoWall = true it plays a fall-
//backwards animation and has an exit time.
animator.SetBool("ranIntoWall", true);
falling = true;
//All player movement is inside of an if(!falling){} block
}
}

Raycast can not detect collider

My bullet can not detect the collider and raycast can not detect the collision. It's very weird since the only way to get a message on the console is whenever I shoot bullets within the range of my terrain(either on or above), I instantly get "Terrain" printed on my console, but the raycast cannot detect any other objects and print anything, and if I go out of the range and shoot at a sphere, nothing gets printed. Everything in my game has a collider except the bullet.
Thanks!
Here's an image of my game .
void Update () {
if (Input.GetKey(KeyCode.KeypadEnter) && counter > delayTime)
{
Instantiate(bullet, transform.position, transform.rotation);
counter = 0;
RaycastHit hit;
if (Physics.Raycast(transform.position, -Vector3.up, out hit))
{
Debug.Log(hit.collider.gameObject.name);
}
}
counter += Time.deltaTime;
}
Add a collider to your bullet prefab. You should have tags on your enemies or other destructible objects. Use OnCollisionEnter OR OnTriggerEnter. For enemies, I prefer to use OnCollisionEnter for the most part.
void OnCollisionEnter(Collision collision){//Assuming bullet touches enemy
if(collision.tag=="Bullet"){
// insert your code here for damage
}
}
As far as your RayCast, I'd do something like this:
Vector3 fwd = transform.TransformDirection(Vector3.forward) * 3; // length of ray
//forward-facing. ( * 3 is equal to 3 units/Meters )
Debug.DrawRay(transform.position, fwd, Color.red); // Can Make any color
if (Physics.Raycast(transform.position, fwd, out hit))
{
print(hit.collider.gameObject.name);
}
See, the reason I'd use collision detection is that as long as your enemy is tagged you'll make contact. Otherwise, your raycast should detect contact and you can still set collision damage or whatever.

Categories