在 Unity3d 中使用 Android 上的音量按钮

Tha*_*oad 3 android unity-game-engine

我正在尝试在 Android 上的 unity3d 游戏中使用音量按钮。不幸的是,我看不到任何与映射为 KeyCode 的卷有关的内容,因此在我看来 Unity3d 中没有此功能。有没有更隐蔽的方法来做到这一点?有没有办法解决这个问题?它的应用是在按下音量按钮时简单地发送一个 UDP 数据包,因此它不需要与 Unity3d 应用程序本身进行交互。可能是一个可以处理它的后台进程?我只是想要关于要遵循的路径的建议,因为我不想浪费时间为我的解决方案寻找错误的树。提前致谢!

小智 6

另一种方法是使用手机音量(好吧,这是一种解决方法^^)。如果音量增加,则按下音量按钮“UP”。或者,如果音量减小,则表示按下了音量按钮“DOWN”。要访问电话音量,我使用了这个 stackoverflow 答案: Unity3D:是否可以检查 Android 和 iPhone 设备的音量?

这是我的 android 解决方案(我没有处理 ios 的能力,但我想以前的答案提供了一些线索):

public static class Common {

    private static AndroidJavaObject s_mainActivity = null;
    private static AndroidJavaObject s_androidAudioManager = null;

    public static AndroidJavaObject GetAndroidAudioManager()
    {
        if (s_androidAudioManager == null)
        {
            s_androidAudioManager = GetMainActivity().Call<AndroidJavaObject>("getSystemService", "audio");
        }
        return s_androidAudioManager;
    }

    public static AndroidJavaObject GetMainActivity()
    {
        if (s_mainActivity == null)
        {
            var unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            s_mainActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
        }
        return s_mainActivity;
    }

    public static bool IsRunningOnAndroid()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
        return true;
#else
        return false;
#endif
    }
}



using UnityEngine;
using System.Collections.Generic;

public interface VolumeListener
{
     void OnVolumeUp();
     void OnVolumeDown();
}

public abstract class VolumeListenerGO : MonoBehaviour, VolumeListener
{
    public abstract void OnVolumeUp();
    public abstract void OnVolumeDown();
}


public class VolumeButton : MonoBehaviour {

    public bool m_bGetVolumeFromPhone = true;
    //for non gameobject listener
    public List<VolumeListener> m_vVolumeListener = null;
    //for gameobject listener (easier to edit in scene mode)
    public VolumeListenerGO[] m_vVolumeListenerGO = null;

    private float m_fPrevVolume = -1;
    private bool m_bShutDown = false;

    //quick access to reference
    private static VolumeButton s_instance = null;


    public static VolumeButton Get()
    {
        return s_instance;
    }

    //Get phone volume if running or android or application volume if running on pc
    //(or wanted by user)
    public float GetVolume()
    {
        if(m_bGetVolumeFromPhone && Common.IsRunningOnAndroid())
        {
            AndroidJavaObject audioManager = Common.GetAndroidAudioManager();
            return audioManager.Call<int>("getStreamVolume", 3);
        }
        else
        {
            return AudioListener.volume;
        }

    }

    //set phone or application volume (according if running on android or if user want application volume)
    public void SetVolume(float a_fVolume)
    {
        if (m_bGetVolumeFromPhone && Common.IsRunningOnAndroid())
        {
            AndroidJavaObject audioManager = Common.GetAndroidAudioManager();
            audioManager.Call("setStreamVolume", 3, (int)a_fVolume, 0);
        }
        else
        {
            AudioListener.volume = a_fVolume;
        }
    }

    private void ResetVolume()
    {
        SetVolume(m_fPrevVolume);
    }

    void Start () {
        s_instance = this;
        PowerOn();
    }

    void OnVolumeDown()
    {
        if (m_vVolumeListener != null)
        {
            foreach (VolumeListener listener in m_vVolumeListener)
            {
                listener.OnVolumeDown();
            }
        }
        if (m_vVolumeListenerGO != null)
        {
            foreach (VolumeListener listener in m_vVolumeListenerGO)
            {
                listener.OnVolumeDown();
            }
        }
    }

    void OnVolumeUp()
    {
        if (m_vVolumeListener != null)
        {
            foreach (VolumeListener listener in m_vVolumeListener)
            {
                listener.OnVolumeUp();
            }
        }
        if (m_vVolumeListenerGO != null)
        {
            foreach (VolumeListener listener in m_vVolumeListenerGO)
            {
                listener.OnVolumeUp();
            }
        }

    }

    //If user want to change volume, he has to mute this script first
    //else the script will interpret this has a user input and resetvolume
    public void ShutDown()
    {
        m_bShutDown = true;
    }

    //to unmute the script
    public void PowerOn()
    {
        m_bShutDown = false;
        //get the volume to avoid interpretating previous change (when script was muted) as user input
        m_fPrevVolume = GetVolume();
    }

    // Update is called once per frame
    void Update () {
        if (m_bShutDown)
            return;

        float fCurrentVolume = GetVolume();
        float fDiff = fCurrentVolume - m_fPrevVolume;

        //if volume change, compute the difference and call listener according to
        if(fDiff < 0)
        { 
            ResetVolume();
            OnVolumeDown(); 
        }
        else if(fDiff > 0)
        {
            ResetVolume();
            OnVolumeUp();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我在 samsung note 4 上对其进行了测试。也可以使用 SamsungGear Input 在 VR 模式下工作。希望它可以为某人服务。

编辑:

如果音量最小或最大,则此解决方案不起作用。因此,您必须先将音量设置在最小和最大音量之间。

//to unmute the script
public void PowerOn()
{
    m_bShutDown = false;
    //get the volume to avoid interpretating previous change (when script was muted) as user input
    m_fPrevVolume = GetVolume();

    //if volume is set to max, reduce it -> if not, there will be no detection for volume up
    if (m_fPrevVolume == GetMaxVolume())
    {
        --m_fPrevVolume;
        SetVolume(m_fPrevVolume);
    }

}

//Get max volume phone
public float GetMaxVolume()
{
    if (m_bGetVolumeFromPhone && Common.IsRunningOnAndroid())
    {
        AndroidJavaObject audioManager = Common.GetAndroidAudioManager();
        return audioManager.Call<int>("getStreamMaxVolume", 3);
    }
    else
    {
        return 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

在那里找到了获取最大音量的方法:

Android:如何以最大音量播放音乐?