不同的声音、不同的图像目标和一个按钮。 Vuforia(Unity3d)
Different sounds, different imageTargets and one button. Vuforia (Unity3d)
我将识别几个 imageTargets,我想用 onClick(button) 播放声音。此按钮位于 canvas 上,并且在应用程序生命周期内始终位于顶部。所以你总能看到它。在这个按钮后面你可以看到相机视图和识别标记。
F.e 我有两个标记:狗和牛。
狗已分配音频 - 吠声。
牛已分配音频-muu.
当我识别出 Cow -> 单击按钮时,它应该会发出 muu 的声音,但是当我识别出 Dog 时,同样的按钮,在单击时应该会发出吠声。
这是一个问题。我无法解决它。我想我应该为这个按钮编写一个脚本来为适当的标记播放 onClick 声音,但我不知道如何告诉按钮现在我可以看到 Cow 而另一次我可以看到 Dog。
我制作了一个在识别图像时播放声音的脚本,但我想用按钮来做。
如果有什么地方不够清楚 - 让我知道,我会写得更好或再写一次。
到目前为止,在我的 "Default trackable event handler" 中,这是值得的:
using UnityEngine;
using Vuforia;
public class DefaultTrackableEventHandlerEng : MonoBehaviour, ITrackableEventHandler
{
//------------Begin Sound----------
public AudioSource soundTarget;
public AudioClip clipTarget;
private AudioSource[] allAudioSources;
//function to stop all sounds
void StopAllAudio()
{
allAudioSources = FindObjectsOfType(typeof(AudioSource)) as AudioSource[];
foreach (AudioSource audioS in allAudioSources)
{
audioS.Stop();
}
}
//function to play sound
void playSound(string ss)
{
clipTarget = (AudioClip)Resources.Load(ss);
soundTarget.clip = clipTarget;
soundTarget.loop = false;
soundTarget.playOnAwake = false;
soundTarget.Play();
}
//-----------End Sound------------
#region PROTECTED_MEMBER_VARIABLES
protected TrackableBehaviour mTrackableBehaviour;
protected TrackableBehaviour.Status m_PreviousStatus;
protected TrackableBehaviour.Status m_NewStatus;
#endregion // PROTECTED_MEMBER_VARIABLES
#region UNITY_MONOBEHAVIOUR_METHODS
protected virtual void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if (mTrackableBehaviour)
mTrackableBehaviour.RegisterTrackableEventHandler(this);
//Register / add the AudioSource as object
soundTarget = (AudioSource)gameObject.AddComponent<AudioSource>();
}
protected virtual void OnDestroy()
{
if (mTrackableBehaviour)
mTrackableBehaviour.UnregisterTrackableEventHandler(this);
}
#endregion // UNITY_MONOBEHAVIOUR_METHODS
#region PUBLIC_METHODS
/// <summary>
/// Implementation of the ITrackableEventHandler function called when the
/// tracking state changes.
/// </summary>
///
public void OnTrackableStateChanged(
TrackableBehaviour.Status previousStatus,
TrackableBehaviour.Status newStatus)
{
m_PreviousStatus = previousStatus;
m_NewStatus = newStatus;
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
if (mTrackableBehaviour.TrackableName == "1")
{
playSound("audio/1_eng");
}
if (mTrackableBehaviour.TrackableName == "2")
{
playSound("audio/2_eng");
}
if (mTrackableBehaviour.TrackableName == "3")
{
playSound("audio/3_eng");
}
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
StopAllAudio();
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
}
}
#endregion // PUBLIC_METHODS
#region PROTECTED_METHODS
protected virtual void OnTrackingFound()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Enable rendering:
foreach (var component in rendererComponents)
component.enabled = true;
// Enable colliders:
foreach (var component in colliderComponents)
component.enabled = true;
// Enable canvas':
foreach (var component in canvasComponents)
component.enabled = true;
}
protected virtual void OnTrackingLost()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Disable rendering:
foreach (var component in rendererComponents)
component.enabled = false;
// Disable colliders:
foreach (var component in colliderComponents)
component.enabled = false;
// Disable canvas':
foreach (var component in canvasComponents)
component.enabled = false;
}
#endregion // PROTECTED_METHODS
}
因此,如果我对您的理解正确,您的代码基本上可以正常工作,但您不想直接为识别的目标播放相应的声音,而是只想在单击按钮时播放它,对吗?
您可以简单地添加一个方法 PlayCurrentSound
并在 onClick
:
中引用它
// SET THIS NAME INSTEAD OF DIRECTLY PLAYING IT
private string currentSoundName;
// THIS IS THE METHOD CALLED BY THE BUTTON
public void PlayCurrentSound()
{
if(!string.IsNullOrWhiteSpace(currentSoundName)) playSound(currentSoundName);
}
而在 OnTrackableStateChanged
中只更改 currentSoundName
的值而不是直接重播它
public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus)
{
m_PreviousStatus = previousStatus;
m_NewStatus = newStatus;
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
// HERE BETTER USE A SWITCH INSTEAD
switch(mTrackableBehaviour.TrackableName)
{
case "1":
currentSoundName = "audio/1_eng";
break;
case "2":
currentSoundName = "audio/2_eng";
break;
case "3":
currentSoundName = "audio/3_eng";
break;
default:
currentSoundName = "";
break;
}
// OR ALTERNATIVELY IF YOU ANYWAY WANT TO
// SET THE NAME FOR ALL POSSIBLE NAMES YOU COULD EVEN GO
currentSoundName = string.Format("audio/{0}_eng", mTrackableBehaviour.TrackableName);
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
StopAllAudio();
// RESET currentSoundName
currentSoundName = "";
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
// RESET currentSoundName
currentSoundName = "";
}
}
但是还有一些其他的小东西我也会改变:
soundTarget.loop = false;
soundTarget.playOnAwake = false;
这已经可以在游戏开始时完成,只能执行一次,不应每次都重复。所以这样做:
private void Awake()
{
soundTarget.loop = false;
soundTarget.playOnAwake = false;
}
比
clipTarget = (AudioClip)Resources.Load(ss);
从资源中一遍又一遍地加载(也许)相同的声音……效率不高。您可能希望在加载后保留引用,如
private Dictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>();
void playSound(string ss)
{
if(clips.ContainsKey(ss) && clip[ss] != null)
{
clipTarget = clips[ss];
else
{
clip = (AudioClip)Resources.Load(ss);
if(clipTarget == null)
{
Debug.LogError("Couldn't get clip for " + ss, this);
return;
}
clips.Add(ss, clipTarget);
}
soundTarget.clip = clipTarget;
soundTarget.Play();
}
您可能还想改用 soundTarget.PlayOneShot(clipTarget)
。不同之处在于 PlayOneShot
播放整个声音并允许并发声音,而 Play
中断当前声音并开始一个新声音(取决于您的需要)。
我将识别几个 imageTargets,我想用 onClick(button) 播放声音。此按钮位于 canvas 上,并且在应用程序生命周期内始终位于顶部。所以你总能看到它。在这个按钮后面你可以看到相机视图和识别标记。
F.e 我有两个标记:狗和牛。 狗已分配音频 - 吠声。 牛已分配音频-muu.
当我识别出 Cow -> 单击按钮时,它应该会发出 muu 的声音,但是当我识别出 Dog 时,同样的按钮,在单击时应该会发出吠声。 这是一个问题。我无法解决它。我想我应该为这个按钮编写一个脚本来为适当的标记播放 onClick 声音,但我不知道如何告诉按钮现在我可以看到 Cow 而另一次我可以看到 Dog。
我制作了一个在识别图像时播放声音的脚本,但我想用按钮来做。
如果有什么地方不够清楚 - 让我知道,我会写得更好或再写一次。
到目前为止,在我的 "Default trackable event handler" 中,这是值得的:
using UnityEngine;
using Vuforia;
public class DefaultTrackableEventHandlerEng : MonoBehaviour, ITrackableEventHandler
{
//------------Begin Sound----------
public AudioSource soundTarget;
public AudioClip clipTarget;
private AudioSource[] allAudioSources;
//function to stop all sounds
void StopAllAudio()
{
allAudioSources = FindObjectsOfType(typeof(AudioSource)) as AudioSource[];
foreach (AudioSource audioS in allAudioSources)
{
audioS.Stop();
}
}
//function to play sound
void playSound(string ss)
{
clipTarget = (AudioClip)Resources.Load(ss);
soundTarget.clip = clipTarget;
soundTarget.loop = false;
soundTarget.playOnAwake = false;
soundTarget.Play();
}
//-----------End Sound------------
#region PROTECTED_MEMBER_VARIABLES
protected TrackableBehaviour mTrackableBehaviour;
protected TrackableBehaviour.Status m_PreviousStatus;
protected TrackableBehaviour.Status m_NewStatus;
#endregion // PROTECTED_MEMBER_VARIABLES
#region UNITY_MONOBEHAVIOUR_METHODS
protected virtual void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if (mTrackableBehaviour)
mTrackableBehaviour.RegisterTrackableEventHandler(this);
//Register / add the AudioSource as object
soundTarget = (AudioSource)gameObject.AddComponent<AudioSource>();
}
protected virtual void OnDestroy()
{
if (mTrackableBehaviour)
mTrackableBehaviour.UnregisterTrackableEventHandler(this);
}
#endregion // UNITY_MONOBEHAVIOUR_METHODS
#region PUBLIC_METHODS
/// <summary>
/// Implementation of the ITrackableEventHandler function called when the
/// tracking state changes.
/// </summary>
///
public void OnTrackableStateChanged(
TrackableBehaviour.Status previousStatus,
TrackableBehaviour.Status newStatus)
{
m_PreviousStatus = previousStatus;
m_NewStatus = newStatus;
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
if (mTrackableBehaviour.TrackableName == "1")
{
playSound("audio/1_eng");
}
if (mTrackableBehaviour.TrackableName == "2")
{
playSound("audio/2_eng");
}
if (mTrackableBehaviour.TrackableName == "3")
{
playSound("audio/3_eng");
}
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
StopAllAudio();
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
}
}
#endregion // PUBLIC_METHODS
#region PROTECTED_METHODS
protected virtual void OnTrackingFound()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Enable rendering:
foreach (var component in rendererComponents)
component.enabled = true;
// Enable colliders:
foreach (var component in colliderComponents)
component.enabled = true;
// Enable canvas':
foreach (var component in canvasComponents)
component.enabled = true;
}
protected virtual void OnTrackingLost()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Disable rendering:
foreach (var component in rendererComponents)
component.enabled = false;
// Disable colliders:
foreach (var component in colliderComponents)
component.enabled = false;
// Disable canvas':
foreach (var component in canvasComponents)
component.enabled = false;
}
#endregion // PROTECTED_METHODS
}
因此,如果我对您的理解正确,您的代码基本上可以正常工作,但您不想直接为识别的目标播放相应的声音,而是只想在单击按钮时播放它,对吗?
您可以简单地添加一个方法 PlayCurrentSound
并在 onClick
:
// SET THIS NAME INSTEAD OF DIRECTLY PLAYING IT
private string currentSoundName;
// THIS IS THE METHOD CALLED BY THE BUTTON
public void PlayCurrentSound()
{
if(!string.IsNullOrWhiteSpace(currentSoundName)) playSound(currentSoundName);
}
而在 OnTrackableStateChanged
中只更改 currentSoundName
的值而不是直接重播它
public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus)
{
m_PreviousStatus = previousStatus;
m_NewStatus = newStatus;
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
// HERE BETTER USE A SWITCH INSTEAD
switch(mTrackableBehaviour.TrackableName)
{
case "1":
currentSoundName = "audio/1_eng";
break;
case "2":
currentSoundName = "audio/2_eng";
break;
case "3":
currentSoundName = "audio/3_eng";
break;
default:
currentSoundName = "";
break;
}
// OR ALTERNATIVELY IF YOU ANYWAY WANT TO
// SET THE NAME FOR ALL POSSIBLE NAMES YOU COULD EVEN GO
currentSoundName = string.Format("audio/{0}_eng", mTrackableBehaviour.TrackableName);
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
StopAllAudio();
// RESET currentSoundName
currentSoundName = "";
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
// RESET currentSoundName
currentSoundName = "";
}
}
但是还有一些其他的小东西我也会改变:
soundTarget.loop = false;
soundTarget.playOnAwake = false;
这已经可以在游戏开始时完成,只能执行一次,不应每次都重复。所以这样做:
private void Awake()
{
soundTarget.loop = false;
soundTarget.playOnAwake = false;
}
比
clipTarget = (AudioClip)Resources.Load(ss);
从资源中一遍又一遍地加载(也许)相同的声音……效率不高。您可能希望在加载后保留引用,如
private Dictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>();
void playSound(string ss)
{
if(clips.ContainsKey(ss) && clip[ss] != null)
{
clipTarget = clips[ss];
else
{
clip = (AudioClip)Resources.Load(ss);
if(clipTarget == null)
{
Debug.LogError("Couldn't get clip for " + ss, this);
return;
}
clips.Add(ss, clipTarget);
}
soundTarget.clip = clipTarget;
soundTarget.Play();
}
您可能还想改用 soundTarget.PlayOneShot(clipTarget)
。不同之处在于 PlayOneShot
播放整个声音并允许并发声音,而 Play
中断当前声音并开始一个新声音(取决于您的需要)。