尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Unity跨平台设备唯一标识方案:从IDFV、Android ID到哈希融合的实战指南

Unity跨平台设备唯一标识方案:从IDFV、Android ID到哈希融合的实战指南
📅 发布时间:2026/7/12 7:43:00

1. 项目概述:为什么跨平台设备标识是个“老大难”问题?

在Unity3D游戏开发或者应用开发中,我们经常遇到一个看似简单、实则棘手的需求:如何获取一个稳定、可靠、跨平台的设备唯一标识符?无论是用于用户数据统计、广告追踪、反作弊、还是存档绑定,一个靠谱的设备ID都是基础中的基础。新手开发者可能会直接使用SystemInfo.deviceUniqueIdentifier,结果上线后发现,在iOS设备上,用户重装应用或者重置广告标识符(IDFA)后,这个ID就变了;在安卓上,不同厂商的设备返回的标识符五花八门,有的甚至为空。这直接导致用户数据错乱、统计失真,甚至引发严重的业务逻辑问题。

这个问题的核心在于“跨平台”和“唯一性”之间的天然矛盾。每个操作系统(Android, iOS, Windows, macOS)都有自己的一套硬件和软件标识体系,它们的获取权限、生命周期、重置规则各不相同。Unity提供的deviceUniqueIdentifier是一个封装后的便捷接口,但其底层实现在不同平台上有不同的后备方案,稳定性和一致性无法满足生产环境的要求。因此,我们需要一个融合了多平台特性、具备一定抗重置能力、并且符合隐私规范的实战解决方案。这不仅仅是调用一个API那么简单,它涉及到对各个平台底层机制的深入理解、多种标识符的采集与融合策略、本地存储的优化以及隐私合规的考量。接下来,我将结合多年的项目踩坑经验,为你拆解一套从原理到代码,从选型到优化的完整策略。

2. 核心思路与方案选型:构建分层的标识符体系

直接依赖单一标识符是风险最高的做法。一个稳健的方案必须是分层的、可降级的。我们的核心思路是:优先采集各平台最稳定、生命周期最长的硬件或系统级标识符作为“种子”;当无法获取理想标识时,采用软件生成的UUID进行兜底;最后,将所有可用标识符按优先级进行组合与哈希,生成一个最终的综合ID,并持久化存储以对抗部分标识符的变更。

2.1 各平台标识符特性深度解析

首先,我们必须了解在每个目标平台上我们能获取到什么,以及它们的“脾气”。

Android平台:

  1. Android ID (Settings.Secure.ANDROID_ID):这是目前相对最可靠的软件标识符。它是一个64位的十六进制字符串,在设备首次启动时生成,并在设备恢复出厂设置时改变。关键点在于:在Android 8.0(API级别26)及以上,ANDROID_ID的值基于应用签名密钥和用户(应用)范围,这意味着不同签名的应用获取到的Android ID是不同的。这反而成了我们的优势,因为它与应用绑定,避免了跨应用追踪的隐私问题,同时对于本应用而言稳定性尚可。
  2. 序列号 (Serial Number):通过SystemInfo.deviceUniqueIdentifier在安卓上的一个后备来源,或通过AndroidJavaClass调用系统API获取。但需要注意,从Android 10(API级别29)开始,非系统应用默认无法读取设备序列号,除非你的应用是设备策略管理器或拥有特殊权限。因此,它已不可作为可靠来源。
  3. MAC地址:过去常用的标识符,但现在由于隐私限制(Android 6.0后需要精确定位权限,且随机化MAC地址普及),获取难度大且价值低,不推荐使用。
  4. Build.SERIAL / Build.getSerial():与上述序列号类似,受Android 10+的严格限制。

iOS / iPadOS平台:

  1. identifierForVendor (IDFV):这是苹果为开发者提供的、用于跨应用追踪同一供应商(即同一个开发者账号下的应用)的标识符。它的生命周期是:只要用户设备上还保留着来自同一供应商的至少一个应用,IDFV就不会变。删除该供应商的所有应用后再重装,IDFV会改变。它是我们在iOS上首选的标识符。
  2. advertisingIdentifier (IDFA):广告标识符。用户可以随时在系统设置中“重置广告标识符”或开启“限制广告跟踪”,这会导致IDFA变化或被返回全零字符串。因此,它绝对不适合用作设备唯一ID,仅可用于合规的广告归因。
  3. UUID(由Keychain存储):这是很多成熟方案采用的“终极兜底”策略。当无法获得稳定ID时,我们生成一个随机UUID,并将其存储到iOS的Keychain中。Keychain的数据在应用删除后依然可能保留(取决于Keychain访问组配置),这为我们提供了对抗应用重装的能力。这是实现“超稳定”ID的关键技术点。

Windows / macOS / Linux (Standalone) 平台:Unity的SystemInfo.deviceUniqueIdentifier在PC和Mac单机版上,通常会结合硬盘序列号、主板信息等生成一个哈希值。相对移动平台,它要稳定得多,但并非绝对不变(如更换主要硬件)。我们可以将其作为桌面平台的主要参考,同时考虑结合机器名、用户名等系统信息进行加强。

2.2 我们的混合方案选型

基于以上分析,我们摒弃“一招鲜”的想法,采用如下优先级策略:

  1. 第一优先级(平台原生稳定ID):
    • iOS:获取identifierForVendor (IDFV)。
    • Android:获取应用作用域的Android ID。
    • 其他平台:使用SystemInfo.deviceUniqueIdentifier作为基础。
  2. 第二优先级(持久化UUID兜底):
    • 当第一优先级的标识符获取失败、为空或明显无效(如全零)时,则尝试从本地安全存储(如PlayerPrefs,但更优选文件加密存储)中读取一个之前生成并保存的UUID。
    • 如果本地也没有,则生成一个新的随机UUID(采用System.Guid.NewGuid().ToString()),并立即保存到本地安全存储和(在iOS上)Keychain中。
  3. 最终生成(融合与哈希):
    • 将获取到的所有有效标识符(可能包括第一优先级的ID、第二优先级的UUID、以及一些辅助信息如设备型号SystemInfo.deviceModel)按固定顺序拼接成一个字符串。
    • 对这个拼接字符串进行哈希计算(如SHA256),取哈希值的前若干位(例如16位或32位十六进制字符)作为最终的“综合设备指纹”。
    • 为什么用哈希?一是为了统一格式和长度;二是哈希过程不可逆,避免了直接暴露原始设备信息,更符合隐私保护趋势;三是将多个源融合,即使其中一个源发生变化,只要其他源未变,最终哈希值仍有很大概率保持稳定,增强了鲁棒性。

这个方案的优势在于:它尊重了各平台的隐私规则,利用了平台提供的、最稳定的标识符,并通过本地持久化和哈希融合,创造了一个应用层级的、相对更稳定的虚拟标识。

3. 核心实现细节与跨平台代码架构

理论清晰后,我们来看代码如何组织。Unity的跨平台特性要求我们使用条件编译 (#if UNITY_IOS,#if UNITY_ANDROID,#if UNITY_STANDALONE等) 来编写平台特定的代码。

3.1 定义统一接口与数据模型

首先,我们定义一个管理类和一个数据结构。

// DeviceIdentifierManager.cs using System; using System.Text; using System.Security.Cryptography; using UnityEngine; public class DeviceIdentifierManager { private static DeviceIdentifierManager _instance; public static DeviceIdentifierManager Instance => _instance ?? (_instance = new DeviceIdentifierManager()); // 最终生成的综合设备ID public string CustomDeviceID { get; private set; } // 存储获取到的原始标识符信息 private class DeviceIdInfo { public string Platform; // 平台名称 public string PrimaryID; // 第一优先级ID (IDFV, Android ID等) public string BackupUUID; // 第二优先级/兜底UUID public string SystemDeviceUID; // Unity系统ID public string Model; // 设备型号 // 可以扩展其他信息,如系统版本 } private DeviceIdInfo _currentInfo = new DeviceIdInfo(); private DeviceIdentifierManager() { } public void Initialize() { GatherDeviceInfo(); CustomDeviceID = GenerateCustomDeviceID(); Debug.Log($"[DeviceID] 初始化完成。平台:{_currentInfo.Platform}, 最终ID: {CustomDeviceID}"); } }

3.2 分平台信息采集实现

这是核心,我们在GatherDeviceInfo方法中实现。

private void GatherDeviceInfo() { _currentInfo.Platform = Application.platform.ToString(); _currentInfo.Model = SystemInfo.deviceModel; _currentInfo.SystemDeviceUID = SystemInfo.deviceUniqueIdentifier; #if UNITY_IOS && !UNITY_EDITOR // 调用iOS原生代码获取IDFV _currentInfo.PrimaryID = GetIOSIdentifierForVendor(); // 尝试从Keychain读取之前保存的UUID _currentInfo.BackupUUID = GetUUIDFromKeychain(); if (string.IsNullOrEmpty(_currentInfo.BackupUUID)) { _currentInfo.BackupUUID = Guid.NewGuid().ToString(); SaveUUIDToKeychain(_currentInfo.BackupUUID); } #elif UNITY_ANDROID && !UNITY_EDITOR // 调用Android Java API获取Android ID _currentInfo.PrimaryID = GetAndroidID(); // Android端使用PlayerPrefs或加密文件存储兜底UUID _currentInfo.BackupUUID = PlayerPrefs.GetString("DEVICE_BACKUP_UUID", ""); if (string.IsNullOrEmpty(_currentInfo.BackupUUID)) { _currentInfo.BackupUUID = Guid.NewGuid().ToString(); PlayerPrefs.SetString("DEVICE_BACKUP_UUID", _currentInfo.BackupUUID); PlayerPrefs.Save(); } #elif UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX // PC/Mac平台,以系统ID为主,同时生成一个持久化UUID _currentInfo.PrimaryID = _currentInfo.SystemDeviceUID; // 直接使用Unity提供的 _currentInfo.BackupUUID = PlayerPrefs.GetString("DEVICE_BACKUP_UUID", ""); if (string.IsNullOrEmpty(_currentInfo.BackupUUID)) { _currentInfo.BackupUUID = Guid.NewGuid().ToString(); PlayerPrefs.SetString("DEVICE_BACKUP_UUID", _currentInfo.BackupUUID); PlayerPrefs.Save(); } #else // 其他平台(如WebGL、编辑器)使用纯软件生成的持久化UUID _currentInfo.PrimaryID = "UNKNOWN_PLATFORM"; _currentInfo.BackupUUID = PlayerPrefs.GetString("DEVICE_BACKUP_UUID", ""); if (string.IsNullOrEmpty(_currentInfo.BackupUUID)) { _currentInfo.BackupUUID = Guid.NewGuid().ToString(); PlayerPrefs.SetString("DEVICE_BACKUP_UUID", _currentInfo.BackupUUID); PlayerPrefs.Save(); } #endif // 有效性检查:如果PrimaryID无效,则用BackupUUID顶替 if (string.IsNullOrEmpty(_currentInfo.PrimaryID) || IsInvalidID(_currentInfo.PrimaryID)) { Debug.LogWarning($"[DeviceID] 第一优先级ID无效,将使用备份UUID。原ID: {_currentInfo.PrimaryID}"); _currentInfo.PrimaryID = _currentInfo.BackupUUID; } } // 示例:检查ID是否无效(如全零) private bool IsInvalidID(string id) { if (string.IsNullOrEmpty(id)) return true; // 检查是否是常见的无效ID,例如iOS的IDFA在限制跟踪时返回的“00000000-0000-0000-0000-000000000000” if (id.Trim('0', '-').Length == 0) return true; return false; }

3.3 iOS原生插件实现(关键)

需要在Xcode项目中创建原生代码桥接。这里使用C#的[DllImport("__Internal")]方式。

首先,创建一个IOSDeviceIDBridge.mm文件(如果你的Unity版本支持,也可以使用.c或.h):

// IOSDeviceIDBridge.mm #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> extern "C" { // 获取IDFV const char* _GetIDFV() { NSString *idfvString = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; if (idfvString) { char* idfvCString = (char*)malloc([idfvString length] + 1); strcpy(idfvCString, [idfvString UTF8String]); return idfvCString; } return NULL; } // 将UUID保存到Keychain(简化示例,生产环境应用更健壮的Keychain操作) void _SaveUUIDToKeychain(const char* uuidCString) { NSString *uuid = [NSString stringWithUTF8String:uuidCString]; if (!uuid) return; // 这里使用NSUserDefaults模拟,实际应用必须使用Keychain Services (Security.framework) // 例如使用开源库如`KeychainAccess`,或自己封装`SecItemAdd`等函数。 [[NSUserDefaults standardUserDefaults] setObject:uuid forKey:@"CustomDeviceUUID"]; [[NSUserDefaults standardUserDefaults] synchronize]; } // 从Keychain读取UUID const char* _GetUUIDFromKeychain() { NSString *savedUUID = [[NSUserDefaults standardUserDefaults] stringForKey:@"CustomDeviceUUID"]; if (savedUUID) { char* uuidCString = (char*)malloc([savedUUID length] + 1); strcpy(uuidCString, [savedUUID UTF8String]); return uuidCString; } return NULL; } }

注意:上述Keychain操作使用了NSUserDefaults作为简化示例,这并不能实现应用删除后数据保留。真正的生产代码必须使用iOS的Keychain Services API(Security/Security.h)。你可以使用SecItemAdd,SecItemCopyMatching等函数,并正确设置kSecAttrAccessGroup和kSecAttrService等属性,或者集成成熟的第三方插件(如Unity Asset Store上的“iOS Keychain Plugin”)。这是实现iOS端“超稳定ID”的技术关键点,务必重视。

然后在C#中声明对应的外部方法:

// 在DeviceIdentifierManager.cs内部或单独的桥接类中 #if UNITY_IOS && !UNITY_EDITOR using System.Runtime.InteropServices; public static class IOSNativeBridge { [DllImport("__Internal")] private static extern string _GetIDFV(); [DllImport("__Internal")] private static extern void _SaveUUIDToKeychain(string uuid); [DllImport("__Internal")] private static extern string _GetUUIDFromKeychain(); public static string GetIDFV() { try { return _GetIDFV(); } catch (Exception e) { Debug.LogError($"[iOS] 获取IDFV失败: {e.Message}"); return null; } } public static void SaveUUIDToKeychain(string uuid) { try { _SaveUUIDToKeychain(uuid); } catch (Exception e) { Debug.LogError($"[iOS] 保存UUID到Keychain失败: {e.Message}"); } } public static string GetUUIDFromKeychain() { try { return _GetUUIDFromKeychain(); } catch (Exception e) { Debug.LogError($"[iOS] 从Keychain读取UUID失败: {e.Message}"); return null; } } } #endif

最后,在GatherDeviceInfo的iOS部分调用这些方法。

3.4 Android原生接口实现

Android端通过AndroidJavaClass和AndroidJavaObject调用系统API。

// 在DeviceIdentifierManager.cs内部 private string GetAndroidID() { string androidId = ""; #if UNITY_ANDROID && !UNITY_EDITOR try { using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) using (AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject>("getContentResolver")) using (AndroidJavaClass secure = new AndroidJavaClass("android.provider.Settings$Secure")) { androidId = secure.CallStatic<string>("getString", contentResolver, "android_id"); } } catch (Exception e) { Debug.LogError($"[Android] 获取Android ID失败: {e.Message}"); } #endif return androidId; }

3.5 生成最终的综合设备ID

采集到所有信息后,进行融合与哈希。

private string GenerateCustomDeviceID() { // 1. 构建用于哈希的源字符串 StringBuilder sb = new StringBuilder(); sb.Append(_currentInfo.Platform ?? ""); sb.Append("|"); sb.Append(_currentInfo.PrimaryID ?? ""); sb.Append("|"); sb.Append(_currentInfo.BackupUUID ?? ""); sb.Append("|"); sb.Append(_currentInfo.Model ?? ""); // 可以加入更多稳定信息,如系统版本(SystemInfo.operatingSystem) string sourceString = sb.ToString(); Debug.Log($"[DeviceID] 哈希源字符串: {sourceString}"); // 2. 计算SHA256哈希 using (SHA256 sha256 = SHA256.Create()) { byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(sourceString)); // 3. 将字节数组转换为十六进制字符串,并取前16位作为最终ID(可根据需要调整长度) StringBuilder hashBuilder = new StringBuilder(); for (int i = 0; i < 8 && i < hashBytes.Length; i++) // 取前8字节,即16个十六进制字符 { hashBuilder.Append(hashBytes[i].ToString("x2")); } return hashBuilder.ToString().ToUpper(); // 转为大写,更美观 } }

4. 优化策略与进阶考量

实现基础功能只是第一步,要让这个方案在生产环境中坚如磐石,还需要一系列优化策略。

4.1 存储优化与ID升级机制

  • 加密存储:无论是Android的PlayerPrefs还是iOS的Keychain,存储的兜底UUID都应该加密。PlayerPrefs本质是明文plist文件,容易被篡改。建议使用AES等对称加密算法,将UUID加密后再存储,密钥可以硬编码(安全性较低)或由服务器下发(更安全)。
  • ID版本与升级:你的设备ID生成算法可能会迭代。例如,V1版只用了Android ID,V2版加入了设备型号哈希。为了兼容旧版本,你需要在本地存储一个DeviceIDVersion。每次初始化时,检查本地版本与当前代码版本。如果版本落后,则用新旧两套算法分别计算ID,并将新旧ID的映射关系上报服务器,由服务器端进行用户身份的合并与迁移,确保用户体验连贯。

4.2 网络层校验与容灾

  • 服务器端校验:客户端生成的ID不能完全信任。每次启动或关键请求时,应将CustomDeviceID连同部分“原料”(如平台、设备型号、系统版本)上报服务器。服务器端可以记录该ID的首次出现时间、常用登录地等信息,用于风险控制。如果发现同一个ID在极短时间内从地理位置迥异的地方登录,可能标识符被伪造或泄露,需要触发二次验证。
  • ID失效与重新生成策略:定义什么情况下ID需要重新生成。例如,检测到设备恢复出厂设置(Android ID改变)、用户明确重置广告标识符(虽然我们不用IDFA,但可作为参考)等。此时,可以清空本地存储的旧UUID,按照新流程重新生成,并通知服务器旧ID已失效,新ID与旧ID的关联关系。

4.3 隐私合规与用户体验

这是当今移动开发的重中之重。

  • 明确告知与获取同意:在应用启动的隐私政策弹窗中,必须清晰告知用户你收集了设备标识符用于哪些目的(如保障账号安全、统计分析、反作弊)。在iOS上,如果涉及IDFA,必须使用AppTrackingTransparency框架请求用户授权。我们的方案主要使用IDFV和Android ID,它们通常不需要额外的运行时权限,但在隐私政策中说明仍是必要的。
  • 提供重置选项:在应用的设置页面,可以考虑提供一个“重置设备标识符”的选项。这不仅是尊重用户权利的表现(如GDPR、CCPA等法规要求),也能在用户怀疑ID泄露或出现问题时,提供一个自我修复的渠道。实现上,就是清除本地存储的所有ID相关数据(加密的UUID、版本号等),然后重新走一遍初始化流程,生成全新的ID。

4.4 针对特定平台的深入优化

  • iOS Keychain的共享:如果你有多个应用(同一Team ID),可以通过配置Keychain Access Groups,让多个应用共享同一个存储的UUID,实现跨应用的同一设备识别。这需要配置正确的Entitlements文件。
  • Android 10+的适配再思考:虽然硬件标识符获取受限,但可以结合更多软件特征进行设备指纹计算,例如屏幕分辨率、CPU架构、已安装应用列表(需权限)、蓝牙/Wi-Fi MAC地址(需权限且可能随机化)等。但这些信息要么不稳定,要么需要权限,需谨慎使用,并作为哈希源的一部分,而非主要依据。
  • 编辑器与多平台测试:在Unity编辑器中,上述原生代码不会执行。你需要模拟各平台的行为,可以硬编码一个测试ID,或者通过定义UNITY_EDITOR宏来使用一套模拟逻辑,确保开发和调试流程顺畅。

5. 实战中常见问题与排查清单

即使方案再完善,实际部署中还是会遇到各种“坑”。下面是我总结的常见问题速查表。

问题现象可能原因排查步骤与解决方案
iOS设备上,应用删除重装后ID变化兜底UUID没有正确存入Keychain,或者Keychain访问组配置错误,导致应用删除后数据被清空。1. 确认使用的是Keychain Services API,而非NSUserDefaults。2. 检查Xcode工程中Capabilities的Keychain Sharing是否开启,并设置了正确的Access Group。3. 使用工具(如Keychain Access.app)查看应用删除后,条目是否依然存在。
Android设备上,部分厂商返回的Android ID为空或重复这是某些厂商(尤其是低端或深度定制ROM)的已知问题。系统可能没有正确生成或返回Android ID。1. 在GatherDeviceInfo中加强IsInvalidID的判断,将空字符串、”9774d56d682e549c” (已知的默认值) 等视为无效。2. 当Android ID无效时,必须可靠地降级到使用备份UUID。3. 考虑在Android端也引入类似Keychain的更持久化存储(如加密文件存于外部存储,但需注意权限和可清除性)。
生成的CustomDeviceID在极少数情况下发生改变哈希的源信息中,某一部分发生了预期之外的变化。例如,设备系统OTA升级后,SystemInfo.deviceModel的字符串可能微调;或者备份UUID因存储损坏而被重置。1. 在日志中输出哈希的源字符串sourceString,对比变化前后差异。2. 优先保证PrimaryID和BackupUUID的稳定性。如果它们没变,即使其他辅助信息变化,哈希结果也有很高概率稳定。3. 实现ID版本机制,当检测到ID不稳定时,可升级算法,将更多稳定信息纳入哈希源。
WebGL平台无法获取有效IDWebGL环境限制极大,无法获取任何硬件信息,且本地存储(如IndexedDB)可能被用户清除。1. 接受WebGL平台ID不稳定的现实,明确将其归类为“其他平台”,完全依赖生成的、存储在本地存储(PlayerPrefs/IndexedDB)中的UUID。2. 在隐私政策中说明Web版本体验的限制。3. 强烈建议WebGL版本强制用户登录账号,以账号体系代替设备ID。
服务器端收到大量重复或无效的设备ID客户端生成逻辑有BUG,或者遭到了恶意篡改和伪造。1. 服务器端对收到的设备ID进行格式校验(长度、字符集)。2. 建立频率监控:同一个ID在短时间内从多个IP发起请求,应触发警报。3. 客户端上报时,可以附带一个由服务器下发的盐(salt)参与哈希计算,增加伪造难度。

最后,我个人在实际项目中的体会是,没有一劳永逸的“完美”设备ID方案。我们的目标是:在满足隐私合规的前提下,为绝大多数正常用户提供一个生命周期足够长、足够稳定的标识符,同时为异常情况设计好降级和修复通路。这套混合方案经过多个上线项目的检验,能有效将因设备ID变更导致的用户识别错误率降低一个数量级以上。在实现时,务必做好详尽的日志记录,方便线上问题追踪。同时,保持对操作系统更新和隐私政策的关注,因为这块领域的变化可能会很快。

相关新闻

  • AI 时代持久层开发的动态最优解:从 7:2:1 到 5:3:2,约束强度决定一切
  • 2026口碑不错的财税咨询公司强势出炉,价格透明零套路不踩坑 - mypinpai
  • 百达翡丽中国官方售后服务中心|网点地址与售后服务热线权威信息通告(2026年7月最新) - 百达翡丽服务中心

最新新闻

  • 基于G6D-ASI与TM4C1299KCZAD的直流负载管理系统设计
  • SAP采购信息记录价格更新对比:PB00条件价格 vs 参考PO价格(ME1M视图)
  • A3910与PIC18F25K42在电机控制中的高效应用
  • Prometheus 监控 vSphere:VMware Exporter 与 Grafana Agent vSphere 组件 2 方案对比
  • 人形机器人关节模组:机电热控材五维耦合的精密系统
  • Crunch 3.6 密码字典生成:5个高级参数组合实战,字典体积缩减80%

日新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号