【问题标题】:Different sounds, different imageTargets and one button. Vuforia (Unity3d)不同的声音,不同的 imageTargets 和一个按钮。 Vuforia (Unity3d)
【发布时间】:2019-04-02 15:51:00
【问题描述】:

我要识别几个 imageTargets,我想用 onClick(button) 播放声音。此按钮位于画布上,并且在应用程序生命周期内始终位于顶部。所以你总是可以看到它。在此按钮后面,您可以查看相机视图并识别标记。

F.e 我有两个标记:Dog 和 Cow。 狗已分配音频 - 吠声。 牛已分配音频 - muu。

当我识别 Cow -> 单击按钮时,它应该给我 muu 声音,但是当我识别 Dog 时,单击相同的按钮应该给我吠声。 这是一个问题。我无法解决它。我想我应该为这个按钮编写一个脚本来为适当的标记播放声音 onClick,但我不知道如何告诉按钮现在我可以看到 Cow 并且下次我可以看到 Dog。

我制作了一个脚本,当图像被识别时播放声音,但我想用按钮来做。

如果有些地方不够清楚,请告诉我,我会写得更好或再写一次。

到目前为止,在我的“默认可跟踪事件处理程序”中,这是值得的:

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
}

【问题讨论】:

    标签: c# unity3d vuforia


    【解决方案1】:

    因此,如果我理解正确,您的代码基本上可以正常工作,但不是直接为识别的目标播放相应的声音,而是只想在单击按钮时播放它,对吧?

    您可以简单地添加一个方法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 中断当前声音并开始一个新声音(取决于您的需要)。

    【讨论】:

    • 请看最后添加的代码。 onclick PlayCurrentSound() 函数不知什么原因看不到,编辑器发誓要字符串方法。 IsNull 或 WhiteSpace。不骂,刚开始学Unity3d和c#:)
    • 抱歉它必须是 !string.IsNullOrWhiteSpace(currentSoundName) 它没有出现,因为存在编译器错误并且 Unity 到目前为止没有更新可用的方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多