I'm a student and I'm doing a 2D platform game as a project but my programming skills are so bad(That's why I'm trying to do the code by myself) but I'm stuck on that and I don't really have an idea about whats going on. Let me explain.
I've got my Player GameObject with his script playerBehaviour actually working and a BoxCollider2D marked as a Trigger
This Player, also tagged as Player, it's inside a Trigger that belongs the the GameObject LiveZone, who has the DeathZone script below.
using UnityEngine;
using System.Collections;
public class DeathZone : MonoBehaviour {
public PlayerBehaviour playerBehaviour;
void OnTriggerExit2D (Collider2D other) {
if (other.tag == "Player") {
playerBehaviour.respawn = true;
Debug.Log ("Respawn");
}
Debug.Log ("Exit Collider");
}
}
I also tried to do it in a most common way, setting the limits of the "LiveZone" with some triggers to delimitate the area with "DeathZoneTriggers"(that's why the script was called DeathZone at first). But I had the same problem with the OnTriggerEnter2D ().
It looks like it doesn't want to detect my Player leaving or entering this area, as you can see I also called some Debugs, but are not working neither.
To organize information you may also need(or not):
2 GameObjects with Triggers
"Player", who has to exit the zone and "AliveZone", who should detect who's leaving.
Player is tagged as "Player", AliveZone has no tag(don't know if that would mean something)
Any idea?
God I found what was wrong, I set a layer that was ignoring the deafault ones, so it wasn't interacting with that deathzone collider ._.
At least I finally found what was wrong with it, thx anyways for those who read it up and tried to think about a solution! :)
Related
What I am attempting to do is apply the Debugger script to show the message "we hit an obstacle" when my player makes a collision with the white cube, which is tagged as an obstacle.
The problem is: when my player makes contact with the floor/plane it shows "we hit an obstacle" and then the player proceeds to collide with the actual obstacle and it repeats the message.
The white cube is tagged as "obstacle" in the inspector, the player is tagged as "player", and the plane which the game is played on is tagged as "floor."
In my source function, I've made sure to only include the tag labeled as "obstacle" and the only thing in my scene that is tagged as such is my obstacle.
Every time my player makes contact with the floor or any other game object that isn't tagged, it still shows the message.
How do I fix this to only apply this function to a specific tag in unity?
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
void OnCollisionEnter (Collision collisionInfo) {
if (collisionInfo.gameObject.tag == "Obstacle") {
Debug.Log("We hit an obstacle");
}
}
}
Here is the scene I am trying to apply the code to, you can see in console it reads as two messages when there is only supposed to be one, indicating that my function is applying to more than one game object rather than my intended object. You can also see in the top left in the inspector, the Obstacle is tagged as obstacle.
In Unity you usually don't compare tags like strings.
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Obstacle"))
Destroy(other.gameObject);
}
Taken from the docs:
https://docs.unity3d.com/540/Documentation/ScriptReference/GameObject.CompareTag.html
In your case it is collisionInfo.collider.gameObject.CompareTag("Obstacle"). You need the gameobject of the collider which holds the tag.
You should also consider putting your tag names into a static class as static strings from where you can access them and with that eliminate the possibility of typos.
public static class TagNames
{
public static string Obstacle = "Obstacle";
public static string Player = "Player";
}
And use them like that collisionInfo.collider.gameObject.CompareTag(TagNames.Obstacle).
I would try to do:
if (collisionInfo.collider.tag == "Obstacle")
{
Debug.Log("We hit an obstacle");
}
Instead of gameObject, use collider. Also I don't know if you had a semi-colon after the if statement, or if it's just a formatting error, but there's no need for that either.
I am trying to make an attack mechanic for my 2D game. It would work as follows: if the player was standing in front of the enemy and pressed space the enemy would die. To do that I wrote this in the player script:
void Attack()
{
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackArea.position, AttackRange, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
enemy.GetComponent<Enemy_1>().Death();
}
}
And this in the enemy script:
public void Death()
{
Destroy(gameObject);
}
It worked flawlessly but I wanted to make another type of enemy to the game so I added this for the second enemy in the player attack script (I have mention that "GunBoi" is the name of the second enemy script and that I named the second function "Dead()" instead of "Death()" since I thought it wouldn't work if they had the same name)
Collider2D[] hitEnemies2 = Physics2D.OverlapCircleAll(AttackArea.position, AttackRange, EnemyLayers);
foreach (Collider2D enemy2 in hitEnemies2)
{
enemy2.GetComponent<GunBoi>().Dead();
}
and this in the second enemy script:
public void Dead()
{
Destroy(gameObject);
}
but whenever I try to attack the second enemy nothing happens. When I try to attack the first enemy it does work and the enemy dies. Does anyone know why this is happening?
About your problem: your code is in order. Check if the script have been assigned to the enemy prefab.
Now, a recommendation. If you follow it, your problem may be solved.
You said that you created a new script for the new enemy but they both share one same mechanics: the Death() function (and, as long as they are both enemies, i belive they will share a lot of other mechanics like HP, damage, and other traditional stuff).
In this case, i think that the best solution is to the GunBoi's script be inherited from the common enemy's one.
Replicate a function that do exactly the same thing but have a (not very) different name is a bad practice. If you decide to create a third enemy, you will have to create a third function to destroy it, but again, with a different name.
Multiple things could be wrong, but at first sight I would at least verify those two:
are the GunBoi on the good layer
Do they have the GunBoi component
We lack too much information to help you further than this.
But honestly you should try to refactor this by having both enemy type have a generic enemy component. There is no reason why should would have to do the collision logic twice. You want to have to write as less code as possible. With your approach you will have to do this for each new enemy type which is both problematic and error prone.
Hey StackOverflow community, I am making my very first game and I've run into a problem. The game is about a ball dodging obstacles in order to reach the end of a level. So my issue is that I want to implement a "Woosh" sound whenever the ball passes an obstacle. I have created an invisible object which is supposed to execute the "Woosh" sound whenever the ball passes the invisible object.
These are the settings on the "invisible" object:
If you look at the image you can see that there is a "Woosh" script which contains these lines of code:
using UnityEngine;
public class Woosh : MonoBehaviour
{
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Player")
{
FindObjectOfType<AudioManager>().Play("Woosh");
}
}
}
This code is supposed to make the invisible object play the "Woosh" audio whenever it collides with the Player. However, when I try it out in game, the audio never gets played when I pass the invisible object.
For your information, I do have an audio manager, which contains all my sounds that I have implemented so far. It can be seen here:
Note: All the other sounds work, but not the "Woosh" sound.
Any help is appreciated!
Thanks in advance,
E.W
Comments aren't sufficient.
What I'm trying to tell you is that you can't just automatically assume that the problem is with the "Woosh" sound. That's just one of the things that can go wrong. You have this code:
public class Woosh : MonoBehaviour
{
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Player")
{
FindObjectOfType<AudioManager>().Play("Woosh");
}
}
}
Your expectation is that when OnCollisionEnter is called, the "Woosh" sound will be played. You say the sound isn't playing, so you have to figure out what's wrong. This is what I would check:
Can you make the "Woosh" sound play somewhere else? You should be able to add code to your program to make the "Woosh" sound play. Maybe replace code that plays "ShatterSmall" with "Woosh". If the sound doesn't play there, then there's probably something wrong with the "Woosh" sound, and you need to fix it. If the sound does play there, then there's some other problem.
If "Woosh" plays in other places, but not in this code, then you have to check to see if the code is even being executed. If you're running this code in your debugger, put a breakpoint on the OnCollisionEnter method to see if it gets called. If it doesn't get called, then the problem is somewhere else. If you don't have a debugger, then you can output some kind of message like "Hey, I got here!" to tell you that the OnCollisionEnter function actually was called.
If you're getting to OnCollisionEnter, then you need to check to see if collisionInfo.collider.tag does indeed contain the value "Player". Again, use some kind of output function to tell you what is in that variable.
If collisionInfo.collider.tag == "Player", then check to see if the call to FindObjectOfType<AudioManager> returns the expected value.
You can break up your code:
var mgr = FindObjectOfType<AudioManager>();
if (mgr == null)
{
// some error here. Maybe throw an exception.
}
else
{
// Make sure (somehow) that it's really the object you wanted
}
mgr.Play("Woosh");
If the above tells you that you're getting the right object, then perhaps there's a problem playing the sound. Does Play throw any exceptions?
The point I'm trying to make here is that debugging involves questioning all of your assumptions, and doing tests to see where things are failing. This is best done with a debugger, because it lets you move through your code step-by-step to see exactly what's happening.
If you don't know how to use the debugger, now is the perfect time to learn. It will save you days of debugging.
It won't be making the sound because your collider is a trigger not a collision, so if you disable that box of Is Trigger, the sound will play when you collide with it.
If you want to pass through the collider like a trigger you need to use this functions.
void OnTriggerEnter(Collider other) {}
void OnTriggerStay(Collider other) {}
void OnTriggerExit(Collider other) {}
EDIT:
Also using FindObjectOfType is an expensive function, just make the Audio Manager a Singleton
So in my game, there's a gun that sprays bullets, and I'm trying to make a gameObject destroy on collision with the bullets. The bullets are based off of one gameObject (Capsule). I've tried these two scripts so far:
using UnityEngine;
using System.Collections;
public class whenshot : MonoBehaviour {
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "Bullet")
{
Destroy(col.gameObject);
}
}
}
and:
using UnityEngine;
using System.Collections;
public class whenshot : MonoBehaviour {
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "Bullet")
{
Destroy(this); //the difference between the two is that I changed "col.gameObject" to "this"
}
}
}
I'm shooting the object but it's not disappearing/destroying itself. How can I fix this?
Here's a visual if it helps:
this refers to the object instance of the caller (this is basic OOP), i.e., whenshot, and not gameObject. So the second sample is effectively Destroying the instance of the script from the gameObject it is attached to.
The first script is technically fine, and should work, provided these conditions are met:
Either the projectile (bullet) or the target (or both) have a non-kinematic rigidbody component attached. (Unity docs.)
Both have 3D Collider components.
The name of every single bullet gameObject that collides with the target is exactly "Bullet".
All projectile objects have this script as a component.
Some suggestions
Use prefabs and tags: take your bullet primitive and store it as a prefab. Add a tag to the prefab called "Bullet". Do the same for the target and tag it as "Target". Tag the player as "Player". In the "gunController", set a reference to the bullet prefab and make it Instantiate bullets on whatever trigger you're using. In the bullet's script, use CompareTag("Target") instead of == and Destroy both the target gameObject and this.gameObject.
It seems to me that the above is the behaviour you want. If that is the case, there is no delay between collision and destruction, and hence no need to simulate physics whatsoever. Unless you have some other physics interactions with bullets/targets, mark the one without a rigidbody as a Trigger.
A Strong Suggestion
Go through Unity tutorials.
This is an example from a 2D Game I made a while back, but i think it might help.
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Destroyable")
{
Destroy(other.gameObject);
}
}
I used this to destroy certain blocks when the player would shoot them so many times, just switch them to the 3D Collider and Trigger, but it should do the trick for ya (i hope ^^).
edit: this script should be attached to your bullet prefab
Ok so I figured it out, it's kind of weird but apparently I was making the bullets move too fast... I had to slow down the "Bullet_Forward_Force" float to about 150f to make it work. Thanks to everyone who answered though.
I can't comment so I will make an answer:
You can make the bullet go fast, just set the collision detection to continious dynamic.
It has an almost %100 success rate.
I am working through the Unity tutorials, and am currently on a tutorial called "Space Shooter." Something fishy has happened.
I noticed that the Boundary object, and the asteroid object both disappear when the game begins running. Note, both have colliders, and they are not touching. Their is a script called "DestroyByContact", which essentially destroys the game object whenever the player shoots it.
using UnityEngine;
using System.Collections;
public class DestroyByBoundary : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
if (other.tag == "Boundary")
{
return;
}
Destroy(other.gameObject);
Destroy(gameObject);
}
}
I found that when I delete this script off of my Asteroid gameObject, the game functions normally, and the objects are deleted. Their must be something wrong with the script, but I cannot find out what went wrong.
EDIT: I forgot to place the Boundary object to the tag "Boundary" in Unity. This fixes the problem.
Most likely you have not set or misspelled your boundary's tag Boundary1. See This point in the tutorial video.
This is causing your if (other.tag == "Boundary") to be false so it does not go in to the if block to exit the function early.
P.S.: If you are using Unity 5 you should now use if (other.CompareTag("Boundary")), it was not in Unity 4 when the space shooter tutorial was written and it supposedly has better performance than doing a other.tag == "Boundary" compare. You can see a example of it used in the Roll-A-Ball tutorial which is written in Unity 5. The Roll-A-Ball tutorial also has a example of adding a new custom tag in the Unity 5 UI.
1: Ironically I misspelled Boundary when I first posted this answer.