How do you play audio from another object on trigger in unity - c#

I am making a game in unity and whenever I walk into a box trigger I want it to play audio from another objects audio source in the scene. How would I do that.

Maybe something like this is what you need ?
Remember this code must go on the object that has the box trigger, and don't forget to set the correct parameters for on trigger to work (https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html)
private void OnTriggerEnter(Collider other)
{
if(other.name == "WalkingObject") //can also use other.tag
{
GameObject.Find("ObjectWithAudioSource").GetComponent<AudioSource>();
}
}
you can also store that Audio source in a variable like so
AudioSource audioSource;
private void OnTriggerEnter(Collider other)
{
if(other.name == "YourObject")
{
audioSource = GameObject.Find("ObjectWithAudioSource").GetComponent<AudioSource>();
}
}
Than if you need you can add .Play or whatever you need after it
more on audio source https://docs.unity3d.com/ScriptReference/AudioSource.html
Also if you use OnTriggerEnter(Collider other) you may also need OnTriggerExit(Collider other), Which would stop the trigger executing (if you need it)
(https://docs.unity3d.com/ScriptReference/Collider.OnTriggerExit.html)

Related

Unity how to check what object triggered a trigger

I am in the middle of creating a simple 3d platformer in unity and i'm trying to make it so if you are in a certain radius and you hit the "f" key the enemy will disappear. the way i'm checking to make sure the enemy is close enough to be attacked is to have trigger sphere and when its triggered and you press "f" the enemy will be removed. i'm currently trying to see what collided with the trigger but i cant figure it out. here is my current code
using UnityEngine;
public class PlayerCombat : MonoBehaviour
{
public GameObject Enemy1;
public GameObject Enemy2;
public GameObject Enemy3;
public GameObject Enemy4;
// Update is called once per frame
void OnTriggerEnter (Trigger triggerInfo)
{
if (triggerInfo.collider.tag == "Enemy" & Input.GetKey("f"))
{
if (triggerInfo.collider.name == Enemy)
{
Enemy1.SetActive(false);
}
}
}
}
The signature is and has always been OnTriggerEnter(Collider) otherwise that message method will not be recognized by Unity and not get called at all!
And then you already have the according Collider ... what else do you need?
public class PlayerCombat : MonoBehaviour
{
// There is no need to know the enemy references beforehand at all
// you will get all required references from the Collider parameter of OnTriggerEnter itself
// I personally would however expose these two settings to the Inspector to be more flexible
// this way you can adjust these two settings within Unity without having to touch your code
public string listenToTag = "Enemy";
public KeyCode listenToKey = KeyCode.F;
// The signature has to be this otherwise the message method is never invoked at all
private void OnTriggerEnter (Collider other)
{
// Rather use "CompareTag" instead of `==` since the latter will silently fail
// for typos and nonexistent tags while "CompareTag" shows an error which is good for your debugging
// And in general you want to use the logical "&&" instead of the bitwise operator "&" for bools
if (other.CompareTag(listenToTag) && Input.GetKey(listenToKey))
{
// simply set the object you collide with inactive
other.gameObject.SetActive(false);
}
}
}
Finally just make sure that all your enemy instances actually have the tag Enemy
First, I'm pretty sure OnTriggerEnter takes a Collider as its parameter, no? https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
You can get the name of the collided object like so
//Upon collision with another GameObject,
private void OnTriggerEnter(Collider other)
{
Debug.Log($"collided with {other.gameObject.name}");
//you can check for specific components too
MyComponent myComponent = other.GetComponent<MyComponent>();
if (myComponent != null) {
// do something if it has that component on it!
}
}

I am having issues with coding a game of tag

So I am trying to make my first game using Unity and c#. I want my game to be a simple game of tag like I used to play when I was younger. I have tried using "OnCollisionEnter" and I was able to get that to change a counter that gave a bool a label. I realized that while this may work for tagging someone it does not help with other people tagging you. And tips on how I can make my code more like a "Tag Manager"?My current progress
you can have a Taggable.cs like this, not sure if this is even correct syntax, I don't care to actually write it out and test
class Taggable : MonoBehaviour {
bool it;
private void OnCollisionEnter(Collision collision) {
var other = collision.collider.GetComponent<Taggable>();
if(other != null) {
if(it) {
other.it = true;
it = false;
}else if(other.it) {
it = true;
other.it = false;
}
}
}
}
You could implement the logic such that your script checks to see if you are the tagger using Unity's tags property. Then, you could switch the tags of both the players, once you check if the collided object is a player.
Below is the code I suggest you use. I would personally use OnTriggerEnter to have more clearer logic between collider and player. Make sure to have a collider object and a Rigidbody on all players within the scene for the function to be called, and attach your script onto every player within the scene.
private void OnTriggerEnter (Collider col) {
// if you are the tagger
if (gameObject.tag == "Tagger") {
// and if the collided object is a regular player
if (col.tag == "Player") {
// the player is now a tagger
col.tag = "Tagger";
// depending on if you want to buildup taggers or switch them around,
// the below assignment would vary
gameObject.tag = "Player";
}
}
}

How to fix "Can't Play a Disabled Audio Source"?

I am trying to add a sound into my game that whenever the player moves over a certain space it plays a crunch sound. I have created the AudioSource file and a .OGG file for the sound.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpaceBlue : MonoBehaviour
{
public Transform spaceNext;
public AudioSource stepOnObject;
public AudioClip stepOnSound;
private void Start()
{
stepOnObject.clip = stepOnSound;
stepOnObject.enabled = true;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
stepOnObject.Play();
if (BoardScript.diceValue > 0)
{
BoardScript.diceValue -= 1;
Debug.Log("The dice are now " +BoardScript.diceValue);
other.transform.LookAt(spaceNext);
}
}
}
}
I have included the source and clip to my game object and i have tried it both with and without "Play on wake" selected.
Whenever the play walks over the player walks over the object i get a warning in the unity engine saying that the source is disabled.
Any help is appreciated :)
I had a similar problem and I fixed it by changing the location of the Play() call to after calling Destroy(GameObject). I would recommend trying moving the call to Play() to the end of the function, or trying Invoke("stepOnObject.Play", 0.5f); to ensure it gets called.
Otherwise, make sure its checkbox is ticked, and that the AudioSource actually has a AudioClip attached.
If you have any piece of code in some other script that Destroys this game object or makes SetActive false, then the best way to solve this problem will be to delay that piece of code by some time using a Coroutine.

Cannot generate sound when moving method to another class

So for starters, I wish to say that the code below works. But its not structured how I want it to:
public AudioClip pickup;
void OnTriggerEnter(Collider collider)
{
//Trigger for pickups
if (collider.gameObject.CompareTag("Pickup"))
{
AudioSource audio = GetComponent<AudioSource>();
audio.PlayOneShot(pickup);
}
}
But I want to split the class into two and have the player controller (part of it written above) be used to call a function from a new class called 'LevelClass' which will house the method for pickup like so:
public void collidePickup(Collider collider)
{
collider.gameObject.SetActive(false);
AudioSource audio = GetComponent<AudioSource>();
audio.PlayOneShot(pickup);
}
and have player controller call the function like so:
level.collidePickup(collider);
I also linked the sound file with the script so that it would have a sound to play on. From testing, I determined that the problem is being caused in the AudioSource section as its not finding an audio source to work with. Is there something i can do so that i would be able to use an instance of audiosource within the levelclass rather than in the playercontroller?
You should be able to pass a reference to your audio source into the function like this.
public void collidePickup(Collider collider,ref AudioSource audio)
{
collider.gameObject.SetActive(false)
audio.PlayOneShot(pickup);
}
Then you just need to pass the AudioSource to he function when you call it.
You should know, that every AudioSource emits sound according to it's position and uses Doppler effect parameters with it's rigidbody relative velocity.
Also note that every AudioSource can play exactly one clip at a time.
One of the solutons is to create a new GameObject with AudioSource on it (either from prefab on the your audio manager object or from code) for every sound that you want to play in your game, and immediately Destroy it with timeout equal to audio length.
public void collidePickup(Collider collider)
{
collider.gameObject.SetActive(false);
PlaySoundAt(pickup, collider.transform.position);
}
private static void PlaySoundAt(AudioClip sound, Vector3 position)
{
var go = new GameObject("PickupSound");
go.transform.position = position;
var source = go.AddComponent<AudioSource>();
source.PlayOneShot(sound);
Destroy(source, sound.length);
}

Detect Collision for an instantly refreshed object

so i have an old code for a "Connect4" game it was written years ago, now i am having a big problem getting it results and rebuild them for a unity3D project.
the problem is that every gameObject (i've managed to instanciate in the scene) is, meant to be destroyed and reinstantiated every frame (and i have the feeling that is really more that a frame time); wanting to get the color of each gameobject in time seem to be really challenging, i am supposed now to not enter the code created i am only supposed to get the information from what i get as graphical results.
so now i have a board of boxes having a grid disposition that changes colors according to the player turns (red for the cp and yellow for the plyer).
i created a fixed boxes having colliders and wanted to get the game objects colliding with it everyframe but i failed .
PS: i tested this code and every solution i found in this community hope to find somehelp, thank you.
using UnityEngine;
using System.Collections;
public class SelectorCode : MonoBehaviour
{
public Collision other;
public GameObject GO;
void OnTriggerEnter(Collider other)
{
GO = other.gameObject;
}
void OnTriggerStay(Collider other)
{
GO = other.gameObject;
}
void OnTriggerExit(Collider other)
{
GO = other.gameObject;
}
void Update()
{
GO = this.other.gameObject;
}
}
First make sure the object to which the SelectorCode component is attached has a trigger collider (property "Is Trigger" is checked).
Next you'll get an error in the Updatemethod with GO = this.other.gameObject; since other is never assigned. I think you should remove that line.
Finally, in OnTriggerExit you put in GO the object that is leaving your collider, that doesn't make sense, you should probably assign GO to null at this point :
void OnTriggerExit(Collider other)
{
if (other.gameObject == GO)
{
GO = null;
}
}

Categories