Unity的SystemInfo.deviceUniqueIdentifier与WPF通过System.Management获取的设备唯一ID不一致问题排查及解决方案咨询
Let's break down why you're seeing mismatched IDs and how to get consistent results across both platforms.
Root Cause of the Mismatch
The core issue is that Unity's SystemInfo.deviceUniqueIdentifier uses a different set of hardware data and hashing logic than your custom WPF implementation:
- Unity's Windows ID Logic: On Windows, Unity generates this ID by combining multiple hardware identifiers (like motherboard UUID, BIOS serial, hard drive ID, and potentially others) using its own internal hashing/encoding rules. This is not the same as your WPF code, which only uses
Win32_BaseBoard,Win32_BIOS, andWin32_OperatingSystemserial numbers. - Low-End Device Hardware Gaps: On lower-spec PCs, some WMI properties (like baseboard/BIOS serial numbers) return "Not Applicable". Your WPF code drops these values, but Unity falls back to other available hardware data (e.g., hard drive serial) to generate its ID—creating even more divergence between the two inputs fed into the hash functions.
Solutions to Get Consistent Device IDs
To fix this, you need to enforce identical data sources, concatenation rules, and hashing logic on both platforms. Here are two reliable approaches:
Option 1: Unify with WMI + SHA1 (Matches Your Existing WPF Code)
Make Unity use the exact same WMI queries and SHA1 hashing as your WPF app. This ensures full compatibility with your existing implementation.
Unity Implementation Steps:
- Set your Unity project's API Compatibility Level to
.NET Framework(inEdit > Project Settings > Player > Other Settings). This enables access to theSystem.Managementnamespace needed for WMI. - Add the
System.Managementassembly reference (usually included automatically when targeting .NET Framework in Unity). - Use this identical code to your WPF implementation:
using System; using System.Management; using System.Security.Cryptography; using System.Text; using System.Linq; using UnityEngine; public static class DeviceIDUtility { public static string GetDeviceUniqueIdentifier() { string ret = string.Empty; string concatStr = string.Empty; try { using (ManagementObjectSearcher searcherBb = new ManagementObjectSearcher("SELECT * FROM Win32_BaseBoard")) { foreach (var obj in searcherBb.Get()) { concatStr += (string)obj.Properties["SerialNumber"].Value ?? string.Empty; } } using (ManagementObjectSearcher searcherBios = new ManagementObjectSearcher("SELECT * FROM Win32_BIOS")) { foreach (var obj in searcherBios.Get()) { concatStr += (string)obj.Properties["SerialNumber"].Value ?? string.Empty; } } using (ManagementObjectSearcher searcherOs = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem")) { foreach (var obj in searcherOs.Get()) { concatStr += (string)obj.Properties["SerialNumber"].Value ?? string.Empty; } } using (var sha1 = SHA1.Create()) { ret = string.Join("", sha1.ComputeHash(Encoding.UTF8.GetBytes(concatStr)).Select(b => b.ToString("x2"))); } } catch (Exception e) { Debug.LogError($"Failed to get device ID: {e}"); } return ret; } }
Option 2: Use Windows MachineGuid (Simpler & More Reliable)
For a lighter-weight solution, read the MachineGuid from the Windows registry. This is a unique, stable ID generated during Windows installation, and it works seamlessly in both WPF and Unity.
WPF Implementation:
using Microsoft.Win32; private string GetMachineGuid() { try { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography")) { return key?.GetValue("MachineGuid")?.ToString() ?? string.Empty; } } catch (Exception e) { Console.WriteLine($"Error fetching MachineGuid: {e}"); return string.Empty; } }
Unity Implementation:
using Microsoft.Win32; using UnityEngine; public static string GetMachineGuid() { try { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography")) { return key?.GetValue("MachineGuid")?.ToString() ?? string.Empty; } } catch (Exception e) { Debug.LogError($"Error fetching MachineGuid: {e}"); return string.Empty; } }
Note: The MachineGuid changes if Windows is reinstalled, but it's consistent for the lifetime of the OS installation—ideal for most device identification use cases.
内容的提问来源于stack exchange,提问作者crackanddie




