本文介绍如何在Unity应用开发中集成使用HTTPDNS。
Unity是实时3D互动内容创作和运营平台。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助Unity将创意变成现实。Unity平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。
随着使用Unity开发的移动应用越来越多,应用类型越来越广泛,我们专门提供了针对Unity的HTTPDNS插件,方便Unity开发者以熟悉方式接入HTTPDNS功能。
以下是插件的使用说明和最佳实践:
一、快速入门
1.1 开通服务
请参考快速入门开通HTTPDNS。
1.2 获取配置
请参考开发配置在EMAS控制台开发配置中获取AccountId/SecretKey/AESSecretKey等信息,用于初始化SDK。
1.3 集成插件到项目
本插件以源码形式提供,已发布到GitHub,需要将插件复制到您的Unity项目中进行集成。
1.3.1 导入Unity Package
下载本项目的
httpdns_unity_demo目录将整个
Assets/Plugins目录复制到您的Unity项目中将
Assets/Editor目录(可选,用于创建测试UI)复制到您的项目中
项目结构应如下所示:
YourUnityProject/
├── Assets/
│ ├── Plugins/
│ │ ├── HttpDnsHelper.cs # 主接口文件
│ │ ├── AndroidHttpDnsHelper.cs # Android平台实现
│ │ ├── iOSHttpDnsHelper.cs # iOS平台实现
│ │ ├── CHttpDnsHelper.cs # C SDK平台实现
│ │ ├── Android/ # Android JAR库
│ │ ├── iOS/ # iOS Bridge文件
│ │ └── C/ # C SDK
│ └── Editor/ # 测试UI创建器
├── ProjectSettings/
└── ...插件使用了baseProjectTemplate, mainTemplate, proguard-user, settingsTemplate等文件,如果项目有其他地方也需要定制这些文件,请注意合并修改内容。
1.3.2 验证原生SDK版本
插件已集成了对应平台的HTTPDNS原生SDK,当前版本:
Android:
com.aliyun.ams:alicloud-android-httpdns:2.6.5iOS:
AlicloudHTTPDNS:3.2.1C:
alibabacloud-httpdns-c-sdk:2.2.5
二、安装配置
2.1 添加Unity依赖
在您的Unity项目中进行以下配置:
# Unity项目配置
Player Settings:
- Android:
Minimum API Level: 19+
Internet Permission: Enabled
- iOS:
Deployment Target: 12.0+
Internet Capability: Enabled
- C:
Platforms: Windows/macOS
Architectures: x64/arm64
Scripting Backend: Mono 或 IL2CPP插件使用本地源码依赖方式引用。添加到项目之后需要根据目标平台进行相应配置。
2.2 原生SDK版本更新
如需更新HTTPDNS原生SDK版本,请按以下步骤操作:
2.2.1 更新Android SDK版本
Android 端通过 Maven 依赖管理。请在 Assets/Plugins/Android/mainTemplate.gradle 的 dependencies 中修改版本号:
dependencies {
// 其他依赖...
implementation 'com.aliyun.ams:alicloud-android-httpdns:2.6.5' // 修改为所需版本
}提示:Android、iOS、C 三端接口能力存在差异,请以各平台官方接口文档为准。
启用了自定义 Gradle 模板(Custom Main/Base Gradle Template、Custom Proguard)后,Unity 构建会自动从仓库拉取对应版本。
可用版本请参考:Android SDK发布说明
2.2.2 更新iOS SDK版本
编辑构建后处理器中的CocoaPods依赖版本:
// 在 HttpDnsIOSPostProcessor.cs 中更新版本
podfileContent += " pod 'AlicloudHTTPDNS', '~> 3.2.1'\n";
// 更新为您需要的版本
podfileContent += " pod 'AlicloudHTTPDNS', '~> 新版本号'\n";可用版本请参考:iOS SDK发布说明
2.2.3 更新C SDK版本
请参考以下步骤操作:
获取更新后的 C SDK 源码。
在本机编译生成原生库文件。
将生成的库文件放入 Unity 工程的插件目录,例如
Assets/Plugins/C/x86_64/下的.dll或 macOS 的.dylib。回到 Unity,重新构建项目以生效。
更多信息与版本说明参考:C SDK发布说明
2.2.4 重新构建项目
更新版本后,需要重新构建项目:
Android:
# Unity Editor中
File -> Build Settings -> Android -> BuildiOS:
# Unity Editor中构建后cd [iOS构建目录]
pod install --repo-update
open Unity-iPhone.xcworkspaceC (Windows/macOS) :
# Unity Editor中
File -> Build Settings -> PC, Mac & Linux Standalone -> Build三、配置和使用
3.1 初始化配置
应用启动后,需要先初始化插件,才能调用HTTPDNS能力。 初始化主要是配置AccountId/SecretKey等信息及功能开关。 示例代码如下:
using UnityEngine;
public class HttpDnsManager : MonoBehaviour
{
void Start()
{
// 初始化HTTPDNS - 分阶段初始化模式
HttpDnsHelper.init("YOUR_ACCOUNT_ID", "YOUR_SECRET_KEY");
// 设置功能选项
HttpDnsHelper.setHttpsRequestEnabled(true);
HttpDnsHelper.debug(true);
HttpDnsHelper.setTimeout(3000);
// 高级功能配置
HttpDnsHelper.setPersistentCacheIPEnabled(true, 3600); // 启用持久化缓存1小时
HttpDnsHelper.setReuseExpiredIPEnabled(true); // 允许复用过期IP
HttpDnsHelper.setPreResolveAfterNetworkChanged(true); // 网络切换时自动预解析
// 构建服务实例
bool success = HttpDnsHelper.build();
if (success)
{
Debug.Log("HTTPDNS初始化成功");
// 预解析常用域名
var hosts = new List<string> { "www.aliyun.com", "ecs.console.aliyun.com" };
HttpDnsHelper.setPreResolveHosts(hosts, "auto");
}
else
{
Debug.LogError("HTTPDNS初始化失败");
}
}
}3.1.1 日志配置
应用开发过程中,如果要输出HTTPDNS的日志,可以调用日志输出控制方法,开启日志,示例代码如下:
HttpDnsHelper.debug(true);
Debug.Log("日志输出已启用");3.1.2 sessionId记录
应用在运行过程中,可以调用获取SessionId方法获取sessionId,记录到应用的数据采集系统中。 sessionId用于表示标识一次应用运行,线上排查时,可以用于查询应用一次运行过程中的解析日志,示例代码如下:
string sessionId = HttpDnsHelper.getSessionId();
Debug.Log($"SessionId = {sessionId}");3.2 域名解析
3.2.1 预解析
当需要提前解析域名时,可以调用预解析域名方法,示例代码如下:
var hosts = new List<string> { "www.aliyun.com", "www.example.com" };
HttpDnsHelper.setPreResolveHosts(hosts, "both");
Debug.Log("预解析设置成功");调用之后,插件会发起域名解析,并把结果缓存到内存,用于后续请求时直接使用。
3.2.2 域名解析
当需要解析域名时,可以通过调用域名解析方法解析域名获取IP,示例代码如下:
public void ResolveDomain(string hostname)
{
// 同步非阻塞解析
var result = HttpDnsHelper.resolveHostSyncNonBlocking(hostname, "auto");
if (result != null)
{
Debug.Log($"IPv4地址: {result.IPv4.Count}个");
Debug.Log($"IPv6地址: {result.IPv6.Count}个");
Debug.Log($"TTL: {result.TTL}秒");
}
}注意:resolveHostSyncNonBlocking 为同步非阻塞解析,可能返回空或无结果。建议配合预解析功能,在无解析结果时回退到系统 DNS 发起请求。
四、Unity最佳实践
4.1 原理说明
本示例展示了Unity中集成HTTPDNS的完整解决方案:
跨平台统一接口: 使用
HttpDnsHelper提供统一的API接口平台特定实现: 针对Android、iOS、C SDK提供不同的底层实现
自动DNS替换: 在网络请求前自动将域名替换为解析的IP地址
Host头设置: 确保HTTPS/SSL连接的SNI正确性
4.2 网络请求集成
当使用不同的网络模块发送请求时,需要相应地进行请求头配置等操作,下面对HttpClient、HttpWebRequest、UnityWebRequest三种类型分别给出示例:
4.2.1 HttpClient
using System;
using System.Net.Http;
using UnityEngine;
public class HttpDnsHttpClient : MonoBehaviour
{
private static readonly HttpClient httpClient = new HttpClient();
public async void MakeRequest(string url)
{
try
{
var uri = new Uri(url);
string hostname = uri.Host;
// 使用HTTPDNS解析域名
var result = HttpDnsHelper.resolveHostSyncNonBlocking(hostname, "auto");
if (result != null && result.IPv4 != null && result.IPv4.Count > 0)
{
string resolvedIP = result.IPv4[0];
string newUrl = url.Replace(hostname, resolvedIP);
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, newUrl))
{
// 关键:设置Host头保证SSL/SNI正确性
requestMessage.Headers.Host = hostname;
var response = await httpClient.SendAsync(requestMessage);
string content = await response.Content.ReadAsStringAsync();
Debug.Log($"请求成功: {response.StatusCode}");
}
}
}
catch (Exception e)
{
Debug.LogError($"请求失败: {e.Message}");
}
}
}4.2.2 HttpWebRequest
using System;
using System.IO;
using System.Net;
using UnityEngine;
public class HttpDnsWebRequest : MonoBehaviour
{
public void MakeRequest(string url)
{
try
{
var uri = new Uri(url);
string hostname = uri.Host;
// 使用HTTPDNS解析域名
var result = HttpDnsHelper.resolveHostSyncNonBlocking(hostname, "auto");
if (result != null && result.IPv4 != null && result.IPv4.Count > 0)
{
string resolvedIP = result.IPv4[0];
string newUrl = url.Replace(hostname, resolvedIP);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(newUrl);
request.Method = "GET";
// 关键:设置Host头保证SSL/SNI正确性
request.Host = hostname;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
string content = reader.ReadToEnd();
Debug.Log($"请求成功: {response.StatusCode}");
}
}
}
catch (Exception e)
{
Debug.LogError($"请求失败: {e.Message}");
}
}
}4.2.3 UnityWebRequest(不推荐)
由于UnityWebRequest无法正确配置SNI(服务器域名指示)信息,当服务器依赖SNI返回特定域名证书时,会导致SSL验证失败。因此处理这类域名时,推荐使用前两种网络请求方式。
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class HttpDnsUnityWebRequest : MonoBehaviour
{
public IEnumerator MakeRequest(string url)
{
var uri = new Uri(url);
string hostname = uri.Host;
// 使用HTTPDNS解析域名
var result = HttpDnsHelper.resolveHostSyncNonBlocking(hostname, "auto");
if (result != null && result.IPv4 != null && result.IPv4.Count > 0)
{
string resolvedIP = result.IPv4[0];
string newUrl = url.Replace(hostname, resolvedIP);
using (UnityWebRequest request = UnityWebRequest.Get(newUrl))
{
// 关键:设置Host头
request.SetRequestHeader("Host", hostname);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log($"请求成功: {request.responseCode}");
}
else
{
Debug.LogError($"请求失败: {request.error}");
}
}
}
}
}4.3 测试UI使用
项目提供了两个测试UI创建器:
基础测试UI: 通过菜单
HttpDNS/Create DNS Test UI创建高级测试UI: 通过菜单
HttpDNS/Create Advanced Test UI创建
测试UI包含完整的功能演示,帮助您快速验证集成效果。
五、API参考
5.1 初始化方法
init
初始化HTTPDNS服务。
// 基础初始化
HttpDnsHelper.init(string accountId, string secretKey);
// 完整初始化
HttpDnsHelper.init(string accountId, string secretKey, string aesSecretKey);参数说明:
accountId: HTTPDNS账户ID(必选)secretKey: 访问密钥(可选,用于鉴权)aesSecretKey: AES加密密钥(可选,用于加密)
build
构建HTTPDNS服务实例,在设置完所有配置后调用。
bool success = HttpDnsHelper.build();返回值:
true: 构建成功false: 构建失败
5.2 配置方法
debug
控制是否打印调试日志。
HttpDnsHelper.debug(bool enable);setHttpsRequestEnabled
设置是否使用HTTPS进行DNS查询。
HttpDnsHelper.setHttpsRequestEnabled(bool enable);setTimeout
设置DNS查询超时时间。
HttpDnsHelper.setTimeout(int timeoutMs);setPersistentCacheIPEnabled
设置是否启用持久化缓存。
HttpDnsHelper.setPersistentCacheIPEnabled(bool enable, int cacheTTL);参数:
enable: 是否启用cacheTTL: 缓存TTL时间(秒)
setReuseExpiredIPEnabled
设置是否允许复用过期IP。
HttpDnsHelper.setReuseExpiredIPEnabled(bool enable);setPreResolveAfterNetworkChanged
设置网络切换时是否自动刷新预解析。
HttpDnsHelper.setPreResolveAfterNetworkChanged(bool enable);5.3 解析方法
getIpsByHostAsync
异步解析域名。
List<string> ips = HttpDnsHelper.getIpsByHostAsync(string hostname);返回:IP地址列表,如果解析失败返回null或空列表。
getIpsByHost
同步解析域名。
List<string> ips = HttpDnsHelper.getIpsByHost(string hostname);resolveHostSyncNonBlocking
同步非阻塞解析,返回详细信息。
HttpDnsResult result = HttpDnsHelper.resolveHostSyncNonBlocking(string hostname, string ipType);参数:
hostname: 要解析的域名ipType: IP类型 (“auto”, “ipv4”, “ipv6”, “both”)
返回对象包含:
IPv4: IPv4地址列表IPv6: IPv6地址列表TTL: 缓存存活时间Extra: 额外信息
5.4 预解析方法
setPreResolveHosts
设置预解析域名列表。
// 单个域名
HttpDnsHelper.setPreResolveHosts(string hostname);
// 多个域名
HttpDnsHelper.setPreResolveHosts(List<string> hostnames, string ipType);5.5 缓存管理
clearCache
清除指定域名的缓存。
HttpDnsHelper.clearCache();cleanAllHostCache
清除所有域名缓存。
HttpDnsHelper.cleanAllHostCache();5.6 辅助方法
getSessionId
获取当前会话ID。
string sessionId = HttpDnsHelper.getSessionId();六、常见问题
6.1 Android构建问题
问题: Gradle 无法解析 com.aliyun.ams:alicloud-android-httpdns 依赖或构建失败。
解决:
启用自定义 Gradle 模板(Player Settings -> Publishing Settings -> Custom Main/Base Gradle Template)。
检查
Assets/Plugins/Android/mainTemplate.gradle:repositories是否配置了阿里云远程仓库镜像。dependencies中存在implementation 'com.aliyun.ams:alicloud-android-httpdns:版本号'。
6.2 iOS构建问题
问题: iOS构建后找不到CocoaPods依赖。
解决: 确保按照构建说明执行 pod install 命令,并使用 .xcworkspace 文件打开项目。
6.3 C SDK平台问题
问题: C SDK平台缺少原生库依赖。
解决:
Windows: 确保安装了VCPKG并设置了环境变量
macOS: 确保安装了Homebrew依赖库
检查构建后处理器是否正确复制了库文件
手动复制依赖库到构建目录
6.4 网络请求问题
问题: HTTPS请求失败,提示证书错误。
解决: 确保设置了正确的Host头,使用原始域名而不是IP地址作为SNI。