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
Related
I'm doing a mechanic that if you shoot at a specific object it adds ammo, but I tried a lot of things and ammo is not being added when it collides with the object.
Here is the code:
public GlobalAmmo ammo;
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.transform.tag == "Enemy")
{
Destroy(gameObject);
}
if (collision.gameObject.CompareTag("Ammo"))
{
ammo.ammo += 3;
}
}
Edit: sorry!
I already put this code and I put in the images that the "if" is working, so I don't understand why this is not working because the ammo decrease correctly.
I think it must be a very silly mistake, I'm actually doing this project to test everything I'm learning
if (collision.transform.tag == "Ammo")
{
print("Hit!");
ammo.ammo += 3;
}
Does the shooting itself work?
Try to write:
if (collision.gameObject.CompareTag("Ammo"))
{
Debug.Log("Work");
ammo.ammo += 3;
}
If you do not write "Work" on the console, then you have an error somewhere else.
Since your debugging shows that the if is properly executed, I see one main possibility (an easy mistake to make when not used to Unity).
Is that a script you dragged-dropped over 2 different game objects?
You are probably not modifying the proper instance of the GlobalAmmo class (script) . There might be two (or more) GlobalAmmo.
Instead you should refer to only one instance, which is the "source of truth".
For instance, during Init the public GlobalAmmo ammo; should be initialized by fetching the proper script instance if it is on another object etc.
As per your comments, it seems you figured it out! Feel free to add more details if this is not the case.
The Context:
I'm currently creating a melee combo system for my 2D RPG. The first time a player attacks will trigger the first attack animation and if the player chooses to attack a second time, it ill trigger the second attack animation. I got the system to work by calling an attack function that passes a string parameter depending on which animation I need to be played.
So the ComboOrder function will be called every frame to order the animations and once the player presses the "E" key, the Attack function will be called with either "Attack-1" or "Attack-2".
The Problem: The code and animations work fine however, after many changes to other parts of the game I noticed, I get a warning every time I press the "E" key. What I changed was completely unrelated ti this so I don't see a connection from that to the warning.
Parameter" does not exist
Solutions I have tried: I've searched the web for answers, however, none of them fit my issue. It seems that Unity thinks I'm passing the string " which would indicate a syntax error but I've double-checked my code and I can't find anything of sorts. I've also heard that it has been a bug in Unity but they never told how to fix it. Is there anything I can do if that were the case?
Here's the code:
void ComboOrder() {
if (comboIndex == 1)
{
if (Input.GetKeyDown(KeyCode.E)) // Attack Input
{
Attack("Attack-1");
comboIndex++;
}
} else if (comboIndex == 2) {
if (Input.GetKeyDown(KeyCode.E)) // Attack Input
{
Attack("Attack-2");
comboIndex--;
}
}
}
public void Attack(string attack)
{
animator.SetTrigger(attack);
}
And here are the Animator settings for the player:
So after not being able to work on the game for about two weeks, I came back to take a closer look and realized it was what you said, there was an animation event calling the function without passing a parameter and since it was not coded, I never caught it. Thank you to everybody who helped.
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! :)
Ok so I have this coroutine :
IEnumerator ShowCharTraits()
{
while(!hasPlayerChosen)
{
yield return null;
traitPanel.SetActive(true);
}
hasPlayerChosen = false;
traitPanel.SetActive(false);
// Debug.Log("Got called! job done");
}
It's being called like this from the awake method in my GameManager:
players = GameObject.FindGameObjectsWithTag("Player");
foreach (GameObject g in players)
{
ui_Controller.StartShowCharTraits();
g.GetComponent<PlayerToken>().isTurn = false;
}
StartShowCharTraits() is a simple method that does this :
public void StartShowCharTraits()
{
StartCoroutine("ShowCharTraits");
}
Now, I have checked the tags, no null reference exception, actually no errors or warnings are being thrown. If i load the scene in the editor and then play it everything works fine. traitPanel.SetActive(true); get called and my panel shows up. However when I load my scene from another scene using SceneManager.LoadScene(1); the above mentioned line is never reached. Any ideas why this is happening ?
Say you want to have one central place that is "like a singleton" in a Unity project. Example,
SoundEffects
LapTimer
Scores
SocialMediaConnections
All you do is this.
make your script SoundEffects.cs
recall that every Unity project must have a "preload" scene. (it's impossible to not have one)
in the preload scene, have a empty game object called "holder". make sure it is marked "DontDestroyOnLoad"
attach SoundEffects.cs to that holder
you're done.
there's just nothing more to it.
you're finished.
it's "just that simple"
So, any particular script, which happens to be attached to any particular object, in any particular scene, may need to access "SoundEffects"...
To do so, simply do this in Awake:
SoundEffects soundEffects = Object.FindObjectOfType<SoundEffects>();
then just use soundEffects anywhere in that script, for example soundEffects.PlayBoom(13) etc etc.
So in Awake()
Laps laps = Object.FindObjectOfType<Laps>();
Social social = Object.FindObjectOfType<Social>();
AI ai = Object.FindObjectOfType<AI>();
or whatever.
Unity is simple. Incredibly simple. It's just that easy.
write your script, LapTimer.cs or whatever
put it on a holder object in your preload scene (where else could it be?)
there's no "3", that's all there is. It's just that ridiculously simple.
Note that...
In the early days of Unity, someone unfortunately mentioned "singletons" on a QA board somewhere. (You can't have "singletons" in an ECS system, it's meaningless.) At the time, this led to huge discussions about how you can make a "singleton-like thingy" in Unity, which is piling confusion on confusion. Unfortunately from that day to this, you get people learning Unity, who see "singleton" mentioned here and there on the net, and it leads to endless confusion.
Once again, note that the idea of "managers" is just impossibly simple in Unity - explained above. It's trivial. It just couldn't be easier.
Note, above I mention you might want syntactic candy to avoid the incredible chore of typing Laps laps = Object.FindObjectOfType<Laps>();
There are very unfortunately no macros in Unity/c# so you need another way.
All you do is use a "Grid" script http://answers.unity3d.com/answers/1124859/view.html which has been popular for years in Unity.
But honestly, it's so simple to use Scores scores = Object.FindObjectOfType<Scores>(); that I usually just do that nowadays.
Ok how do I explain this. I have a singleton that acts as a data holder. While developing the scene with the game manager I had attached the singleton to the gamemanger object that hold a bunch of scripts. Now when I made the main menu I ofc added my singleton to it so I can carry info to the game scene and because of this my whole game manger object was being deleted. This is the culprit from the DataHolder :
void Awake()
{
if (instance == null)
instance = this;
else if (instance != this)
Destroy(gameObject);//This right here.
DontDestroyOnLoad(gameObject);
}
So I changed that line to Destroy(gameObject.GetComponent(instance.GetType()));
I know this has been asked many times but I have checked as many forums as I can. Here is everything I'm doing:
I have a cube (that in this case is serving as the floor) with the following properties
and I have a "Runner" that is just a cube with the following properties
I froze the z position and rotations because this is a side-scroller.
The onCollisionEnter method for the "Runner" that you can see is attached to the "Runner" object is as follows:
void onCollisionEnter(){
print("Collision Detected");
}
And when I run it, I get bupkis. So. Help please? It seems so simple but I am clearly messing something up.
It is not
void onCollisionEnter()
but as stated in the documentation
void OnCollisionEnter(Collision collision)
So the method is written in full CamelCase and has an argument.