For some reason, the audio clip wont play. I even chacked it with Debug.log(audioSource.clip.LoadState); and it returned
Loaded
. I dont know what goes wrong and prevents the source from playing the clip. Also, the clip name is blank.
The code :
IEnumerator LoadMusic(string path, AudioSource audioSource)
{
if (File.Exists(path))
{
using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(path, AudioType.WAV))
{
yield return uwr.SendWebRequest();
var uwrClip = DownloadHandlerAudioClip.GetContent(uwr);
audioSource.clip = uwrClip;
}
}
}
private void LoadAssets()
{
if (charts.Length == 0)
{
return;
}
else if (startingValue != currentDropdownValue)
{
startingValue = currentDropdownValue;
string musicToLoad = currentFilePath;
StartCoroutine(LoadMusic(musicToLoad, SelectorAudioPreview));
SelectorAudioPreview.Play();
}
}
(I know that i could've used charts.Lenght != 0, but I was too tired to think straight back then.)
Add audioSource.Play(); after audioSource.clip = uwrClip;
‘
And remember to check if in your scene there is a audio listener. Check also that the audioSource settings are ok to listen, like the volume, mute, distance...
Related
I am trying to capture video from web camera using unity and hololens.
I found this example on the unity page here .
I am pasting the code below. The light on the cam turns on, however it doesnt record.
The VideoCapture.CreateAsync doesnt create a VideoCapture. So the delegate there is never executed.
I saw this thread, however that was on. On the player settings the webcam and microphone capabilities are on.
What could be the problem?
using UnityEngine;
using System.Collections;
using System.Linq;
using UnityEngine.XR.WSA.WebCam;
public class VideoCaptureExample : MonoBehaviour
{
static readonly float MaxRecordingTime = 5.0f;
VideoCapture m_VideoCapture = null;
float m_stopRecordingTimer = float.MaxValue;
// Use this for initialization
void Start()
{
StartVideoCaptureTest();
Debug.Log("Start");
}
void Update()
{
if (m_VideoCapture == null || !m_VideoCapture.IsRecording)
{
return;
}
if (Time.time > m_stopRecordingTimer)
{
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}
}
void StartVideoCaptureTest()
{
Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
Debug.Log(cameraResolution);
float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();
Debug.Log(cameraFramerate);
VideoCapture.CreateAsync(false, delegate (VideoCapture videoCapture)
{
Debug.Log("NULL");
if (videoCapture != null)
{
m_VideoCapture = videoCapture;
Debug.Log("Created VideoCapture Instance!");
CameraParameters cameraParameters = new CameraParameters();
cameraParameters.hologramOpacity = 0.0f;
cameraParameters.frameRate = cameraFramerate;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
m_VideoCapture.StartVideoModeAsync(cameraParameters,
VideoCapture.AudioState.ApplicationAndMicAudio,
OnStartedVideoCaptureMode);
}
else
{
Debug.LogError("Failed to create VideoCapture Instance!");
}
});
}
void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Started Video Capture Mode!");
string timeStamp = Time.time.ToString().Replace(".", "").Replace(":", "");
string filename = string.Format("TestVideo_{0}.mp4", timeStamp);
string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);
filepath = filepath.Replace("/", #"\");
m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
}
void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Stopped Video Capture Mode!");
}
void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Started Recording Video!");
m_stopRecordingTimer = Time.time + MaxRecordingTime;
}
void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Stopped Recording Video!");
m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}
}
EDIT:
The problem was that the API doesnt work on the Emulator
You should try taking a look at this thread here. Where it goes into detail on how to record a video with HoloLens as well as how to take a photo. Also make sure you have the WebCam and microphone capabilities set. Also if you are trying to save it, make sure you have the Videos Library capability as well.
OnVideoCaptureCreated:
void OnVideoCaptureCreated (VideoCapture videoCapture)
{
if (videoCapture != null)
{
m_VideoCapture = videoCapture;
Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();
CameraParameters cameraParameters = new CameraParameters();
cameraParameters.hologramOpacity = 0.0f;
cameraParameters.frameRate = cameraFramerate;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
m_VideoCapture.StartVideoModeAsync(cameraParameters,
VideoCapture.AudioState.None,
OnStartedVideoCaptureMode);
}
else
{
Debug.LogError("Failed to create VideoCapture Instance!");
}
}
OnStartVideoCaptureMode:
void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
if (result.success)
{
string filename = string.Format("MyVideo_{0}.mp4", Time.time);
string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);
m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
}
}
OnStartRecordingVideo:
void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Started Recording Video!");
// We will stop the video from recording via other input such as a timer or a tap, etc.
}
StopRecordingVideo:
// The user has indicated to stop recording
void StopRecordingVideo()
{
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}
OnStopRecordingVideo:
void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
Debug.Log("Stopped Recording Video!");
m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}
void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
m_VideoCapture.Dispose();
m_VideoCapture = null;
}
I'm making my very first game in unity. In this game my player is a ball which touches some question marks. When a question mark is triggered it has to display a question and the answers. Till here every thing is fine. Now i need to press a or b according to the question. If the answer is right it will add points. But here is the problem. Unity doesn't wait for me to press the keys. Unity passes through the code before i press the buttons and the game crashes.
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.CompareTag("QuestionCube1"))
{
Question.text = "Which Number is bigger?";
Answer.text = "A.5 B.10";
if (Input.GetKeyDown(KeyCode.A))
{
gameController.minusQuestionScore();
}
else if (Input.GeyKeyDown(KeyCode.B))
{
gameController.addQuestionScore();
}
Question.text = "";
Answer.text = "";
}
}
//Sorry if the code is kinda all over the place I dont know how to pass the code here exactly. The gameController and the UI texts are declared and working
Okay let's shift away from the comment section and let's try to improvise, on my current understandings of your problem.
First thing you must consider is the following.
void OnTriggerEnter(Collider collider)
Triggers ONLY once, when the other collider enters. The solution?
Use OnTriggerStay.
void OnTriggerStay(Collider collider)
This will always check for the input when the objects are colliding.
The next thing to consider is the reset of the text. As far as I understand you should remove it when they are not colliding anymore, so you could have additional method. OnTriggerExit, which will run additional code when they are not colliding anymore.
void OnTriggerExit(Collider collider)
{
if (collider.gameObject.CompareTag("QuestionCube1"))
{
Question.text = "";
Answer.text="";
}
}
So overall
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.CompareTag("QuestionCube1"))
{
Question.text = "Which Number is bigger?";
Answer.text = "A.5 B.10";
if(Input.GetKeyDown(KeyCode.A))
{
gameController.minusQuestionScore();
}
else if(Input.GeyKeyDown(KeyCode.B))
{
gameController.addQuestionScore();
}
}
}
You can use Coroutine to wait for the input after it is triggered.
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.CompareTag("QuestionCube1"))
{
Question.text = "Which Number is bigger?";
Answer.text = "A.5 B.10";
StartCoroutine(WaitForAnswer());
}
}
IEnumerator WaitForAnswer()
{
for (;;)
{
if (Input.GetKeyDown(KeyCode.A))
{
gameController.minusQuestionScore();
break;
}
else if (Input.GetKeyDown(KeyCode.B))
{
gameController.addQuestionScore();
break;
}
yield return null;
}
Question.text = "";
Answer.text = "";
yield return null;
}
I am calling ChangeVideo() from an invoke method:
InvokeRepeating ("ChangeVideo", 1, TimeToChangeImage);
public void ChangeVideo()
{
public string[] VedioPaths ={"aa","bb"}
System.Random random1 = new System.Random();
PathNO1 = random1.Next (VedioPaths.Length);
ConfirmPath1 = VedioPaths[PathNO1];
Handheld.PlayFullScreenMovie (ConfirmPath1,Color.black,FullScreenMovieControlMode.CancelOnInput);
}
I need to play the next video soon after the other finishes. How can I do that? I tried many ways but every time I build I get an error.
I have a string array from which I randomly select a video; once the first video finishes the next one should start playing. I tried using the invoke method but it is giving me an error.
If you want to load videos in a coroutine:
void Start()
{
StartCoroutine(LoadVideos());
}
IEnumerator LoadVideos()
{
//first vid
Handheld.PlayFullScreenMovie("vid1.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
//second vid
Handheld.PlayFullScreenMovie("vid2.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
}
Note that two lines of yield return new WaitForEndOfFrame(); is absolutely required for this method to work. The reason is unknown to me but it won't work otherwise.
Take a look closer to the documentation : https://docs.unity3d.com/ScriptReference/Handheld.PlayFullScreenMovie.html
Calling this function will pause Unity during movie playback. When playback finishes Unity will resume
Meaning that, if you want to play 2 videos one after the other, you just have to do :
Handheld.PlayFullScreenMovie (path1,Color.black,FullScreenMovieControlMode.CancelOnInput);
Handheld.PlayFullScreenMovie (path2,Color.black,FullScreenMovieControlMode.CancelOnInput);
Waiting between the two calls may be required though.
There is a very easy way for the lastest VideoPlayer to detect the loop point even if it‘s not looping.
public VideoPlayer videoPlayer;
public VideoClip[] videos;
public VideoClip theVideo;
public static int index;
bool isPlaying = true;
void Start()
{
index = 0;
videoPlayer = gameObject.GetComponent<VideoPlayer>();
videoPlayer.loopPointReached += CheckOver;
}
void CheckOver(UnityEngine.Video.VideoPlayer vp)
{
print("Video Is Over");
index += 1;
if (index >= videos.Length)
{
index = 0;
}
theVideo = videos[index];
videoPlayer.clip = theVideo;
videoPlayer.Play();
isPlaying = true;
}
I'm trying to load a video via url, but I keep getting the same error. I'm using Unity 5.3 and the example code from http://docs.unity3d.com/ScriptReference/WWW-movie.html (heavily modified because the current example doesn't compile).
using UnityEngine;
using System.Collections;
// Make sure we have gui texture and audio source
[RequireComponent (typeof(GUITexture))]
[RequireComponent (typeof(AudioSource))]
public class TestMovie : MonoBehaviour {
string url = "http://www.unity3d.com/webplayers/Movie/sample.ogg";
WWW www;
void Start () {
// Start download
www = new WWW(url);
StartCoroutine(PlayMovie());
}
IEnumerator PlayMovie(){
MovieTexture movieTexture = www.movie;
// Make sure the movie is ready to start before we start playing
while (!movieTexture.isReadyToPlay){
yield return 0;
}
GUITexture gt = gameObject.GetComponent<GUITexture>();
// Initialize gui texture to be 1:1 resolution centered on screen
gt.texture = movieTexture;
transform.localScale = Vector3.zero;
transform.position = new Vector3 (0.5f,0.5f,0f);
// gt.pixelInset.xMin = -movieTexture.width / 2;
// gt.pixelInset.xMax = movieTexture.width / 2;
// gt.pixelInset.yMin = -movieTexture.height / 2;
// gt.pixelInset.yMax = movieTexture.height / 2;
// Assign clip to audio source
// Sync playback with audio
AudioSource aud = gameObject.GetComponent<AudioSource>();
aud.clip = movieTexture.audioClip;
// Play both movie & sound
movieTexture.Play();
aud.Play();
}
}
I added this as a script to the Main Camera in a new scene, and I get this error:
Error: Cannot create FMOD::Sound instance for resource (null), (An invalid parameter was passed to this function. )
UnityEngine.WWW:get_movie()
<PlayMovie>c__Iterator4:MoveNext() (at Assets/TestMovie.cs:20)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
TestMovie:Start() (at Assets/TestMovie.cs:16)
(Line 20 is MovieTexture movieTexture = www.movie;)
I've been working on this for a while now, it's happened on many files and both of my systems.
I found a solution! I tested the code with unity 5.2.X and 5.3.X.
I dont know why but Unity 3d requires first wait unitl the download is done with isDone == true and after the copy of the texture wait until the isReadyToPlay == true.
The movie file must be OGG Video format some MP4 files doesn't work.
Well. Check the code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class MovieTextureStream : MonoBehaviour {
public Text progressGUI;
public MeshRenderer targetRender = null;
public AudioSource targetAudio = null;
public string URLString = "http://unity3d.com/files/docs/sample.ogg";
MovieTexture loadedTexture;
IEnumerator Start() {
if(targetRender ==null) targetRender = GetComponent<MeshRenderer> ();
if(targetAudio ==null) targetAudio = GetComponent<AudioSource> ();
WWW www = new WWW (URLString);
while (www.isDone == false) {
if(progressGUI !=null) progressGUI.text = "Progresso do video: " + (int)(100.0f * www.progress) + "%";
yield return 0;
}
loadedTexture = www.movie;
while (loadedTexture.isReadyToPlay == false) {
yield return 0;
}
targetRender.material.mainTexture = loadedTexture;
targetAudio.clip = loadedTexture.audioClip;
targetAudio.Play ();
loadedTexture.Play ();
}
}
I won't provide a solution with the WWW.movie, but an alternative solution that may help ou or anyone else.
On IPhone, we didn't find a solution to stream video from a server, we decided to download the video before reading it, here's how:
string docPath = Application.persistentDataPath + "/" + id + ".mp4";
if (!System.IO.File.Exists(docPath))
{
WWW www = new WWW(videouUrl);
while(!www.isDone)
{
yield return new WaitForSeconds(1);
Loading.Instance.Message = "Downloading video : " + (int)(www.progress * 100) + "%";
if (!string.IsNullOrEmpty(www.error))
Debug.Log(www.error);
}
byte[] data = www.bytes;
System.IO.File.WriteAllBytes(docPath, data);
}
mediaPlayer.Load(docPath);
onVideoReady();
mediaPlayer.Play();
This is the coroutine used to download and write the video on the iphone's file system. Once it's done, you can load and play it.
Hope it helps.
I have two spawn spots where a player will show up upon connection.
I need that, when one of the players connects on one of the spots, any other player will always spawn at the other spot.
Here's some visual in case it helps: https://goo.gl/Y0ohZC
Thanks in advance,
IC
You can add those two possible spawn spots as empty game objects.
Then I'd make a boolean array and set its states to true or false depending on if the spot is occupied. The spots aren't directly stored in this array so you should make another array.
In C# this would approximately look like this:
public GameObject[] Spots = new GameObject[2]; //Drag the spots in here (In the editor)
bool[] OccupiedSpawnSpots = new bool[2];
int mySpotNumber = -1;
void Start() {
PhotonNetwork.ConnectUsingSettings ("v1.0.0");
}
void OnGUI() {
GUILayout.Label (PhotonNetwork.connectionStateDetailed.ToString ());
}
void OnJoinedLobby()
{
Debug.Log ("Joined the lobby");
PhotonNetwork.JoinRandomRoom ();
}
void OnPhotonRandomJoinFailed()
{
Debug.Log ("No room found. Creating a new one...");
PhotonNetwork.CreateRoom (null);
}
void OnPhotonPlayerConnected(PhotonPlayer player)
{
//If we are the MasterClient, send the list to the connected player
if (PhotonNetwork.isMasterClient)
GetComponent<PhotonView>().RPC("RPC_SendList", player, OccupiedSpawnSpots);
}
void OnApplicationQuit()
{
//If I am outside and others want to connect, my spot shouldn't be still set as occupied:
//I mean if the application quits I'm of course going to be disconnected.
//You have to do this in every possibility of getting disconnected or leaving the room
OccupiedSpawnSpots[mySpotNumber] = false;
//Send the changed List to the others
GetComponent<PhotonView>().RPC("RPC_UpdateList", PhotonTargets.All, OccupiedSpawnSpots);
}
[RPC]
void RPC_SendList(bool[] ListOfMasterClient)
{
OccupiedSpawnSpots = ListOfMasterClient;
//Get the free one
if (OccupiedSpawnSpots[0] == false)
{
//Spawn your player at 0
SpawnMyPlayer(0);
//Set it to occupied
OccupiedSpawnSpots[0] = true;
}
else //so the other must be free
{
//Spawn your player at 1
SpawnMyPlayer(1);
//Set it to occupied
OccupiedSpawnSpots[1] = true;
}
//Send the changed List to the others
GetComponent<PhotonView>().RPC("RPC_UpdateList", PhotonTargets.All, OccupiedSpawnSpots);
}
[RPC]
void RPC_UpdateList(bool[] RecentList)
{
OccupiedSpawnSpots = RecentList;
}
void SpawnMyPlayer(int SpotNumber) {
// Check if spawnspots are set OK
if (Spots == null) {
Debug.LogError ("SpawnSpots aren't assigned!");
return;
}
mySpotNumber = SpotNumber;
// The player object for the network
GameObject myPlayerGO = (GameObject)PhotonNetwork.Instantiate ("PlayerController",
Spots[SpotNumber].transform.position,
Spots[SpotNumber].transform.rotation, 0);
// Enable a disabled script for *this player only, or all would have the same camera, movement, etc
//((MonoBehaviour)myPlayerGO.GetComponent("FPSInputController")).enabled = true;
// Set a camera just for this player
//myPlayerGO.transform.FindChild ("Main Camera").gameObject.SetActive (true);
//standbyCamera.SetActive(false);
}
Note: If you have more than two players, it gets a lot more difficult. This code isn't optimized so maybe you'll find a better one, but it should give you the right idea.
Please ask if anything isn't clear to you...