using System; using System.Runtime.InteropServices; using UnityEngine; /// /// 跨平台系统控制器 /// 提供亮度、音量等系统级功能的真实控制 /// 支持 Windows、Android 等平台 /// public static class WindowsSystemController { #if UNITY_STANDALONE_WIN && !UNITY_EDITOR #region Windows API 声明 // 音量控制 API [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); [DllImport("user32.dll")] private static extern byte MapVirtualKey(uint uCode, uint uMapType); // 亮度控制 API [DllImport("dxva2.dll", SetLastError = true)] private static extern bool SetMonitorBrightness(IntPtr hMonitor, uint dwNewBrightness); [DllImport("dxva2.dll", SetLastError = true)] private static extern bool GetMonitorBrightness(IntPtr hMonitor, ref uint pdwMinimumBrightness, ref uint pdwCurrentBrightness, ref uint pdwMaximumBrightness); [DllImport("dxva2.dll", SetLastError = true)] private static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, ref uint pdwNumberOfPhysicalMonitors); [DllImport("dxva2.dll", SetLastError = true)] private static extern bool GetPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, uint dwPhysicalMonitorArraySize, [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray); [DllImport("user32.dll")] private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); [DllImport("dxva2.dll", SetLastError = true)] private static extern bool DestroyPhysicalMonitors(uint dwPhysicalMonitorArraySize, [In] PHYSICAL_MONITOR[] pPhysicalMonitorArray); // WMI 相关 API (备用亮度控制方案) [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool FreeLibrary(IntPtr hModule); // 时间设置 API [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetSystemTime(ref SYSTEMTIME lpSystemTime); [DllImport("kernel32.dll", SetLastError = true)] private static extern void GetSystemTime(out SYSTEMTIME lpSystemTime); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetLocalTime(ref SYSTEMTIME lpSystemTime); [DllImport("kernel32.dll", SetLastError = true)] private static extern void GetLocalTime(out SYSTEMTIME lpSystemTime); #endregion #region 常量定义 // 音量控制常量 private const byte VK_VOLUME_MUTE = 0xAD; private const byte VK_VOLUME_DOWN = 0xAE; private const byte VK_VOLUME_UP = 0xAF; private const uint KEYEVENTF_EXTENDEDKEY = 0x0001; private const uint KEYEVENTF_KEYUP = 0x0002; #endregion #region 结构体定义 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct PHYSICAL_MONITOR { public IntPtr hPhysicalMonitor; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string szPhysicalMonitorDescription; } private delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData); [StructLayout(LayoutKind.Sequential)] public struct Rect { public int left; public int top; public int right; public int bottom; } [StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; } #endregion #region 音量控制 /// /// 设置系统音量到指定百分比 /// /// 音量百分比 (0-100) public static bool SetSystemVolume(int volumePercent) { try { // 获取当前音量 int currentVolume = GetCurrentSystemVolume(); if (currentVolume == -1) return false; int targetVolume = Mathf.Clamp(volumePercent, 0, 100); int difference = targetVolume - currentVolume; // 根据差值调整音量 if (difference > 0) { for (int i = 0; i < Math.Abs(difference); i += 2) // 每次大约调整2% { SystemVolumeUp(); System.Threading.Thread.Sleep(10); // 短暂延时确保命令执行 } } else if (difference < 0) { for (int i = 0; i < Math.Abs(difference); i += 2) // 每次大约调整2% { SystemVolumeDown(); System.Threading.Thread.Sleep(10); // 短暂延时确保命令执行 } } Debug.Log($"WindowsSystemController: 音量已设置为 {targetVolume}%"); return true; } catch (Exception ex) { Debug.LogError($"WindowsSystemController: 设置音量失败: {ex.Message}"); return false; } } /// /// 增加系统音量 /// public static void SystemVolumeUp() { keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY, 0); keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); } /// /// 降低系统音量 /// public static void SystemVolumeDown() { keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY, 0); keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); } /// /// 切换系统静音状态 /// public static void SystemMute() { keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY, 0); keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); } /// /// 获取当前系统音量 (简化估算,实际实现可能需要更复杂的 API) /// private static int GetCurrentSystemVolume() { // 这是一个简化版本,实际实现需要使用 Windows Volume API // 目前返回 -1 表示无法获取,使用相对调整 return -1; } #endregion #region 亮度控制 /// /// 设置显示器亮度 /// /// 亮度百分比 (0-100) public static bool SetMonitorBrightness(int brightnessPercent) { try { uint brightness = (uint)Mathf.Clamp(brightnessPercent, 0, 100); // 方法1: 尝试使用 DXVA2 API if (SetBrightnessViaDDC(brightness)) { Debug.Log($"WindowsSystemController: 亮度已通过DDC设置为 {brightness}%"); return true; } // 方法2: 尝试使用 WMI (需要管理员权限) if (SetBrightnessViaWMI(brightness)) { Debug.Log($"WindowsSystemController: 亮度已通过WMI设置为 {brightness}%"); return true; } // 方法3: 使用 PowerShell 命令 (备用方案) if (SetBrightnessViaPowerShell(brightness)) { Debug.Log($"WindowsSystemController: 亮度已通过PowerShell设置为 {brightness}%"); return true; } Debug.LogWarning("WindowsSystemController: 所有亮度控制方法都失败了"); return false; } catch (Exception ex) { Debug.LogError($"WindowsSystemController: 设置亮度失败: {ex.Message}"); return false; } } /// /// 通过 DDC/CI 设置亮度 (外接显示器) /// private static bool SetBrightnessViaDDC(uint brightness) { try { bool success = false; EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, (IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData) => { uint numPhysicalMonitors = 0; if (GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, ref numPhysicalMonitors) && numPhysicalMonitors > 0) { PHYSICAL_MONITOR[] physicalMonitors = new PHYSICAL_MONITOR[numPhysicalMonitors]; if (GetPhysicalMonitorsFromHMONITOR(hMonitor, numPhysicalMonitors, physicalMonitors)) { for (uint i = 0; i < numPhysicalMonitors; i++) { if (SetMonitorBrightness(physicalMonitors[i].hPhysicalMonitor, brightness)) { success = true; Debug.Log($"成功设置显示器 {physicalMonitors[i].szPhysicalMonitorDescription} 亮度为 {brightness}%"); } } DestroyPhysicalMonitors(numPhysicalMonitors, physicalMonitors); } } return true; // 继续枚举 }, IntPtr.Zero); return success; } catch (Exception ex) { Debug.LogError($"DDC亮度控制失败: {ex.Message}"); return false; } } /// /// 通过 WMI 设置亮度 (笔记本内置屏幕) /// private static bool SetBrightnessViaWMI(uint brightness) { try { // 使用 WMI 设置亮度 (需要 System.Management 或者 PowerShell) // 这里使用简化的 PowerShell 调用方式 string script = $"(Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,{brightness})"; return ExecutePowerShellCommand(script); } catch (Exception ex) { Debug.LogError($"WMI亮度控制失败: {ex.Message}"); return false; } } /// /// 通过 PowerShell 设置亮度 /// private static bool SetBrightnessViaPowerShell(uint brightness) { try { // 使用 Windows 10/11 的现代亮度控制 string script = $@" Add-Type -AssemblyName System.Windows.Forms $brightness = {brightness} try {{ (Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods).WmiSetBrightness(1,$brightness) exit 0 }} catch {{ exit 1 }} "; return ExecutePowerShellCommand(script); } catch (Exception ex) { Debug.LogError($"PowerShell亮度控制失败: {ex.Message}"); return false; } } /// /// 执行 PowerShell 命令 /// private static bool ExecutePowerShellCommand(string script) { try { var processInfo = new System.Diagnostics.ProcessStartInfo { FileName = "powershell.exe", Arguments = $"-Command \"{script}\"", UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true }; using (var process = System.Diagnostics.Process.Start(processInfo)) { process.WaitForExit(5000); // 5秒超时 return process.ExitCode == 0; } } catch (Exception ex) { Debug.LogError($"PowerShell执行失败: {ex.Message}"); return false; } } #endregion #elif UNITY_ANDROID && !UNITY_EDITOR #region Android 实现 private static AndroidJavaClass _unityPlayer; private static AndroidJavaObject _currentActivity; private static AndroidJavaObject _audioManager; /// /// 初始化Android系统控制 /// static WindowsSystemController() { try { _unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); _currentActivity = _unityPlayer.GetStatic("currentActivity"); // 获取AudioManager _audioManager = _currentActivity.Call("getSystemService", "audio"); Debug.Log("Android系统控制器初始化成功"); } catch (Exception ex) { Debug.LogError($"Android系统控制器初始化失败: {ex.Message}"); } } /// /// 设置Android系统音量 /// public static bool SetSystemVolume(int volumePercent) { try { if (_audioManager == null) return false; // 获取最大音量 int maxVolume = _audioManager.Call("getStreamMaxVolume", 3); // STREAM_MUSIC = 3 // 计算目标音量 int targetVolume = Mathf.RoundToInt((volumePercent / 100f) * maxVolume); targetVolume = Mathf.Clamp(targetVolume, 0, maxVolume); // 设置音量 _audioManager.Call("setStreamVolume", 3, targetVolume, 0); // FLAG_SHOW_UI = 1, 不显示UI = 0 Debug.Log($"Android: 音量已设置为 {volumePercent}% (系统值: {targetVolume}/{maxVolume})"); return true; } catch (Exception ex) { Debug.LogError($"Android音量设置失败: {ex.Message}"); return false; } } /// /// 增加Android系统音量 /// public static void SystemVolumeUp() { try { if (_audioManager == null) return; _audioManager.Call("adjustStreamVolume", 3, 1, 0); // STREAM_MUSIC, ADJUST_RAISE, no flags Debug.Log("Android: 音量增加"); } catch (Exception ex) { Debug.LogError($"Android音量增加失败: {ex.Message}"); } } /// /// 降低Android系统音量 /// public static void SystemVolumeDown() { try { if (_audioManager == null) return; _audioManager.Call("adjustStreamVolume", 3, -1, 0); // STREAM_MUSIC, ADJUST_LOWER, no flags Debug.Log("Android: 音量降低"); } catch (Exception ex) { Debug.LogError($"Android音量降低失败: {ex.Message}"); } } /// /// 切换Android系统静音 /// public static void SystemMute() { try { if (_audioManager == null) return; // 获取当前音量 int currentVolume = _audioManager.Call("getStreamVolume", 3); if (currentVolume > 0) { // 静音 _audioManager.Call("setStreamVolume", 3, 0, 0); Debug.Log("Android: 静音"); } else { // 恢复到中等音量 int maxVolume = _audioManager.Call("getStreamMaxVolume", 3); _audioManager.Call("setStreamVolume", 3, maxVolume / 2, 0); Debug.Log("Android: 恢复音量"); } } catch (Exception ex) { Debug.LogError($"Android静音切换失败: {ex.Message}"); } } /// /// 设置Android屏幕亮度 /// public static bool SetMonitorBrightness(int brightnessPercent) { try { if (_currentActivity == null) return false; // Android亮度范围是0-255 float brightness = Mathf.Clamp01(brightnessPercent / 100f); int systemBrightness = Mathf.RoundToInt(brightness * 255f); // 方法1: 设置当前窗口亮度 (仅对当前应用生效) AndroidJavaObject window = _currentActivity.Call("getWindow"); AndroidJavaObject layoutParams = window.Call("getAttributes"); layoutParams.Set("screenBrightness", brightness); // 0.0f - 1.0f window.Call("setAttributes", layoutParams); Debug.Log($"Android: 应用窗口亮度已设置为 {brightnessPercent}%"); // 方法2: 尝试设置系统亮度 (需要WRITE_SETTINGS权限) try { AndroidJavaClass settingsSystem = new AndroidJavaClass("android.provider.Settings$System"); AndroidJavaObject contentResolver = _currentActivity.Call("getContentResolver"); bool success = settingsSystem.CallStatic("putInt", contentResolver, "screen_brightness", systemBrightness); if (success) { Debug.Log($"Android: 系统亮度已设置为 {brightnessPercent}%"); } else { Debug.LogWarning("Android: 系统亮度设置失败,可能缺少WRITE_SETTINGS权限"); } } catch (Exception ex) { Debug.LogWarning($"Android系统亮度设置失败 (权限问题): {ex.Message}"); } return true; } catch (Exception ex) { Debug.LogError($"Android亮度设置失败: {ex.Message}"); return false; } } /// /// 获取当前Android音量 /// public static int GetCurrentVolume() { try { if (_audioManager == null) return -1; int currentVolume = _audioManager.Call("getStreamVolume", 3); int maxVolume = _audioManager.Call("getStreamMaxVolume", 3); return Mathf.RoundToInt((currentVolume / (float)maxVolume) * 100f); } catch (Exception ex) { Debug.LogError($"获取Android音量失败: {ex.Message}"); return -1; } } /// /// 获取当前Android亮度 /// public static int GetCurrentBrightness() { try { if (_currentActivity == null) return -1; AndroidJavaClass settingsSystem = new AndroidJavaClass("android.provider.Settings$System"); AndroidJavaObject contentResolver = _currentActivity.Call("getContentResolver"); int brightness = settingsSystem.CallStatic("getInt", contentResolver, "screen_brightness", 128); // 默认值 return Mathf.RoundToInt((brightness / 255f) * 100f); } catch (Exception ex) { Debug.LogError($"获取Android亮度失败: {ex.Message}"); return -1; } } #endregion #region 时间控制 /// /// 设置系统时间 - 跨平台实现 /// /// 要设置的时间 /// 设置是否成功 public static bool SetSystemTime(DateTime dateTime) { #if UNITY_STANDALONE_WIN && !UNITY_EDITOR return SetWindowsSystemTime(dateTime); #elif UNITY_ANDROID && !UNITY_EDITOR return SetAndroidSystemTime(dateTime); #else Debug.Log($"[模拟] 系统时间设置为: {dateTime:yyyy-MM-dd HH:mm:ss}"); return true; #endif } /// /// 获取当前系统时间 - 跨平台实现 /// /// 当前系统时间 public static DateTime GetSystemTime() { #if UNITY_STANDALONE_WIN && !UNITY_EDITOR return GetWindowsSystemTime(); #elif UNITY_ANDROID && !UNITY_EDITOR return GetAndroidSystemTime(); #else return DateTime.Now; #endif } #if UNITY_STANDALONE_WIN && !UNITY_EDITOR /// /// Windows平台设置系统时间 /// 注意:需要管理员权限 /// private static bool SetWindowsSystemTime(DateTime dateTime) { try { SYSTEMTIME st = new SYSTEMTIME { wYear = (ushort)dateTime.Year, wMonth = (ushort)dateTime.Month, wDayOfWeek = (ushort)dateTime.DayOfWeek, wDay = (ushort)dateTime.Day, wHour = (ushort)dateTime.Hour, wMinute = (ushort)dateTime.Minute, wSecond = (ushort)dateTime.Second, wMilliseconds = (ushort)dateTime.Millisecond }; bool result = SetLocalTime(ref st); if (result) { Debug.Log($"Windows: 系统时间已设置为 {dateTime:yyyy-MM-dd HH:mm:ss}"); } else { Debug.LogWarning("Windows: 设置系统时间失败,可能需要管理员权限"); // 尝试使用命令行方式 return SetWindowsSystemTimeViaCommand(dateTime); } return result; } catch (Exception ex) { Debug.LogError($"Windows系统时间设置失败: {ex.Message}"); return SetWindowsSystemTimeViaCommand(dateTime); } } /// /// 通过命令行设置Windows系统时间 /// private static bool SetWindowsSystemTimeViaCommand(DateTime dateTime) { try { string dateCommand = $"date {dateTime:MM-dd-yyyy}"; string timeCommand = $"time {dateTime:HH:mm:ss}"; var processDate = new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo { FileName = "cmd.exe", Arguments = $"/C {dateCommand}", UseShellExecute = false, CreateNoWindow = true, Verb = "runas" // 以管理员身份运行 } }; var processTime = new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo { FileName = "cmd.exe", Arguments = $"/C {timeCommand}", UseShellExecute = false, CreateNoWindow = true, Verb = "runas" // 以管理员身份运行 } }; bool dateSuccess = processDate.Start() && processDate.WaitForExit(5000); bool timeSuccess = processTime.Start() && processTime.WaitForExit(5000); if (dateSuccess && timeSuccess) { Debug.Log($"Windows: 通过命令行设置系统时间成功 {dateTime:yyyy-MM-dd HH:mm:ss}"); return true; } else { Debug.LogWarning("Windows: 命令行设置系统时间失败,可能被用户拒绝或超时"); return false; } } catch (Exception ex) { Debug.LogError($"Windows命令行时间设置失败: {ex.Message}"); return false; } } /// /// 获取Windows系统时间 /// private static DateTime GetWindowsSystemTime() { try { GetLocalTime(out SYSTEMTIME st); return new DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); } catch (Exception ex) { Debug.LogError($"获取Windows系统时间失败: {ex.Message}"); return DateTime.Now; } } #endif #if UNITY_ANDROID && !UNITY_EDITOR /// /// Android平台设置系统时间 /// 注意:需要WRITE_SECURE_SETTINGS权限,通常只有系统应用才能获得 /// private static bool SetAndroidSystemTime(DateTime dateTime) { try { using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (var currentActivity = unityClass.GetStatic("currentActivity")) using (var contentResolver = currentActivity.Call("getContentResolver")) { // Android系统时间是以毫秒为单位的时间戳 long timeMillis = ((DateTimeOffset)dateTime).ToUnixTimeMilliseconds(); try { // 尝试设置系统时间 (需要系统权限) var systemClock = new AndroidJavaClass("android.os.SystemClock"); bool result = systemClock.CallStatic("setCurrentTimeMillis", timeMillis); if (result) { Debug.Log($"Android: 系统时间已设置为 {dateTime:yyyy-MM-dd HH:mm:ss}"); return true; } else { Debug.LogWarning("Android: 设置系统时间失败,可能缺少WRITE_SECURE_SETTINGS权限"); // 尝试使用AlarmManager设置(备用方案) return SetAndroidTimeViaAlarmManager(currentActivity, dateTime); } } catch (Exception ex) { Debug.LogWarning($"Android直接时间设置失败: {ex.Message}"); return SetAndroidTimeViaAlarmManager(currentActivity, dateTime); } } } catch (Exception ex) { Debug.LogError($"Android系统时间设置失败: {ex.Message}"); return false; } } /// /// 通过AlarmManager尝试时间设置(限制较多) /// private static bool SetAndroidTimeViaAlarmManager(AndroidJavaObject activity, DateTime dateTime) { try { // 注意:从Android 4.2开始,普通应用无法直接修改系统时间 // 这里只能提供用户引导到系统设置页面 Debug.LogWarning("Android: 普通应用无法直接修改系统时间,将引导用户到系统设置"); // 打开系统日期时间设置页面 var intent = new AndroidJavaObject("android.content.Intent"); intent.Call("setAction", "android.settings.DATE_SETTINGS"); activity.Call("startActivity", intent); Debug.Log("Android: 已打开系统日期时间设置页面"); return false; // 返回false表示需要用户手动设置 } catch (Exception ex) { Debug.LogError($"Android时间设置引导失败: {ex.Message}"); return false; } } /// /// 获取Android系统时间 /// private static DateTime GetAndroidSystemTime() { try { var systemClass = new AndroidJavaClass("java.lang.System"); long timeMillis = systemClass.CallStatic("currentTimeMillis"); DateTime dateTime = DateTimeOffset.FromUnixTimeMilliseconds(timeMillis).DateTime; return dateTime; } catch (Exception ex) { Debug.LogError($"获取Android系统时间失败: {ex.Message}"); return DateTime.Now; } } #endif #endregion #else // 其他平台或编辑器模式的模拟实现 public static bool SetSystemVolume(int volumePercent) { Debug.Log($"[模拟] 音量设置为: {volumePercent}%"); return true; } public static void SystemVolumeUp() { Debug.Log("[模拟] 音量增加"); } public static void SystemVolumeDown() { Debug.Log("[模拟] 音量减少"); } public static void SystemMute() { Debug.Log("[模拟] 静音切换"); } public static bool SetMonitorBrightness(int brightnessPercent) { Debug.Log($"[模拟] 亮度设置为: {brightnessPercent}%"); return true; } public static int GetCurrentVolume() { Debug.Log("[模拟] 获取当前音量"); return 50; // 模拟返回50% } public static int GetCurrentBrightness() { Debug.Log("[模拟] 获取当前亮度"); return 70; // 模拟返回70% } public static bool SetSystemTime(DateTime dateTime) { Debug.Log($"[模拟] 系统时间设置为: {dateTime:yyyy-MM-dd HH:mm:ss}"); return true; } public static DateTime GetSystemTime() { Debug.Log("[模拟] 获取系统时间"); return DateTime.Now; } #endif }