【发布时间】:2018-11-16 05:39:00
【问题描述】:
我想在键盘点击时使用 unity 和 c# 将操作系统音量设置在某个级别,例如我想将 Windows 音量(不是统一)设置为 70:我该怎么做???
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
//Set Windows Volume 70%
}
}
【问题讨论】:
我想在键盘点击时使用 unity 和 c# 将操作系统音量设置在某个级别,例如我想将 Windows 音量(不是统一)设置为 70:我该怎么做???
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
//Set Windows Volume 70%
}
}
【问题讨论】:
这需要一个插件。由于这个问题是针对 Windows 的,您可以使用 IAudioEndpointVolume 构建一个 C++ plugin 然后从 C# 调用它。 This 帖子有一个有效的 C++ 示例,说明如何使用 IAudioEndpointVolume 更改音量,您可以将其用作创建 C++ 插件的基本源。
我已经开始清理该代码,然后将其转换为 dll 插件并将 DLL 放在 Assets/Plugins 文件夹中。你可以看看如何构建C++插件here。
C++ 代码:
#include "stdafx.h"
#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#define DLLExport __declspec(dllexport)
extern "C"
{
enum class VolumeUnit {
Decibel,
Scalar
};
//Gets volume
DLLExport float GetSystemVolume(VolumeUnit vUnit) {
HRESULT hr;
// -------------------------
CoInitialize(NULL);
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
IMMDevice *defaultDevice = NULL;
hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioEndpointVolume *endpointVolume = NULL;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
defaultDevice->Release();
defaultDevice = NULL;
float currentVolume = 0;
if (vUnit == VolumeUnit::Decibel) {
//Current volume in dB
hr = endpointVolume->GetMasterVolumeLevel(¤tVolume);
}
else if (vUnit == VolumeUnit::Scalar) {
//Current volume as a scalar
hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume);
}
endpointVolume->Release();
CoUninitialize();
return currentVolume;
}
//Sets volume
DLLExport void SetSystemVolume(double newVolume, VolumeUnit vUnit) {
HRESULT hr;
// -------------------------
CoInitialize(NULL);
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
IMMDevice *defaultDevice = NULL;
hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioEndpointVolume *endpointVolume = NULL;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
defaultDevice->Release();
defaultDevice = NULL;
if (vUnit == VolumeUnit::Decibel)
hr = endpointVolume->SetMasterVolumeLevel((float)newVolume, NULL);
else if (vUnit == VolumeUnit::Scalar)
hr = endpointVolume->SetMasterVolumeLevelScalar((float)newVolume, NULL);
endpointVolume->Release();
CoUninitialize();
}
}
C# 代码:
using System.Runtime.InteropServices;
using UnityEngine;
public class VolumeManager : MonoBehaviour
{
//The Unit to use when getting and setting the volume
public enum VolumeUnit
{
//Perform volume action in decibels</param>
Decibel,
//Perform volume action in scalar
Scalar
}
/// <summary>
/// Gets the current volume
/// </summary>
/// <param name="vUnit">The unit to report the current volume in</param>
[DllImport("ChangeVolumeWindows")]
public static extern float GetSystemVolume(VolumeUnit vUnit);
/// <summary>
/// sets the current volume
/// </summary>
/// <param name="newVolume">The new volume to set</param>
/// <param name="vUnit">The unit to set the current volume in</param>
[DllImport("ChangeVolumeWindows")]
public static extern void SetSystemVolume(double newVolume, VolumeUnit vUnit);
// Use this for initialization
void Start()
{
//Get volume in Decibel
float volumeDecibel = GetSystemVolume(VolumeUnit.Decibel);
Debug.Log("Volume in Decibel: " + volumeDecibel);
//Get volume in Scalar
float volumeScalar = GetSystemVolume(VolumeUnit.Scalar);
Debug.Log("Volume in Scalar: " + volumeScalar);
//Set volume in Decibel
SetSystemVolume(-16f, VolumeUnit.Decibel);
//Set volume in Scalar
SetSystemVolume(0.70f, VolumeUnit.Scalar);
}
}
GetSystemVolume 函数用于获取当前音量,SetSystemVolume 用于设置。此问题适用于 Windows,但您可以使用其他平台的 API 做类似的事情。
按下A键时将其设置为70%:
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
//Set Windows Volume 70%
SetSystemVolume(0.70f, VolumeUnit.Scalar);
}
}
【讨论】:
IMMDeviceEnumerator.GetDefaultAudioEndpoint 失败或没有可用设备,则 defaultDevice 可以是 null,这将导致 Unity 崩溃。具体来说,我在一个用户的机器上遇到了这个问题,由于驱动程序问题,没有有效的声音播放设备。 (请参阅Control Panel -> Sound -> Playback 并禁用所有设备以对此进行测试。)
据我所知,您无法做到这一点。这样做没有任何好处,您是否在任何游戏/应用程序中看到过这种情况?
您可以使用滑块更改 Unity 应用程序的主音量,还可以以相同的方式管理其他音效
http://docs.unity3d.com/ScriptReference/AudioListener.html
http://docs.unity3d.com/ScriptReference/AudioListener-volume.html
例子
public class AudioControl: MonoBehaviour {
void SetVolume(Slider slider) {
AudioListener.volume = slider.Value;
// probably save this value to a playerpref so it is remembered.
}
}
【讨论】:
System.Windows。