I am making a Music Player app for Android in Unity3d. For show_currentPlayTime() function, I want to get AS.time value to show current playTime. For seek() function, I want to set AS.time value to get to that specific point of AudioClip. But, the problem is that AS.time is giving me 0.
I have tried setting AudioClip in AudioSource. It works that way, but the audio becomes distorted and shows abnormal behavior.
Variable Declaration:
public AudioSource AS;
[Range(0.0f, 1.0f)]
public Slider Volume;
public Slider slider;
bool isPlaying;
public List<AudioClip> AC = new List<AudioClip>();
int currentSong = 0;
Play Function:
public void Play()
{
AS.Stop();
AS.PlayOneShot(AC[currentSong]);
//AS.clip = AC[currentSong]; ---
//AS.Play(); ---
//AS.clip = AC[currentSong]; ---
//AS.PlayOneShot(AS.clip); ---
clipInfo.text = AC[currentSong].name;
Debug.Log(AC[currentSong].name);
CancelInvoke();
Invoke("Next", AC[currentSong].length);
isPlaying = true;
}
The program runs with using --- lines, in above code, but with that, the audio becomes distorted.
Music Seek function:
public void MusicSlider()
{
AS.time = AC[currentSong].length * slider.value;
slider.value = AS.time / AC[currentSong].length;
Debug.Log(AS.time);
}
AS.time gives me value = 0.
The AudioSource.Stop function stops the currently set Audio clip from playing
so you shouldn't be using PlayOneShot since this doesn't assign the clip value and isn't stopped but played parallel. It is usually more used for playing soundeffects which may occure at the same time.
From AudioSource
You can play a single audio clip using Play, Pause and Stop You can also adjust its volume while playing using the volume property, or seek using time. Multiple sounds can be played on one AudioSource using PlayOneShot.
AudioSource.time from the examples also only seems to work using Play instead of PlayOneShot for the same reason.
In the commented code you are also mixing both Play and PlayOneShot. I guess what you called distorted is actually the clip playing twice at the same time. Your code should rather simply be
public void Play()
{
AS.Stop();
AS.clip = AC[currentSong];
AS.Play();
clipInfo.text = AC[currentSong].name;
Debug.Log(AC[currentSong].name);
// Don't know ofcourse what those methods do...
CancelInvoke();
Invoke("Next", AC[currentSong].length);
isPlaying = true;
}
Related
I have a really simple script where I have a video start playing in Unity on start, and then pause at a specific time in the movie:
public class PlayVideoScript : MonoBehaviour
{
public UnityEngine.Video.VideoPlayer videoPlayer;
// Start is called before the first frame update
void Start()
{
// Will attach a VideoPlayer to the main camera.
GameObject camera = GameObject.Find("Main Camera");
// VideoPlayer automatically targets the camera backplane when it is added
// to a camera object, no need to change videoPlayer.targetCamera.
videoPlayer = camera.AddComponent<UnityEngine.Video.VideoPlayer>();
// Play on awake defaults to true. Set it to false to avoid the url set
// below to auto-start playback since we're in Start().
videoPlayer.playOnAwake = false;
// By default, VideoPlayers added to a camera will use the far plane.
// Let's target the near plane instead.
videoPlayer.renderMode = UnityEngine.Video.VideoRenderMode.CameraNearPlane;
// This will cause our Scene to be visible through the video being played.
videoPlayer.targetCameraAlpha = 0.5F;
// Set the video to play. URL supports local absolute or relative paths.
// Here, using absolute.
videoPlayer.url = "Assets/Movie.mp4";
// Skip the first 100 frames.
videoPlayer.frame = 100;
// Restart from beginning when done.
videoPlayer.isLooping = false;
// Each time we reach the end, we slow down the playback by a factor of 10.
//videoPlayer.loopPointReached += EndReached;
// Start playback. This means the VideoPlayer may have to prepare (reserve
// resources, pre-load a few frames, etc.). To better control the delays
// associated with this preparation one can use videoPlayer.Prepare() along with
// its prepareCompleted event.
videoPlayer.Play();
}
// Update is called once per frame
void Update()
{
print(videoPlayer.time);
print(videoPlayer.time);
if (videoPlayer.time == 15.0) {
print("paused;");
videoPlayer.Pause();
}
}
}
I can verify that I've reached the time I want in the Update function, but the videoPlayer doesn't pause at all. I'm pretty new to Unity, so any help appreciated!
In your Update method, you check if the video reached exactly 15s.
The thing is, from one frame to another, you may go further than 15 and so never equal 15.
I will suggest you to do as the following :
void Update()
{
if (videoPlayer.time >= 15.0) {
print("paused;");
videoPlayer.Pause();
}
}
I'm stuck on the last test for my app before submission to the Oculus store. I've tried all sorts with no avail. I need to do is pass the frames when not visible test.
Effectively, the app needs to go into pause mode when the user clicks the menu button on the oculus touch controller.
I need to stop all frames submitting from Unity. For example, things I've tried, turn off cameras, audio, ovrplayercontroller etc but frames being submitted when the menu button is pressed on the rift so it would appear to freeze the application.
I've tried disabling cameras in a foreach loop, disabling the player gameobject, ovr controllers all sorts.
I have a gameobject with a script attached to try and detect when the test will fire based on the HMD losing tracking.
Here's where I'm currently at (gone back to the basics again), any help would be greatly appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HMDCheck : MonoBehaviour
{
public GameObject OVRCameraRig;
private void Update()
{
if (!OVRManager.isHmdPresent)
{
OVRCameraRig.SetActive(false);
Time.timeScale = 0f;
}
else
{
OVRCameraRig.SetActive(true);
Time.timeScale = 1f;
}
}
}
Additionally their docs say the test performs this action:
TestSubmitFramesWhenNotVisible
Tests if your app stops submitting frames when the Universal Menu is open.
Note :
My most recent command line response for the test is the following output :
Starting TestSubmitFramesWhenNotVisible
Waiting for the application to run for 5 seconds before testing begins...
Starting test...
Requesting the void...
Number of texture swap chains committed when visible 68
Number of texture swap chains committed when not visible 4
ERROR: Committed a texture swap chain (called ovr_CommitTextureSwapChain) when application not visible
Please refer to VRC Guidelines:
https://developer.oculus.com/distribute/latest/concepts/vrc-pc-input-1/
Cleaning up...
Test FAILED
To get around it, I created a script with public gameobjects. I then dragged my player into the slots inside Unity but left the camera on the scene alone. Here's a screenshot and the code. I initially added the camera to turn off frames sending but Oculus rejected it as it froze in the background upon pressing the menu button.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HMDCheck : MonoBehaviour
{
public GameObject target, scripts, LocalAvatar;
private void Update()
{
if (!OVRManager.hasVrFocus || !OVRManager.isHmdPresent || !OVRManager.hasInputFocus)
{
//target.SetActive(false);
scripts.SetActive(false);
LocalAvatar.SetActive(false);
Time.timeScale = 0f;
AudioListener.pause = true;
}
else
{
//target.SetActive(true);
scripts.SetActive(true);
LocalAvatar.SetActive(true);
Time.timeScale = 1f;
AudioListener.pause = false;
}
}
}
I have almost the same code, but this detects the Universal Menu correctly and does freeze the output, but it still won't pass the test. I think it may pass if you disable splash screens, but can't know since I have the free version of Unity.
Edit: I saw your answer Diego, but cannot comment. Did your action resolve your original question? And what license do you have for Unity?
Camera cam;
bool bPause = false;
void Update()
{
//install 'Oculus Integration' for this to work
bool bPauseNow = !(OVRManager.hasInputFocus && OVRManager.hasVrFocus);
//pause state change
if (Camera.main != null) cam = Camera.main;
if (bPause != bPauseNow)
{
bPause = bPauseNow;
if (bPauseNow)
{
Time.timeScale = 0.0f; //stops FixedUpdate
//Update keeps running, but
// rendering must also be paused to pass vrc
cam.enabled = false;
}
else
{
Time.timeScale = 1.0f;
//
cam.enabled = true;
}
}
//...
}
I am using the "Oculus XR Plugin", and got this issue,
but I found that the results of the "VRC Validator" are not so accurate,
then I submitted the App for review and passed the test.
I have a 1.5 seconds audio file - a single gunshot sound. I want to be able to play the sound while the mouse is pressed (like an automatic weapon), and I used InvokeRepeating to call the shoot method, with a very low repeatRate:
if (Input.GetButtonDown("Fire1"))
{
InvokeRepeating("Shoot", 0f, 1f/currentWeapon.fireRate);
} else if (Input.GetButtonUp("Fire1"))
{
CancelInvoke("Shoot");
}
And this is the Shoot method:
void Shoot()
{
shootSound.PlayOneShot(shoot);
}
The problem is the sound cuts off and the shot can't be heard, it's playing for a fraction of a second instead of the whole audio clip. I tried play() and playOneShot().
Is there an option to play each clip to its fullest separately, like creating clones of it?
Thanks!
Most things in your code are just unnecessary. You don't need InvokeRepeating for this. Since you want to continue to player sound(shooting effect) while the button is held down, Input.GetButton should be used instead of Input.GetButtonDown because Input.GetButton is true every frame the button is held down and is made for things like auto fire.
A simple timer with Time.time should also be used to determine the rate to play the sound then play the sound with the PlayOneShot function.
This is what that should look like:
public float playRate = 1;
private float nextPlayTime = 0;
public AudioSource shootSound;
public AudioClip shoot;
void Update()
{
if (Input.GetButton("Fire1") && (Time.time > nextPlayTime))
{
Debug.Log("Played");
nextPlayTime = Time.time + playRate;
shootSound.PlayOneShot(shoot);
}
}
The playRate variable is set to 1 which means 1 sound per-sec. You can use this variable to control the play rate. Lower it to play many sounds. The value of 0.1f seems to be fine but it depends on the sound.
I solved it, I used an empty GameObject with an AudioSource, and instantiated a copy of it in each Shoot method:
GameObject gunObj = Instantiate(gunObject);
Destroy(gunObj, 1f);
Works perfectly now!
I'm trying to make a countdown timer but using a Unity Slider instead of text but I've ran across a few issues. So my current code is:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CountdownTimer : MonoBehaviour {
//public Text timeText;
public float startingTime = 100.0f;
public Slider Timer;
// Use this for initialization
void Start () {
Timer = GetComponent<Slider> ();
}
// Update is called once per frame
void Update () {
startingTime -= Time.deltaTime;
Timer.value = startingTime;
if (startingTime <= 0)
{
startingTime = 0;
Application.LoadLevel ("GameOver");
}
}
}
This code works if I were to replace the slider with the text but not vice versa. My second issue is when I attach this code to my player and link the slider from the hierarchy, it disappears when I start the game.
Last issue is when I try to add an On Value Changed, I can link it to my player to get the functions from the code but from doing my research there isn't really anything I can link it to since I only have start and update. Scrollbars can use private voids and receive the dynamic float that way but I haven't been able to yet with Sliders
Example:
On Change Value
It does not work on the slider you say, you need to pass the max value as 100 on the slider component, or it uses 1 until the value gets between 0 and 1.
A UI item has to be under a Canvas to be rendered, so attaching it to your player makes it discarded from rendering. You can put the Canvas with the slider as child under the player object. But I would keep the canvas separated for clarity(POV).
The picture you added shows that you passed an object, but now you need to assign a method. Click the No Function and it will display all the available methods.
Title is pretty self explanatory. But here's a brief description of my problem:
I'm using playscheduled to switch tracks on beat/bar. The issue is that sometimes, some event happens and I would like to cancel a specific queued track from being played.
Using AudioSource.Stop() will only stop the currently played track, the scheduled tracked will still play afterwards.
Any ideas? Is there a method to call that I am missing?
You can use a coroutine to control when and if the next clip should be played. There is a simple example in the AudioSource.clip reference that needs to be extended a little bit.
The following code snippet plays the clip attached to AudioSource and ToggleAudioClips.otherClip alternating in an endless loop until ToggleAudioClips.StopPlaying () is called. A new coroutine is started whenever the current clip is finished.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(AudioSource))]
public class ToggleAudioClips : MonoBehaviour
{
public AudioClip otherClip;
bool stopPlaying = false;
AudioClip currentClip;
AudioClip nextClip;
void Start () {
currentClip = audio.clip;
nextClip = otherClip;
StartCoroutine (PlayClip ());
}
IEnumerator PlayClip () {
audio.clip = currentClip;
audio.Play ();
yield return new WaitForSeconds(audio.clip.length);
if (!stopPlaying) {
AudioClip c = nextClip;
nextClip = currentClip;
currentClip = c;
StartCoroutine (PlayClip ());
}
}
public bool StopPlaying () {
stopPlaying = true;
audio.Stop ();
}
}
After much trial and error, I after creating a whole new scene to test the various options I have realized that AudioSource.Stop() WILL stop a scheduled track from playing. It was my error that was causing my queueing system to schedule a new track after I have sent a cancel call.
To see this working just schedule a track and print AudioSource.isPlaying. You will notice that even thou the source is not currently playing, scheduling it will set this variable to "true". Once you call AudioSource.Stop(), the variable will be set back to false and the scheduled track will never play.