MovieTexture won't play audio - unity3d

I'm trying to dynamically load and play a video file. No matter what I do, I cannot seem to figure out why the audio does not play.
var www = new WWW("http://unity3d.com/files/docs/sample.ogg");
var movieTexture = www.movie;
var movieAudio = www.movie.audioClip;
while (!movieTexture.isReadyToPlay) yield return 0;
// Assign movie texture and audio
var videoAnimation = videoAnimationPrefab.GetComponent<VideoAnimation>();
var videoRenderer = videoAnimation.GetVideoRenderer();
var audioSource = videoAnimation.GetAudioSource();
videoRenderer.material.mainTexture = movieTexture;
audioSource.clip = movieAudio;
// Play the movie and sound
movieTexture.Play();
audioSource.Play();
// Double check audio is playing...
Debug.Log("Audio playing: " + audioSource.isPlaying);
Every time I receive Audio playing: False
I've also tried using a GUITexture using this as a guide, but no dice. There are no errors displayed in the console.
What am I doing wrong that makes the audio never work?
Thanks in advance for any help!

Changed to:
while (!movieTexture.isReadyToPlay) yield return 0;
var movieAudio = movieTexture.audioClip;
Even though AudioClip inherits from Object, a call to movieTexture.audioClip seems to return a copied version instead of returning a reference by value to the object. So at the time I was assigning it, it had not been created yet and had to wait until the movie was "Ready to Play" until fetching the audioClip.

Related

Playing the same sound rapidly from a single audiosource vs multiple audiosources

Ok let me try and explain...
I am making a card game where it plays a sound effect when a card is added to a pile, but during the setup cards are rapidly added to different piles and it breaks if I use a single Audiosource
If I play it from a single audiosource it seems not to play them all or if it is it's playing them all at once.
vs
If I do it by having an audiosource on each pile and use that instance of it and hear the different effects played.
I am in the middle of rewriting the game as the first time was a dry run and didn't know what I was going to need and is a bit rough and came across this while trying to streamline the in game audio by having a GameAudioManager singleton to handle the audio.
Is there a reason for this and a solution?
Info
Sound Effect is a MP3 and 3kb
Delay between effects is 0.01f
Choice is yours actually...
Want them to play sequentially ? one audio source is enough and add pending clips to a queue and dequeue them as the currently playing one finishes.
Want them to play individually, separately as the event happens, regardless of whether another card was just added and its effect was still playing, then you use multiple audio sources.
Here's a starting point for a manager that plays audios individually as they're requested.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GameAudioManager : MonoBehaviour
{
// your singleton pattern here, so assuming you now have an instance.
public static GameAudioManager Instance;
// List holds available sources that we can use to play an audio clip.
List<AudioSource> availableSources = new List<AudioSource>();
// Immediately plays a clip, if a cached audio source available, uses it, if none, create new.
public static void AudioPlayOneShot(AudioClip clip, float volume, float pitch, bool loop)
{
Instance.StartCoroutine(Instance.StartPlayingOneShot(clip, volume, pitch, loop);
}
private IEnumerator StartPlayingOneShot(AudioClip clip, float volume, float pitch, bool loop)
{
AudioSource audioSource = GetAudioSource();
audioSource.playOnAwake = false;
audioSource.clip = clip;
audioSource.volume = volume;
audioSource.pitch = pitch;
audioSource.loop = loop;
audioSource.Play();
while (audioSource.isPlaying)
yield return null;
// Whenever this clip stops, add it back to available cache.
CacheAudioSource(audioSource);
}
private void CacheAudioSource(AudioSource audioSource)
{
audioSource.clip = null;
audioSource.playOnAwake = false;
availableSources.Add(audioSource);
}
/// <summary>
/// Gets an audio source from cached list or creates a new one if none available.
/// </summary>
/// <returns></returns>
private AudioSource GetAudioSource()
{
if (availableSources == null || availableSources.Count == 0)
return this.gameObject.AddComponent<AudioSource>();
else
{
AudioSource fromCache = availableSources[0];
availableSources.RemoveAt(0);
return fromCache;
}
}
}
Use like
GameAudioManager.AudioPlayOneShot(yourClip, yourVolume, yourPitch, loop);
The reason it wasn't working was that a AudioSource can only have one instance of itself playing so if it is playing already it is unable to start the new play.
The solution is to either instantiate them as needed or have it on each item and be able to play it from those individual AudioSources.
Hope this helps anyone else coming across this.

Why is it SO Hard to Just Mute a Sound in Unity?

I have spent all day looking for a solution to this problem, and I simply can't find one. Using JavaScript in Unity 3D, I have a script where I want to play a sound when the player's velocity on the X axis reaches a certain point, and if it's not at that point, then the sound will be muted. And I believe I have all the structure right, it's just the line of code that says to mute the audio that won't work. I've tried all kinds of different combinations, and I get an error for each one.
The script looks like this:
#pragma strict
var playing = false;
var audioSource = GetComponent.<AudioSource>();
function Update () {
if (transform.GetComponent.<Rigidbody>().velocity.x <= 2.5 &&
transform.GetComponent.<Rigidbody>().velocity.x >= -2.5)
{
Mute();
} else {
Unmute();
}
}
function Mute () {
audioSource.mute = true;
}
function Unmute () {
audioSource.mute = false;
Sound();
}
function Sound () {
if (transform.GetComponent.<Rigidbody>().velocity.x >= 2.5 && playing ==
false)
{
playing = true;
GetComponent.<AudioSource>().Play();
yield WaitForSeconds(2);
playing = false;
}
if (transform.GetComponent.<Rigidbody>().velocity.x <= -2.5 &&
playing == false)
{
playing = true;
GetComponent.<AudioSource>().Play();
yield WaitForSeconds(2);
playing = false;
}
}
I've gotten all kinds of different errors, but the one I seem to be getting the most says "UnityException: GetComponentFastPath is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'motioncheck' on game object 'Ball'." I'm not sure what this means, since I'm still kinda a nub at JavaScript.
I feel like it shouldn't be this hard to just mute a sound. I'm going to assume that the answer to this is really simple and that I'm just really dumb. That's what usually seems to happen, lol.
In the mean time, I'm going to continue my rampage across the internet in search for answers to this problem.
Your mute code is fine.
"UnityException: GetComponentFastPath is not allowed to be called from
a MonoBehaviour constructor (or instance field initializer), call it
in Awake or Start instead. Called from MonoBehaviour 'motioncheck' on
game object 'Ball'." I'm not sure what this means, since I'm still
kinda a nub at JavaScript.
See this:
var audioSource = GetComponent.<AudioSource>();
That's a Unity API and you have to call their functions from inside a function. The Awake or Start function is appropriate for initializing component variables.
var audioSource : AudioSource;
function Start()
{
audioSource = GetComponent.<AudioSource>();
}
Note that Unityscript/Javascript is now discontinued. They no longer update the doc on this and you cannot create new scripts from the Editor anymore. It still works as for now but the compiler will be removed soon. Please learn and start using C# before its support is totally removed.

Single Audiosource for multiple clips?

I have a couple of audio sources in a script, idea being that one is used for effects and the other for music. I am noticing that if an effect plays at the same time as another one, it actually stops the previous one from playing, probably because they are playing from the same audio source.
My question is, do I really have to instantiate a new audio source every time i want to play a new sound, just to make sure that one sound will not stop a currently playing one ? Is there a better way ?
The method that plays a sound effect(and the awake one) in my class are these :
void Awake() {
audioSource = GetComponents<AudioSource>()[0];
audioEffectsSource = GetComponents<AudioSource>()[1];
audioSource.volume = PlayerPrefsManager.getMasterVolume();
audioEffectsSource.volume = PlayerPrefsManager.getSFXMasterVolume();
}
public void playSoundEffect(AudioClip clip)
{
if(clip != null)
{
audioEffectsSource.clip = clip;
audioEffectsSource.volume = PlayerPrefsManager.getSFXMasterVolume();
audioEffectsSource.PlayOneShot(clip);
}
}
The script is attached to a musicmanager gameobject with 2 audiosources, one for music fx and one for sound tracks.

How to disable Scrubbing in TVMLKit JS Player Class

I am trying to stop users from scrubbing forward (skipping ads) in the TVMLKit Player class.
I have tried setting
player.interactiveOverlayDocument = null;
but the player still shows the Transport bar, and I am able to scrub forward.
Turns out to be quite easy.
On the MediaItem Class which the Player Class uses to load the video, there is an attribute interstitials that accepts an array of [starttiem, duration] values.
var singleVideo = new MediaItem(mediaType, videourl);
var videoInterstitials = [];
videoInterstitials.push({
starttime: 50,
duration: 30
});
singleVideo.interstitials = videoInterstitials;
var videoList = new Playlist();
videoList.push(singleVideo);
var player = new Player();
player.playlist = videoList;
player.play();

AudioSource error

I am following directions out of a book to put together a simple FPS. However, I am not getting the same results as the book says I should.
The last thing I have been trying to do is add a sound to my "gun", so that this sound clip "pop.wav" plays when you fire.
Here is the working code before I took the steps to add the sound.
var projectile : Rigidbody;
var speed = 50;
function Update () {
if(Input.GetButtonDown("Fire1"))
{
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position +
Vector3(0,-1,0), transform.rotation);
instantiatedProjectile.velocity = transform.TransformDirection(Vector3(0,0,speed));
Physics.IgnoreCollision(instantiatedProjectile.collider, transform.root.collider);
}
}
So I did what the book said, and imported Pop.wav. Then it said to add two simple lines of code to the script.
var projectile : Rigidbody;
var speed = 50;
var pop : AudioClip;
function Update () {
if(Input.GetButtonDown("Fire1"))
{
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position +
Vector3(0,-1,0), transform.rotation);
instantiatedProjectile.velocity = transform.TransformDirection(Vector3(0,0,speed));
Physics.IgnoreCollision(instantiatedProjectile.collider, transform.root.collider);
audio.Play(pop);
}
}
Assets/FireProjectile.js(12,27): BCE0023: No appropriate version of 'UnityEngine.AudioSource.Play' for the argument list '(UnityEngine.AudioClip)' was found.
I would really appreciate some help on this.
I don't see you assigning the file to be played to the audio clip... something like
pop.clip = ...
A brief search on unity 3d mentions assigning the clip, and checking that it's ready to play.
Actually, you have overlooked something outside the script. You do in fact need to add an audio listener and an audio source in the scene. Then, you'll be able to hear the sound.
The reason for this is that unity allows for 3D sound, i.e. sound which has a location in 3D space, and will increase in volume if you go near it. The Audio Source is obviously where the sound is comming from, and Audio Listener is where your ears are, so to speak. Usually the audio listener is on your character. But you can rig it so that it is on any object, but then that object would have to get near the audio source, and not the character, which doesn't make any sense at all.
However, remember to only have ONE audio LISTENER at a time. Infinite audio SOURCES are allowed. :)
You need to assign your variable. It would be something like
pop.clip = (anything here)
You must use audio.PlayOneShot(pop) instead of audio.Play().
But if you want to use audio.Play(); you should know that it doesn't take AudioClip as argument.
Use following code and make sure you assign pop to Audio Clip property of Audio Source component by dragging pop sound from Project to inspector. audio.Play() uses default assigned Audio Clip in AudioSource.
var projectile : Rigidbody;
var speed = 50;
function Update () {
if(Input.GetButtonDown("Fire1"))
{
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position +
Vector3(0,-1,0), transform.rotation);
instantiatedProjectile.velocity = transform.TransformDirection(Vector3(0,0,speed));
Physics.IgnoreCollision(instantiatedProjectile.collider, transform.root.collider);
audio.Play();
}
}
#script RequireComponent(AudioSource)
Based on the Unity documentation (I've never used Unity so I can't be sure this is correct) I find that you probably want to do something like this.
var projectile : Rigidbody;
var speed = 50;
var pop : AudioClip;
...
if(Input.GetButtonDown("Fire1"))
{
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position +
Vector3(0,-1,0), transform.rotation);
instantiatedProjectile.velocity = transform.TransformDirection(Vector3(0,0,speed));
Physics.IgnoreCollision(instantiatedProjectile.collider, transform.root.collider);
audio.PlayOneShot(pop);
}
This is actually all you have to do. Assign a variable, and then tell it to play in the update function, whenever Fire1 is pressed, which is LMB by default.
PlayOneShot means the sound won't loop or anything, which I assume you want for gunshots or similar. Within the parentheses you simply name the sound you want to play.