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.
Related
Hi I'm new to coding games and using Unity, when I switch Scenes in unity the objects 100x and the saturation gets weird
Here is my current script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game_End : MonoBehaviour
{
int Pins = 0;
void OnCollisionEnter(Collision collision)
{
Pins += 1;
}
// Update is called once per frame
void Update()
{
if (Pins == 4)
{
SceneManager.LoadScene("Level 2", LoadSceneMode.Additive);
}
}
}
Welcome to Unity! There are a few issues I can see, so I will try to explain each one. The main issue you are currently having is you are loading a scene on top of itself using the LoadSceneMode.Additive. It is loading the scene Level 2 on top of itself as long as Pins is equal to 4, which I am guessing is every frame.
I would instead put this check inside of the OnCollisionEnter as it should only be called once. Your other issue is you are not checking what you are colliding with. You might want to check the object you hit by tag. If you are unfamiliar with tags, you can look at the docs. Adding a tag to your game called Pins and adding it to all of your objects that are pins will help resolve what you are colliding with.
Now to solve the near infinite amount of scenes you are spawning. As I mentioned, it is because your conditional check is in Update, which in Unity is called every frame. With the condition you are currently checking for, if pins is not reset, it will keep loading your scene. As you are also using the Scene.Additive, it will load the new scene on your old scene, so the variable pins will not reset unless you collide with something else. I would recommend changing your code to this example:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game_End : MonoBehaviour
{
int Pins = 0;
void OnCollisionEnter(Collision collision)
{
// we are only checking if the object we hit is tagged as 'Pins' to make sure we hit a pin
if(collision.gameObject.tag == "Pins")
{
// add to the pins
Pins += 1;
// destroy the pin we hit so the player can not hit it twice
Destroy(collision.gameObject);
// check our condition to load the new scene
if(Pins == 4)
{
SceneManager.LoadScene("Level 2");
}
}
}
}
Now that you are only checking if the collision is with an object tagged as Pin, the counter will only go up when you collect a pin. By adding the Destroy, you assure that each pin will only increase the count by 1. And finally, by putting your level check inside of this function, it will only check your condition when it increases the count. My one question is, do you want to use LoadSceneMode.Additive? It loads a scene directly over your current scene. I believe you'd want to load the scene normally so it loads your new scene. Would you mind clarifying how you want to load the new scene a bit more? In my example snippet I removed the additive as I believe you do not want to use it. The docs Unity has for LoadScene use it, so I assume you got it from there.
If you do not understand any of what I said, feel free to ask any questions in the comments. I can tweak the answer as needed to help you understand.
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
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! :)
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 was following a unity tutorial started on Unity 4 but I am on Unity 5, and when I try to use the script seen (https://youtu.be/vwUahWrY9Jg?t=1337) and I try to use it, it gives an error:
Assets/Scripts/DestroyFinishedParticle.cs(18,17): error CS0246: The type or namespace name `Destroy' could not be found. Are you missing a using directive or an assembly reference?
this is the code:
using UnityEngine;
using System.Collections;
public class DestroyFinishedParticle : MonoBehaviour {
private ParticleSystem thisParticleSystem;
// Use this for initialization
void Start () {
thisParticleSystem = GetComponent<ParticleSystem>();
}
// Update is called once per frame
void Update() {
if (thisParticleSystem.isPlaying)
return;
Destroy (GameObject);
}
}
It can be because C# code for unity changed from 4 to 5? what should I change? The problem seems to be in the Update method.
There are couple of issues with this code.
First, you didn't mention to what exactly is it attached too? I assume it attached to the Particle System.
Secondly, use "gameObject", not "GameObject", since GameObject is the name of the class.
Third, I believe there's a much more efficient way to destroy the gameObject without checking every frame whether the particles system has finished or not, maybe set a small timer? or invoke the function with time?
Depending on how your event is set up would depend on the approach to checking if the particles are running. If you can setup a collider to when you walk in, you can trigger an event to know the particles are on. Upon exiting the collider, the particles will shut off.
I'm not 100% on the syntax of return in C# but seems like it should go after you destroy your game object. I think return works in a similar fashion as the break in that aspect.(Especially since you don't seem to be returning any values anyway why do you need it?)