I'm trying to play a sound when a GameObject is destroyed. However the sound won't play. I've tried it this way and by assigning the audio clip to a variable but neither seem to work. If I set the sound to play on awake it plays when the GameObject spawns, so I know the sound clip works - but it won't play when it is destroyed.
using UnityEngine;
using System.Collections;
public class DestroyByContact : MonoBehaviour {
public GameObject explosion;
public GameObject explosion02;
public GameObject explosionShot;
public int scoreValue;
public GameController gameController;
public int health;
public AudioClip explosionSound01;
void start () {
}
void Update () {
if (health <= 0) {
this.gameObject.GetComponent<AudioSource> ().Play ();
Instantiate(explosion, transform.position, transform.rotation);
Instantiate(explosion02, transform.position, transform.rotation);
GameObject gc = GameObject.Find ("GameController");
GameController gcs = gc.GetComponent<GameController> ();
gcs.AddScore (scoreValue);
Destroy(gameObject);
}
if (this.gameObject.tag == "Asteroid") {
if (this.gameObject.transform.position.x < -16) {
Destroy (gameObject);
Destroy (transform.parent.gameObject);
}
}
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "Boundary") {
return;
}
if (other.tag == "Asteroid") {
return;
}
if (other.tag == "Player") {
Instantiate(explosion, transform.position, transform.rotation);
Instantiate(explosion02, transform.position, transform.rotation);
Destroy (gameObject);
}
if (other.tag == "Bullet") {
Instantiate(explosionShot, transform.position, transform.rotation);
other.gameObject.GetComponent<AudioSource> ().Play ();
health -= 10;
GameObject gc = GameObject.Find ("GameController");
GameController gcs = gc.GetComponent<GameController> ();
gcs.AddScore (10);
Destroy (other.gameObject);
}
}
}
Cutting this down to the essential lines, we're left with just two:
this.gameObject.GetComponent<AudioSource>().Play();
Destroy(gameObject);
Destroying a GameObject will also destroy any components attached to it. You've told the AudioSource to play, and then immediately destroyed it. Once it has been destroyed, it no longer exists and therefore cannot play any sound.
To avoid this, you can create a separate GameObject to contain an AudioSource that will play the sound, then destroy that once it's finished.
Unity actually has a helper function, AudioSource.PlayOneShot, to do exactly that:
[RequireComponent(typeof(AudioSource))]
public class ExampleClass : MonoBehaviour {
public AudioClip impact;
AudioSource audio;
void Start() {
audio = GetComponent<AudioSource>();
}
void OnCollisionEnter() {
audio.PlayOneShot(impact, 0.7F);
}
}
If you need to have more control, you could create and manage your own GameObject, perhaps by instantiating a prefab:
public class ExampleTwoClass : MonoBehaviour {
public AudioSource audioPrefab;
void OnCollisionEnter() {
GameObject clone = Instantiate(audioPrefab, transform.position, transform.rotation) as GameObject;
AudioSource cloneAudio = clone.GetComponent<AudioSource>();
cloneAudio.play();
//destroy clone once audio finishes
Destroy(clone, cloneAudio.clip.length + 0.1f);
}
}
Well, the game object you're trying to play the sound on is being destroyed, so the audio source is going to be destroyed along with it.
You'll have to create an empty game object for the audio source to be attached to, placed at the destroyed object's position, and destroy that one after the sound effect finishes. Or another, similar solution, depending on your exact needs (Destroy has a bit of overhead, so using a pooling system changes the answer).
You can easily change your script to work, you just need to use Destroy(GameObject,float) method instead of Destroy(Gameobject).
This is a handy solution.
if (health <= 0) {
this.gameObject.GetComponent<AudioSource> ().Play ();
Instantiate(explosion, transform.position, transform.rotation);
Instantiate(explosion02, transform.position, transform.rotation);
GameObject gc = GameObject.Find ("GameController");
GameController gcs = gc.GetComponent<GameController> ();
gcs.AddScore (scoreValue);
Destroy(gameObject,1f);// here use time parameter.
}
assign the the depends on your music's time if your exploit sound 1 sec then assign time Destroy(gameObject,1.25f).
You can use this static method:
AudioSource.PlayClipAtPoint(soundClip, Camera.main.transform.position);
Destroy(gameObject);
To set the sound clip from the inspector, add a member to the class:
[SerializeField]
private AudioClip soundClip;
Related
So i have this little particlesystem attached on my player so if he dies he explodes. But i cant simply attach the particlesystem under the player because if i destroy my player the childs of the gameobjects get destroyed as well. The animation runs if he dies but not on his current spot so some ideas for that? Maybe to transform the position to the current position of the player while he dies?
Here my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerdeath : MonoBehaviour
{
public ParticleSystem death_explosion;
// Start is called before the first frame update
void Start()
{
death_explosion.Stop();
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "deathcube")
Destroy(gameObject);
Debug.Log("collision detected");
death_explosion.Play();
}
}
What you could do is create a prefab of the particle object and reference it inside your script like so:
public ParticleSystem death_explosion_Prefab;
And instead of attaching it to the Player as a child, instantiate it on collision:
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "deathcube")
{
Debug.Log("collision detected");
Instantiate(death_explosion_Prefab, gameObject.transform.position, Quaternion.identity);
Destroy(gameObject);
}
}
got it :) --> add death_explosion.transform.position = GameObject.Find("player").transform.position;
I have a game with a player and an enemy.
I also have a particle system for when the player dies, like an explosion.
I have made this particle system a prefab so I can use it multiple times per level as someone might die a lot.
So in my enemy.cs script, attached to my enemy, I have:
public GameObject deathParticle;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "Player" && !player.dead){
player.dead = true;
Instantiate(deathParticle, player.transform.position, player.transform.rotation);
player.animator.SetTrigger("Death");
}
}
So this plays my particle system when the player gets killed by an enemy. Now on my player script, I have this. This specific function gets played after the death animation:
public void RespawnPlayer()
{
Rigidbody2D playerBody = GetComponent<Rigidbody2D>();
playerBody.transform.position = spawnLocation.transform.position;
dead = false;
animator.Play("Idle");
Enemy enemy = FindObjectOfType<Enemy>();
Destroy(enemy.deathParticle);
}
This respawns the player like normal but in my project each time I die I have a death (clone) object which I don't want. The last 2 lines are meant to delete this but it doesn't.
I have also tried this which didn't work:
Enemy enemy = FindObjectOfType<Enemy>();
ParticleSystem deathParticles = enemy.GetComponent<ParticleSystem>();
Destroy(deathParticles);
There is no need to Instantiate and Destroy the death particle, that will create a lot of overhead, you can simply replay it when you want it to start and stop it, when you dont need it
ParticleSystem deathParticleSystem;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticleSystem.time = 0;
deathParticleSystem.Play();
}
public void RespawnPlayer()
{
//rest of the code
deathParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
or you can enable and disable the gameObject associated with your particle prefab
public GameObject deathParticlePrefab;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticlePrefab.SetActive(true);
}
public void RespawnPlayer()
{
//rest of the code
deathParticlePrefab.SetActive(false);
}
You could always create a new script and assign it to the prefab that destroys it after a certain amount of time:
using UnityEngine;
using System.Collections;
public class destroyOverTime : MonoBehaviour {
public float lifeTime;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
lifeTime -= Time.deltaTime;
if(lifeTime <= 0f)
{
Destroy(gameObject);
}
}
}
So in this case you would assign this to your deathParticle. This script is useful in a multitude of scenarios if you're instantiating objects so that you don't have a load of unnecessary objects.
i have a game like the Rooltheball in unitys tutorials, and i want to play a sound when my ball hits the peaks, the thing is that i already tried everything, i basicly added a audioListener in my mainCamera, and added a audioSource and audioClip in the gameobject i want to detect the trigger, here is the code i did:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class colisaoPicos : MonoBehaviour {
Manager gameManager;
public AudioClip impact;
private AudioSource audio;
void Start()
{
gameManager = GameObject.Find ("GameController").GetComponent<Manager> ();
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
AudioSource.PlayClipAtPoint (impact, transform.position);
gameManager.LifeDown();
}
}
}
One solution would be to add an audiosource on the ball, and make it play the clip each time you enter the trigger.
Just make the audio variable public, and drag the AudioSource into it in the inspector.
Second, but in my book, and uglier solution would be to make a gameobject spesifically for that purpose. Then put the gameobject at the spot, and play the sound.
But, as programmer said, you should check the trigger. Remember, one of the Game Objects has to contain a Rigidbody. (Is Kinematic can be active tho)
As my experience, the following code is always working:
public AudioSource soundToPlay;
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
soundToPlay.Play ();
}
}
Do not try to use playOneShot, or play clip. Error happens.
Try this it will play the sound once if Trigger function is working in your case and do add AudioListener component with the trigger gameobject.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class colisaoPicos : MonoBehaviour {
Manager gameManager;
public AudioClip impact;
private AudioSource audio;
void Start()
{
audio=GetComponent<AudioSource>();
gameManager = GameObject.Find ("GameController").GetComponent<Manager();
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
audio.PlayOneShoot(impact);
gameManager.LifeDown();
}
}
}
I'm having trouble with sound triggering. The script below is attached to a coin prefab object with an AudioSource component and sound clip attached. Everything is working except there is no sound. What am I doing wrong?
using UnityEngine;
using System.Collections;
public class CoinPickup : MonoBehaviour {
void OnTriggerEnter(Collider other) // other is a reference to the other trigger collider we have touched
{
if (other.gameObject.CompareTag ("Player"))
{
gameObject.SetActive (false);
Debug.Log ("Sound should trigger here.");
coinSound = gameObject.GetComponent<AudioSource>();
coinSound.Play();
}
}
}
Might not be what you are looking for, but I usually instantiate sounds like this: (I have no access to Unity at the moment, so bare with)
using UnityEngine;
using System.Collections;
public class CoinPickup : MonoBehaviour
{
public AudioSource coinSound; //set in inspector
void OnTriggerEnter(Collider other) // other is a reference to the other trigger collider we have touched
{
if (other.gameObject.tag == "Player") //or you could do other.gameObject.name == "Player"
{
coinSound.Play(); //play the coin sound
Destroy(gameobject); // destroy our coin, it has been picked up!
}
}
}
I'm not sure, but I don't think you can play sounds on a de-activated gameObject.
This way should play the sound when your player comes into contact with your coin, at which point it will play your sound, and the coin will then destroy itself.
Hope this helps :)
Switch the script. So instead of triggering when the coin hits the player, make it so that when the player hits the coin and then attach that script to the player.
Also, make it an AudioClip and add an AudioSource to the Player
public AudioClip coinSound; //set in inspector
void OnTriggerEnter(Collider other) // other is a reference to the other trigger collider we have touched
{
if (other.gameObject.tag == "Coin")
{
coinSound.Play(); //play the coin sound
}
}
I acquired this snippit of code and it instantiates a particle system prefab. The problem I'm having is the clones do not get destroyed after the 5 second delay. Any advice is appreciated.
private ParticleSystem instantiate(ParticleSystem prefab, Vector3 position)
{
ParticleSystem newParticleSystem = Instantiate(
prefab,
position,
Quaternion.identity
) as ParticleSystem;
if(newParticleSystem.gameObject != null)
{
Destroy(
newParticleSystem.gameObject,
newParticleSystem.startLifetime
);
}
return newParticleSystem;
}
Your code relies on whateveris called ParticleSystem to keep track of when to Destroy the system. What I would do is this:
private ParticleSystem instantiate(ParticleSystem prefab, Vector3 position)
{
ParticleSystem newParticleSystem = Instantiate(
prefab,
position,
Quaternion.identity
) as ParticleSystem;
newParticalSystem.AddComponent<TimedDestroy>().delay = newParticleSystem.startLifetime;
return newParticleSystem;
}
and then add this script to your project:
using UnityEngine;
public class TimedDestroy : MonoBehaviour
{
public float delay;
void Start()
{
Invoke("destruct",delay);
}
public void destruct()
{
Destroy(gameObject);
}
}