我正在研究视频播放示例的统一版本。我在检查器中添加了视频播放事件处理程序脚本,并检查了M全屏模式。默认情况下,方向是横向右移。我试图在全屏播放时实现自动旋转,以便在打开设备时改变方向等等。我已经尝试了关于这个问题的建议,例如修改玩家设置等,但它没有奏效。如何在Unity和Vuforia中使用C#编写AR应用程序的视频播放自动旋转?
我的第二个问题是在导航栏上的后退按钮。当我的视频播放时,我必须按两下后退按钮才能返回相机。只要按下后退按钮,我想立即停止全屏播放。这个怎么做。
我试图用下面的代码修补(VideoPlaybackUIEventHandler.cs):
/*==============================================================================
* Copyright (c) 2012-2014 Qualcomm Connected Experiences, Inc. All Rights Reserved.
* ==============================================================================*/
using UnityEngine;
using System.Collections;
using Vuforia;
/// <summary>
/// UI Event Handler class that handles events generated by user-tap actions
/// over the UI Options Menu
/// </summary>
public class VideoPlaybackUIEventHandler : ISampleAppUIEventHandler
{
#region PUBLIC_MEMBER_VARIABLES
public override event System.Action CloseView;
public override event System.Action GoToAboutPage;
public bool mFullScreenMode;
#endregion PUBLIC_MEMBER_VARIABLES
#region PRIVATE_MEMBER_VARIABLES
private static bool sExtendedTrackingIsEnabled;
private VideoPlaybackUIView mView;
private bool mCameraFacingFront;
#endregion PRIVATE_MEMBER_VARIABLES
#region PUBLIC_MEMBER_PROPERTIES
public VideoPlaybackUIView View
{
get
{
if (mView == null)
{
mView = new VideoPlaybackUIView();
mView.LoadView();
}
return mView;
}
}
/// <summary>
/// Currently, there is no mechanism to query the SDK to know whether or not extended tracking is enabled/disabled.
/// Therefore, it needs to be handled at the app layer.
/// </value>
public static bool ExtendedTrackingIsEnabled
{
get
{
return sExtendedTrackingIsEnabled;
}
}
#endregion PUBLIC_MEMBER_PROPERTIES
#region PUBLIC_METHODS
public override void UpdateView(bool tf)
{
this.View.UpdateUI(tf);
}
public override void Bind()
{
this.View.mExtendedTracking.TappedOn += OnTappedToTurnOnTraking;
this.View.mCameraFlashSettings.TappedOn += OnTappedToTurnOnFlash;
this.View.mAutoFocusSetting.TappedOn += OnTappedToTurnOnAutoFocus;
this.View.mCameraFacing.TappedOnOption += OnTappedToTurnCameraFacing;
this.View.mCloseButton.TappedOn += OnTappedOnCloseButton;
this.View.mAboutLabel.TappedOn += OnTappedOnAboutButton;
this.View.mPlayFullscreeSettings.TappedOn += OnTappedOnFullscreenButton;
// register qcar started callback
QCARAbstractBehaviour qcarBehaviour = (QCARAbstractBehaviour)FindObjectOfType(typeof(QCARAbstractBehaviour));
if (qcarBehaviour)
{
qcarBehaviour.RegisterQCARStartedCallback(EnableContinuousAutoFocus);
qcarBehaviour.RegisterOnPauseCallback(OnPause);
}
}
public override void UnBind()
{
this.View.mExtendedTracking.TappedOn -= OnTappedToTurnOnTraking;
this.View.mCameraFlashSettings.TappedOn -= OnTappedToTurnOnFlash;
this.View.mAutoFocusSetting.TappedOn -= OnTappedToTurnOnAutoFocus;
this.View.mCameraFacing.TappedOnOption -= OnTappedToTurnCameraFacing;
this.View.mCloseButton.TappedOn -= OnTappedOnCloseButton;
this.View.mAboutLabel.TappedOn -= OnTappedOnAboutButton;
this.View.mPlayFullscreeSettings.TappedOn -= OnTappedOnFullscreenButton;
// unregister qcar started callback
QCARAbstractBehaviour qcarBehaviour = (QCARAbstractBehaviour)FindObjectOfType(typeof(QCARAbstractBehaviour));
if (qcarBehaviour)
{
qcarBehaviour.UnregisterQCARStartedCallback(EnableContinuousAutoFocus);
qcarBehaviour.UnregisterOnPauseCallback(OnPause);
}
this.View.UnLoadView();
}
//SingleTap Gestures are captured by AppManager and calls this method for TapToFocus
public override void TriggerAutoFocus()
{
StartCoroutine(TriggerAutoFocusAndEnableContinuousFocusIfSet());
}
#endregion PUBLIC_METHODS
#region PRIVATE_METHODS
/// <summary>
/// Activating trigger autofocus mode unsets continuous focus mode (if was previously enabled from the UI Options Menu)
/// So, we wait for a second and turn continuous focus back on (if options menu shows as enabled)
/// </returns>
private IEnumerator TriggerAutoFocusAndEnableContinuousFocusIfSet()
{
//triggers a single autofocus operation
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_TRIGGERAUTO;
}
yield return new WaitForSeconds(1.0f);
//continuous focus mode is turned back on if it was previously enabled from the options menu
if (this.View.mAutoFocusSetting.IsEnabled)
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO;
}
}
Debug.Log(this.View.FocusMode);
}
private void OnPause(bool pause)
{
if (!pause && this.View.mAutoFocusSetting.IsEnabled)
{
// set to continous autofocus
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
}
//On hitting the home button, the app tends to turn off the flash
//So, setting the UI to reflect that
this.View.mCameraFlashSettings.Enable(pause);
}
private void OnTappedOnAboutButton(bool tf)
{
if (this.GoToAboutPage != null)
{
this.GoToAboutPage();
}
}
//We want autofocus to be enabled when the app starts
private void EnableContinuousAutoFocus()
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO;
this.View.mAutoFocusSetting.Enable(true);
}
}
private void OnTappedToTurnOnTraking(bool tf)
{
if (!ExtendedTracking(tf))
{
this.View.mExtendedTracking.Enable(false);
VideoPlaybackUIEventHandler.sExtendedTrackingIsEnabled = false;
}
else
{
this.View.mExtendedTracking.Enable(tf);
VideoPlaybackUIEventHandler.sExtendedTrackingIsEnabled = tf;
}
OnTappedToClose();
}
private void OnTappedToTurnOnFlash(bool tf)
{
if (tf)
{
if (!CameraDevice.Instance.SetFlashTorchMode(true) || mCameraFacingFront)
{
this.View.mCameraFlashSettings.Enable(false);
}
}
else
{
CameraDevice.Instance.SetFlashTorchMode(false);
}
OnTappedToClose();
}
/// <summary>
/// If the video is already playing on texture, enabling it will bring the video to full-screen
/// otherwise, the video will play on fullscreen the next time user taps on the texture.
/// </summary>
/// <param name="tf"></param>
private void OnTappedOnFullscreenButton(bool tf)
{
mFullScreenMode = tf;
if (tf)
{
VideoPlaybackBehaviour video = PickVideo();
if (video != null)
{
if (video.VideoPlayer.IsPlayableFullscreen())
{
//On Android, we use Unity's built in player, so Unity application pauses before going to fullscreen.
//So we have to handle the orientation from within Unity.
#if UNITY_ANDROID
Screen.orientation = ScreenOrientation.Portrait;
#endif
// Pause the video if it is currently playing
video.VideoPlayer.Pause();
// Seek the video to the beginning();
video.VideoPlayer.SeekTo(0.0f);
// Display the busy icon
video.ShowBusyIcon();
// Play the video full screen
StartCoroutine (PlayVideo.PlayFullscreenVideoAtEndOfFrame(video));
//Flash turns off automatically on fullscreen videoplayback mode, so we need to update the UI accordingly
this.View.mCameraFlashSettings.Enable(false);
}
}
}
OnTappedToClose();
}
private VideoPlaybackBehaviour PickVideo()
{
VideoPlaybackBehaviour[] behaviours = GameObject.FindObjectsOfType(typeof(VideoPlaybackBehaviour)) as VideoPlaybackBehaviour[];
VideoPlaybackBehaviour video = null;
foreach (VideoPlaybackBehaviour bhvr in behaviours)
{
if (bhvr.CurrentState == VideoPlayerHelper.MediaState.PLAYING)
{
video = bhvr;
}
}
return video;
}
private void OnTappedToTurnOnAutoFocus(bool tf)
{
if (tf)
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO;
}
else
{
this.View.mAutoFocusSetting.Enable(false);
}
}
else
{
if (CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL))
{
this.View.FocusMode = CameraDevice.FocusMode.FOCUS_MODE_NORMAL;
}
}
OnTappedToClose();
}
private void OnTappedToTurnCameraFacing(int val)
{
if (val == 0)
{
//internally, flash is always turned off everytime it tries to switch to front camera
//so updating the UI options to reflect that.
this.View.mCameraFlashSettings.Enable(false);
if (ChangeCameraDirection(CameraDevice.CameraDirection.CAMERA_FRONT))
{
mCameraFacingFront = true;
}
else
{
ChangeCameraDirection(CameraDevice.CameraDirection.CAMERA_BACK);
mCameraFacingFront = false;
this.View.mCameraFacing.EnableIndex(1);
}
}
else
{
ChangeCameraDirection(CameraDevice.CameraDirection.CAMERA_BACK);
mCameraFacingFront = false;
}
OnTappedToClose();
}
private bool stopRunningObjectTracker()
{
bool needsObjectTrackerRestart = false;
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
if (objectTracker != null)
{
if (objectTracker.IsActive)
{
objectTracker.Stop();
needsObjectTrackerRestart = true;
}
}
return needsObjectTrackerRestart;
}
private bool restartRunningObjectTracker()
{
bool hasObjectTrackerRestarted = false;
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
if (objectTracker != null)
{
if (!objectTracker.IsActive)
{
hasObjectTrackerRestarted = objectTracker.Start();
}
}
return hasObjectTrackerRestarted;
}
private void ResetCameraFacingToBack()
{
bool needsObjectTrackerRestart = stopRunningObjectTracker();
CameraDevice.Instance.Stop();
CameraDevice.Instance.Init(CameraDevice.CameraDirection.CAMERA_BACK);
CameraDevice.Instance.Start();
mCameraFacingFront = false;
if (needsObjectTrackerRestart)
restartRunningObjectTracker();
}
private bool ChangeCameraDirection(CameraDevice.CameraDirection direction)
{
bool directionSupported = false;
bool needsObjectTrackerRestart = stopRunningObjectTracker();
CameraDevice.Instance.Stop();
CameraDevice.Instance.Deinit();
if (CameraDevice.Instance.Init(direction))
{
directionSupported = true;
}
CameraDevice.Instance.Start();
if (needsObjectTrackerRestart)
restartRunningObjectTracker();
return directionSupported;
}
private void OnTappedToClose()
{
if (this.CloseView != null)
{
this.CloseView();
}
}
private void OnTappedOnCloseButton()
{
OnTappedToClose();
}
/// <summary>
/// This method turns extended tracking on or off for all currently available targets.
/// Extended tracking allows to track targets when they are not in view.
/// Returns true of extended tracking is supported; false otherwise
/// </summary>
private bool ExtendedTracking(bool tf)
{
// the StateManager gives access to all available TrackableBehavours
StateManager stateManager = TrackerManager.Instance.GetStateManager();
// We iterate over all TrackableBehaviours to start or stop extended tracking for the targets they represent.
bool extendedTrackingStateChanged = true;
foreach (var behaviour in stateManager.GetTrackableBehaviours())
{
var imageBehaviour = behaviour as ImageTargetBehaviour;
if (imageBehaviour != null)
{
if (tf)
{
//only if extended tracking is supported
if (!imageBehaviour.ImageTarget.StartExtendedTracking())
{
extendedTrackingStateChanged = false;
}
}
else
{
if (!imageBehaviour.ImageTarget.StopExtendedTracking())
{
extendedTrackingStateChanged = false;
}
}
}
}
if (!extendedTrackingStateChanged)
{
Debug.LogWarning("Extended Tracking Failed!");
}
return extendedTrackingStateChanged;
}
#endregion PRIVATE_METHODS
}
和这个代码以及(PlayVideo.cs):
/*==============================================================================
* Copyright (c) 2012-2014 Qualcomm Connected Experiences, Inc. All Rights Reserved.
* ==============================================================================*/
using UnityEngine;
using System.Collections;
using Vuforia;
/// <summary>
/// Demonstrates how to play the video on texture and full-screen mode.
/// Single tapping on texture will play the video on texture (if the 'Play FullScreen' Mode in the UIMenu is turned off)
/// or play full screen (if the option is enabled in the UIMenu)
/// At any time during the video playback, it can be brought to full-screen by enabling the options from the UIMenu.
/// </summary>
public class PlayVideo : MonoBehaviour
{
private bool mVideoIsPlaying;
private VideoPlaybackBehaviour currentVideo;
#region UNITY_MONOBEHAVIOUR_METHODS
void Start()
{
InputController.SingleTapped += HandleSingleTap;
InputController.DoubleTapped += HandleDoubleTap;
}
void OnApplicationPause(bool tf)
{
//When the video finishes playing on fullscreen mode, Unity application unpauses and that's when we need to switch to potrait
//in order to display the UI menu options properly
#if UNITY_ANDROID
if(!tf) {
Screen.orientation = ScreenOrientation.Portrait;
}
#endif
}
#endregion UNITY_MONOBEHAVIOUR_METHODS
#region PRIVATE_METHODS
/// <summary>
/// Just in case the device is in any other mode at the time the user double taps to bring up the UI menu, we force it to go to potrait
/// because the UI menu supports only potrait for now.
/// </summary>
private void HandleDoubleTap()
{
if (Screen.orientation != ScreenOrientation.Portrait)
{
Screen.orientation = ScreenOrientation.Portrait;
}
}
/// <summary>
/// Handle single tap event
/// </summary>
private void HandleSingleTap()
{
if (QCARRuntimeUtilities.IsPlayMode())
{
if (PickVideo(Input.mousePosition) != null)
Debug.LogWarning("Playing videos is currently not supported in Play Mode.");
}
// Find out which video was tapped, if any
currentVideo = PickVideo(Input.mousePosition);
if (currentVideo != null)
{
if (IsFullScreenModeEnabled())
{
if (currentVideo.VideoPlayer.IsPlayableFullscreen())
{
//On Android, we use Unity's built in player, so Unity application pauses before going to fullscreen.
//So we have to handle the orientation from within Unity.
#if UNITY_ANDROID
Screen.autorotateToPortrait = true;
Screen.autorotateToPortraitUpsideDown = true;
Screen.orientation = ScreenOrientation.AutoRotation;
#endif
// Pause the video if it is currently playing
currentVideo.VideoPlayer.Pause();
// Seek the video to the beginning();
currentVideo.VideoPlayer.SeekTo(0.0f);
// Display the busy icon
currentVideo.ShowBusyIcon();
// Play the video full screen
StartCoroutine(PlayFullscreenVideoAtEndOfFrame(currentVideo));
UpdateFlashSettingsInUIView();
}
}
else
{
if (currentVideo.VideoPlayer.IsPlayableOnTexture())
{
// This video is playable on a texture, toggle playing/paused
VideoPlayerHelper.MediaState state = currentVideo.VideoPlayer.GetStatus();
if (state == VideoPlayerHelper.MediaState.PAUSED ||
state == VideoPlayerHelper.MediaState.READY ||
state == VideoPlayerHelper.MediaState.STOPPED)
{
// Pause other videos before playing this one
PauseOtherVideos(currentVideo);
// Play this video on texture where it left off
currentVideo.VideoPlayer.Play(false, currentVideo.VideoPlayer.GetCurrentPosition());
}
else if (state == VideoPlayerHelper.MediaState.REACHED_END)
{
// Pause other videos before playing this one
PauseOtherVideos(currentVideo);
// Play this video from the beginning
currentVideo.VideoPlayer.Play(false, 0);
}
else if (state == VideoPlayerHelper.MediaState.PLAYING)
{
// Video is already playing, pause it
currentVideo.VideoPlayer.Pause();
}
}
else
{
// Display the busy icon
currentVideo.ShowBusyIcon();
// This video cannot be played on a texture, play it full screen
StartCoroutine(PlayFullscreenVideoAtEndOfFrame(currentVideo));
}
}
}
}
public static IEnumerator PlayFullscreenVideoAtEndOfFrame(VideoPlaybackBehaviour video)
{
Screen.orientation = ScreenOrientation.AutoRotation;
Screen.autorotateToPortrait = true;
Screen.autorotateToPortraitUpsideDown = true;
Screen.autorotateToLandscapeLeft = true;
Screen.autorotateToLandscapeRight = true;
yield return new WaitForEndOfFrame();
// we wait a bit to allow the ScreenOrientation.AutoRotation to become effective
yield return new WaitForSeconds (0.3f);
video.VideoPlayer.Play(true, 0);
}
//Flash turns off automatically on fullscreen videoplayback mode, so we need to update the UI accordingly
private void UpdateFlashSettingsInUIView()
{
VideoPlaybackUIEventHandler handler = GameObject.FindObjectOfType(typeof(VideoPlaybackUIEventHandler)) as VideoPlaybackUIEventHandler;
if (handler != null)
{
handler.View.mCameraFlashSettings.Enable(false);
}
}
/// <summary>
/// Checks to see if the 'Play FullScreen' Mode is enabled/disabled in the UI Menu
/// </summary>
/// <returns></returns>
private bool IsFullScreenModeEnabled()
{
VideoPlaybackUIEventHandler handler = FindObjectOfType(typeof(VideoPlaybackUIEventHandler)) as VideoPlaybackUIEventHandler;
if (handler != null)
{
return handler.mFullScreenMode;
}
return false;
}
/// <summary>
/// Find the video object under the screen point
/// </summary>
private VideoPlaybackBehaviour PickVideo(Vector3 screenPoint)
{
VideoPlaybackBehaviour[] videos = (VideoPlaybackBehaviour[])
FindObjectsOfType(typeof(VideoPlaybackBehaviour));
GameObject go = QCARManager.Instance.ARCameraTransform.gameObject;
Camera[] cam = go.GetComponentsInChildren<Camera>();
Ray ray = cam[0].ScreenPointToRay(screenPoint);
RaycastHit hit = new RaycastHit();
foreach (VideoPlaybackBehaviour video in videos)
{
if (video.GetComponent<Collider>().Raycast(ray, out hit, 10000))
{
return video;
}
}
return null;
}
/// <summary>
/// Pause all videos except this one
/// </summary>
private void PauseOtherVideos(VideoPlaybackBehaviour currentVideo)
{
VideoPlaybackBehaviour[] videos = (VideoPlaybackBehaviour[])
FindObjectsOfType(typeof(VideoPlaybackBehaviour));
foreach (VideoPlaybackBehaviour video in videos)
{
if (video != currentVideo)
{
if (video.CurrentState == VideoPlayerHelper.MediaState.PLAYING)
{
video.VideoPlayer.Pause();
}
}
}
}
#endregion // PRIVATE_METHODS
}
在这两种代码,所述在HandleSingleTap方法和OnTappedOnFullScreen方法中,你会看到#IF UNITY_ANDROID,我尝试在Unity脚本中使用Screen.orientation进行游戏。具体而言,我尝试以下,实现自动旋转,但它并没有帮助:
Screen.autorotateToPortrait = true;
Screen.autorotateToPortraitUpsideDown = true;
Screen.autorotateToLandscapeLeft = true;
Screen.autorotateToLandscapeRight = true;
Screen.orientation = ScreenOrientation.AutoRotation;
当我做只有一个方向,就像他们在代码一样,比如:Screen.orientation = ScreenOrientation。 LandscapeRight的方向改变了。但那不是我想要的。
任何帮助/提示,将appeciated!
谢谢。
我使用统一版本5.1.0f3。我刚刚注意到Unity今天发布了一个更新的版本,这可能是解决方案。播放器设置可能在5.1.0f3版本中有问题。 –
更新到最新版本没有任何影响。这仍然没有解决。 –