Collision not being detected Unity2D - unity3d

I am trying to make an object that upon collision with another object, gets destroyed. I have also used Debug.Log and it turns out that the collision is not even detected. Here is the code
public class Enemy_1 : MonoBehaviour
{
public void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag.Equals ("AttackArea"))
{
Destroy(gameObject);
}
}
}

Welcome to the community!
To allow us better to understand the context, next time provide some inspector screenshots of these objects. It will be easier for both of us! 😋
Now, for your problem, there might be one (or combination) of few reasons:
None of the two objects have Rigidbody2D attached. For collision to be detected, at least one of two must be a Rigidbody2D. ...
Other object is not tagged as AttackArea. Thus, tag equation returns false. ...
Other object's collider is marked as is trigger. In this case OnTriggerEnter2D(Collider2D) is called instead of OnCollisionEnter2D(Collision2D).
Check for each of these and let us know! 😉

Related

I'm trying to get the Debug.Log to detect a collision when I bring two objects together

When I put this script into the object, a cube, it does not register the platform it hits beneath when I make the gameObject the platform. I'm trying to get the two objects to detect collision between each other but it does not seem to work. Neither objects are trigger checked in the Box Colliders. The cube has a rigid body with gravity checked but the platform does not. This is a 3D game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Collision : MonoBehaviour
{
public Transform gameObject;
void onCollisionEnter(Collision col)
{
if (col.gameObject);
{
Debug.Log("Yes");
}
}
}
As Sven Viking already said, you have to change the syntax from onCollisionEnter to OnCollision enter. Also, let's take a look at your logic:
You want to check that, if your cube object collides with another object, and if that object is the same as the one you're referencing, you want to see a log of that in your console. Currently, however, you're asking for something else.
First of all, your platform is not stored as a gameObject, it's stored as a Transform. Those two are different things, the Transform stores the position/rotation/scale of an object, while 'GameObject' is the entire object, includng its Transform. Also, you named your variable gameObject, which you should never do - Never name variables with the same name as existing elements.
'col' represents the collision. col.gameObject is the gameObject of that collision. There's no logic demanded there. You're just making a reference. What you want, instead, is compare the gameObject of the collision with your referenced gameObject(the platform) and, if both of them are the same, then you can proceed. Therefore, what you want is:
public class CollisionScript : MonoBehaviour
{
public GameObject platform;
void OnCollisionEnter(Collision col)
{
if (col.gameObject == platform);
{
Debug.Log("Yes");
}
}
}
Let me know if this solves your problem.
EDIT: I see now you also named your class 'Collision', which I'm pretty sure would break things, as Collision is already a class within Unity(you can check that looking at "Collision col", that indicates there is a class named Collision). You should change both the class name on the top of the script and the file name to reflect that change.

In Unity how can I set a value to property while initializing a prefab with Instantiate() method like OOP constructor with parameters?

I am a newbie in Unity and game development. I want to make a mobile stack jump game with primitives. I have a player in the center of the screen. The enemy is approaching the player from the right and left of the screen. The player tries to sit on the enemy by jumping as in Mario Game. If the enemy hits the player from the side, the game is over. I create enemies with a SpawnMan. There is a prefab for an enemy game object. SpawnMan creates them at certain time intervals with the Instantiate() method. I want to store data on whether the enemy is approaching from right or left. I even want to store this information by creating an enum type. In summary, I want to have enemy objects with the left and the right types. How do I set this property (left enemy or right enemy) when calling the Instantiate() method in SpawnMan as in OOP constructor with parameters.
enum EnemyType
{
Left,
Right
}
// ...
Instantiate(enemyPrefab(EnemyType.Left), spawnPos, enemyPrefab.transform.rotation);
Assign a GameObject while instantiating first :
GameObject enemy1 = Instantiate(...)
Then, we can use the player transform and the enemy transform vectors to get a direction (+ value and a minus value)?
As Chandradhar said, addition to that, you can use Mathf.Sign(player.position.x- enemy.position.x); to see if the enemy comes from the left or the right of the player.
You can't really pass it in exactly that way, as Instantiate doesn't call a constructor on the instantiated prefab's scripts. Or I guess enemyPrefab could be a method that returns an actual prefab object with set script values, but that would be a somewhat odd way to get what you want.
But presumably you just want the enemy object to have that information about left/right, in that case the easiest would be to get the attached script and then assign the left/right property. So you would add something like this to your enemy script (the one that is attached to enemy prefab)
public class MyEnemyScript : MonoBehaviour
{
public EnemyType Type;
... your enemy code here...
}
And then use it like that:
var enemyGameObj = Instantiate(enemyPrefab, spawnPos, enemyPrefab.transform.rotation);
enemyGameObj.GetComponent<MyEnemyScript>().Type = EnemyType.Left;
Note that this is not really good practice, as GetComponent is an expensive call, but then again neither is Instantiating all those enemies - it would be nicer to use pooling.
I'm assuming an enum for left and right is overkill, but if you have some design reason that the enemies need to do have some special logic depending on what side they're on, you can still handle that in a simpler fashion.
In your MyEnemyScript(), you have Awake() and OnEnable() methods that will be automatically called by Unity just like Start and Update. In one of them (use OnEnable if you use object pooling), put something like this:
public EnemyType type;
private void Awake()
{
if (transform.position.x > PlayerInfo.playerPosition.x)
type = EnemyType.right;
else
type = EnemyType.left;
}
Now you can just spawn enemies as normal without thinking about it. PlayerInfo can be a static class or a singleton or however you prefer making that information available.
Then in your update loop, just have two logic paths (which I assume is similar to what you're doing anyway).
private void Update()
{
if(type = EnemyType.left)
//do left enemy stuff
else
//do right enemy stuff
}

Recognizing a specific objects collision in Unity

I've been trying to figure out how to detect collision to make a simple combat system, but the commands aren't returning what I want them too. What I'm using right now (in the unity engine):
using UnityEngine;
public class swordDetect : MonoBehaviour
{
void OnCollisionEnter(UnityEngine.Collision CollisionInfo)
{
if (CollisionInfo.gameObject.name == "swordCollide")
{
Debug.Log("it work again");
}
}
}
This isn't returning anything, and its attached to a rock that I've been using to test it.
The swordCollide object is attached to the players sword, but nothing happens when it collides with the rock.
Make sure that your Gameobject has a collider on it, which is not set to Trigger (because then it can't receive collision, but will only trigger). I would always rather tag my Gameobjects and check for the tag than for the name, because it is less error prone. If the colliding Gameobject is a Trigger, you need to check
private void OnTriggerEnter(Collider other){}
Best watch the Unity tutorials about collision https://unity3d.com/learn/tutorials/topics/physics/colliders?playlist=17120
and check the documentation https://docs.unity3d.com/ScriptReference/Collider.html
Both are easy to understand and go with some sample code

Correct way to connect an instance of a class to a GameObject mesh

I have a model with an animator; and a controller script to make it move, then I created a simple class called "TheEntity", which hold a name, and an int for the energy. When the time goes by, the energy goes down, so the mesh walk around or perform animations at random.
public class TheEntity()
{
public string name;
public int energy;
public TheEntity()
{
// make a random name
name = "joe"+ rnd.next(1,1000).toString();
energy = rnd.next(20, 100);
}
}
When the energy value goes to 0, the mesh "goes to sleep", and regenerate again in a certain amount of time.
If I have a list of TheEntity instances, as it would be if I have a list of NPC, what would be the correct way to assign a mesh to each entity class in the list?
Should I have a script on the mesh, that has a reference to a TheEntity class. and assign it at runtime when I load the mesh prefab?
Or should I put the whole "TheEntity" class script on the mesh, and save it as prefab, so every time that I load the prefab, I will have a mesh with a related TheEntity instance directly?
"Things" in the Unity scene are GameObject , that's all there is to it.
Your class must be a MonoBehaviour to be on a game object.
In Unity, everything is a MonoBehaviour (a Component). There is, quite literally, nothing else whatsoever in Unity.
(Of course, you may have some "raw" non-Unity classes for things like say math calculations, but that's irrelevant.)
It's just that simple.
public Class Entity:Monobehaviour
{
}
attach that to an empty game object. Add the models (meshes) .. or whatever you want. Add sound effects, add anything.
Regarding "changing the mesh", no problem.
Do that in a routine in Entity, if you like.
public Class Entity:Monobehaviour
{
public void ChooseRandomMesh()
{
}
public void ChooseRandomColorPattern()
{
}
public void RunForTheHills()
{
}
public void AttackHero()
{
}
}
If you prefer, write a Component which does nothing other than randomly change the mesh.
public Class Entity:Monobehaviour
{
public void RandomizeEntity()
{
}
public void ChooseRandomColorPattern()
{
}
}
.. and attach that script to the game object, also.
In Unity, everything is a MonoBehaviour (a Component), it's that simple.
Regarding making it a prefab, if you want to, sure do that. Read any of thousands of tutorials on prefabs.
There's a critical comment you made in your comments below:
"Also the entity class is not MonoBehaviour..."
Here's an incredibly critical point in understanding Unity:
1) You're quite right that your "model" or "AI" or "database connection" sort of has "nothing to do" with unity game objects. (They of course don't have a "position" or "mass!" or anything, right?!)
HOWEVER HOWEVER HOWEVER HOWEVER HOWEVER HOWEVER HOWEVER HOWEVER HOWEVER
2) In Unity unless a class is a MonoBehaviour: you can't do anything with it/ You can't even access the run loop, it's a total nonstarter.
THUS THUS THUS THUS THUS THUS THUS THUS THUS THUS THUS THUS THUS THUS
3) In Unity all the stuff like that, IS IN FACT a MonoBehaviour AND YOU SIMPLY sit it on an empty game object. (Usually the name in the Heirarchy starts with underscore, say, so you know it's "not really" a conventional game object.)
The simple bottom line is in your preload scene (you must have one in 100% of projects) you have all your "AI" and "model" and "database" stuff, just sitting on one or more "pretend" markers (marker == otherwise empty game object).
Bottom line, when you say below "your model is not a MonoBehaviour" that is wrong. It will have to be a MonoBehaviour (if you think about it, it's absolutely inevitable you'll need to access the runloop, if nothing else) ... just make it a MonoBehaviour and put it on a marker, almost certainly in your preload.
I hope it makes sense. Essay on the topic.

How do I detect collision with a child of a prefab

I've started studying Unity and decided to do some practice. So, I thought that it would be awesome to develope "Flappy Bird" as an experiment. But I've faced with the problem. You know, when you fly between pipes, you earn a point. To do that I made a prefab with two pipes and an empty game object (trigger) between them to detect collision with it. But when I call OnCollisionEnter2D method, it detects collision with a prefab, not with the trigger or pipes in it. Could you help me? How do I detect collision with a child of a prefab?
like what Uri Popov answered, use OnTriggerEnter2D() there are several points you need to do :
1. Put the OnTriggerEnter2D() Script on your empty game object, and don't forget to attached collider2D on your empty object.
2. make sure isTrigger checked in collider2D option
3. also make sure your player has tag, you can make the tag your own, in this example i give "Player" tag to my player game object
4. the example script(i tired it and worked)
public class YourTriggerScript: MonoBehaviour {
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.GetComponent<Collider2D>().tag == "Player")
{
Debug.Log ("Collided");
// do something or you can + your point here
}
}
}
Hope it helped you
if your collider is marked as a Trigger you should use OnTriggerEnter2D().