可以使用插件替换 Unity 在处理 WWW 类请求时使用的默认代码。例如,通过这种方式可以更改默认缓存行为(默认情况下仅基于 URL 进行缓存)。
以下代码(在下面有更详细的描述)禁用默认缓存方法,并且除了从游戏的脚本代码指定的标头之外,还向请求添加“secret”标头字段。
// 代码放置于 Assets 文件夹中的 Plugins/iOS/CustomConnection.mm 位置。
#include "Unity/WWWConnection.h"
@interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
{
}
+ (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
@end
@implementation UnityWWWCustomRequestProvider
+ (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
{
NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];
// 假设我们出于安全原因不希望有任何缓存和 Cookie
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[request setHTTPShouldHandleCookies:NO];
// 假设我们希望标头中包含特殊秘密信息
[request setValue:@"123456789"forHTTPHeaderField:@"Secret"];
return request;
}
@end
@interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
{
}
@end
@implementation UnityWWWCustomConnectionDelegate
- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
{
// 我们不希望缓存
return nil;
}
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
// 我们仅在此处输出一些信息进行测试
[super connection:connection didReceiveResponse:response];
if([response isMemberOfClass:[NSHTTPURLResponse class]])
::printf_console("We've got response with status: %d\n", [(NSHTTPURLResponse*)response statusCode]);
}
@end
IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);
代码细分如下。首先,我们创建 UnityWWWRequestDefaultProvider 的子类,从而提供已修改的 NSURLRequest 对象以进行连接。另一个选择就是从头开始在类中实现 UnityWWWRequestProvider 协议。但是,在这种情况下,我们希望使用 Unity 的现有代码。
@interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
{
}
+ (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
@end
“action”发生在 allocRequestForHTTPMethod
中,这是通过调用超类上的同一方法启动的:
@implementation UnityWWWCustomRequestProvider
+ (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
{
NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];
在此处,我们禁用 iOS 完成的默认数据缓存,并禁用 Cookie:
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[request setHTTPShouldHandleCookies:NO];
接下来,我们添加一个名为“Secret”的标头字段来提供一些额外数据。在真实游戏中,这可能是由服务器检查以验证连接源的值。
[request setValue:@"123456789"forHTTPHeaderField:@"Secret"];
创建了自定义请求处理类之后,我们还需要创建 UnityWWWConnectionDelegate
的子类来自定义连接的处理:
@interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
{
}
@end
我们可以通过从 connection:willCacheResponse:
方法返回一个 nil 值来禁用数据缓存:
- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
{
// 我们不希望缓存
return nil;
}
我们可以从 connection:didReceiveResponse:
处理连接本身,它应该调用超类上的同一方法来实际获取数据。在此处,我们只是在进行连接时向控制台输出一条消息,但您可以在此处实现所需的任何东西:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// 我们仅在此处输出一些信息进行测试
[super connection:connection didReceiveResponse:response];
if([response isMemberOfClass:[NSHTTPURLResponse class]])
::printf_console("We've got response with status: %d\n", [(NSHTTPURLResponse*)response statusCode]);
}
最后,我们向 Unity 注册新的连接委托和请求提供程序,以便在从脚本发出 WWW 请求时调用它们:
IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);
自定义代码对于在 Unity 中使用 WWW 类而言是透明的:不需要在 C# 脚本中添加额外的代码。