Playing specific sounds when an object is revealed
Playing specific sounds when an object is revealed I have completed a tutorial on how to make a memory card game from a book I got (Unity in Action) everything works great, I can play the game and match all the cards (8 animals) and score points. I can even reset the game and start all over, and all the cards are randomly sorted out.
But I want to go beyond the tutorial and put some sound effects in the game to make it more fun. I get that you can play sounds on mouse clicks and stuff, but I want to play sounds when specific cards are revealed. Duck card appears and you hear a quacking sound.
I think the code I wrote is based off element id's so my first thought was when a card id x is revealed x sound is played, but I have no idea how to approach that idea and put it into a working code.
I'm not sure if I would start a new C# script or add to my existing sceneController script. Any help would be appreciated. Thank you.
This is my scene controller script for the game. I think I would have to add something here.
using UnityEngine;
using System.Collections;
public class SceneController : MonoBehaviour {
public const int gridRows = 4;
public const int gridCols = 4;
public const float offsetX = 4f;
public const float offsetY = 3.85f;
private MemoryCard _firstRevealed;
private MemoryCard _secondRevealed;
private int _score = 0;
public bool CanReveal
{
get
{
return _secondRevealed == null;
}
}
public void CardRevealed(MemoryCard card)
{
if (_firstRevealed == null)
{
_firstRevealed = card;
}
else
{
_secondRevealed = card;
StartCoroutine(CheckMatch());
}
}
[SerializeField]
private TextMesh scoreLabel;
private IEnumerator CheckMatch()
{
if (_firstRevealed.id == _secondRevealed.id)
{
_score++;
scoreLabel.text = "Score: " + _score;
}
else
{
yield return new WaitForSeconds(1f);
_firstRevealed.Unreveal();
_secondRevealed.Unreveal();
}
_firstRevealed = null;
_secondRevealed = null;
}
[SerializeField]
private MemoryCard originalCard;
[SerializeField]
private Sprite[] images;
void Start()
{
Vector3 startPos = originalCard.transform.position;
int[] numbers = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
numbers = ShuffleArray(numbers);
for (int i = 0; i < gridCols; i++)
{
for (int j = 0; j < gridRows; j++)
{
MemoryCard card;
if (i == 0 && j == 0)
{
card = originalCard;
}
else
{
card = Instantiate(originalCard) as MemoryCard;
}
int index = j * gridCols + i;
int id = numbers[index];
card.SetCard(id, images[id]);
float posX = (offsetX * i) + startPos.x;
float posY = -(offsetY * j) + startPos.y;
card.transform.position = new Vector3(posX, posY, startPos.z);
}
}
}
void Update()
{
int[] numbers = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
}
private int[] ShuffleArray (int[] numbers)
{
int[] newArray = numbers.Clone() as int[];
for (int i = 0; i <newArray.Length; i++)
{
int tmp = newArray[i];
int r = Random.Range(i, newArray.Length);
newArray[i] = newArray[r];
newArray[r] = tmp;
}
return newArray;
}
public void Restart()
{
Application.LoadLevel("MEMORY GAME");
}
}
Answer by TBruce · Aug 17, 2016 at 08:24 PM
Here is the way that I would approach this
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
#if UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
#endif
[RequireComponent(typeof(AudioSource), typeof(AudioSource))]
public class SceneController : MonoBehaviour
{
public const int gridRows = 4;
public const int gridCols = 4;
public const float offsetX = 4f;
public const float offsetY = 3.85f;
public List<AudioClip> cardSounds = new List<AudioClip>();
// an AudioSource lets you play sounds
private AudioSource audioSource;
private int maxCardIDValueSize = 16;
private MemoryCard _firstRevealed;
private MemoryCard _secondRevealed;
private int _score = 0;
private List<int> cardIDValues = new List<int>();
public bool CanReveal
{
get { return _secondRevealed == null; }
}
public void CardRevealed(MemoryCard card)
{
if (_firstRevealed == null)
{
_firstRevealed = card;
}
else
{
_secondRevealed = card;
StartCoroutine(CheckMatch());
}
}
[SerializeField]
private TextMesh scoreLabel;
private IEnumerator CheckMatch()
{
if (_firstRevealed.id == _secondRevealed.id)
{
_score++;
scoreLabel.text = "Score: " + _score;
if ((cardSounds.Count > 0) && (_firstRevealed.id < cardSounds.Count))
{
audioSource.PlayOneShot(cardSounds[_firstRevealed.id]);
}
}
else
{
yield return new WaitForSeconds(1f);
_firstRevealed.Unreveal();
_secondRevealed.Unreveal();
}
_firstRevealed = null;
_secondRevealed = null;
// a yield must be called in any coroutine
// the first 'if block' above does not have one
// this ensures that yield is called in the coroutine
yield return 0;
}
[SerializeField]
private MemoryCard originalCard;
[SerializeField]
private Sprite[] images;
void Start()
{
Vector3 startPos = originalCard.transform.position;
maxCardIDValueSize = (gridRows * gridCols);
ShuffleCardIDValues();
for (int i = 0; i < gridCols; i++)
{
for (int j = 0; j < gridRows; j++)
{
MemoryCard card;
if (i == 0 && j == 0)
{
card = originalCard;
}
else
{
card = Instantiate(originalCard) as MemoryCard;
}
int index = j * gridCols + i;
if (index < cardIDValues.Count)
{
int id = cardIDValues[index];
card.SetCard(id, images[id]);
float posX = (offsetX * i) + startPos.x;
float posY = -(offsetY * j) + startPos.y;
card.transform.position = new Vector3(posX, posY, startPos.z);
}
}
}
// get a handle to the audioSource
audioSource = GetComponent<AudioSource>();
audioSource.loop = false; // change this to true if you want it to loop
}
// Update is called once per frame
void Update()
{
}
private void InitializeCardIDList()
{
cardIDValues.Clear();
for (int i = 0; i < maxCardIDValueSize; i++)
{
cardIDValues.Add(i / 2);
}
}
private void ShuffleCardIDValues()
{
InitializeCardIDList();
// Fisher-Yates Card Shuffle
for (int i = cardIDValues.Count - 1; i > 0; --i)
{
int j = (int)UnityEngine.Random.Range(0, i);
int temp = cardIDValues[i];
cardIDValues[i] = cardIDValues[j];
cardIDValues[j] = temp;
}
}
public void Restart()
{
#if UNITY_5_3_OR_NEWER
// Application.LoadLevel is deprecated UNITY 5.3 or newer
// Use SceneManager.LoadScene instead
SceneManager.LoadScene("MEMORY GAME");
#else
Application.LoadLevel("MEMORY GAME");
#endif
}
}
I have tried to make as few changes as possible, but everything is explained below
Application.LoadLevel() is deprecated as of Unity 5.3, SceneManager.LoadScene needs to be used instead.
Use List instead of an Array (more efficient).
Added a second yield statement at the end of the coroutine. This was added because the only yield in the function is within the else part of the if statement which means an error can occur.
Added an AudioSource (to play sounds).
Added a list for the card sound clips (public - they need to be added in the inspector).
Yep works great, I didnt catch that you put Using System.Collections.Generic up top so it wasn't working for a bit, but I eventually found it. $$anonymous$$y kiddo will enjoy playing this once I find the rest of the sounds. Thank you again!
Your answer
Follow this Question
Related Questions
How can I get my sound array working here? 0 Answers
change sound pitch on object 0 Answers
How to prevent sound effects playing every frame? 0 Answers