Вы можете использовать плагин, чтобы заменить стандартный код, который Unity использует при встрече с классом WWW. Сделать это вы можете, например, чтобы изменить стандартное поведение кэша, который кэширует на основании только URL.
Следующий код (ниже описанный в деталях) отключает стандартный метод кэширования и добавляет хедер-поле “Secret” , в дополнение к хедерам, указанным из скриптового кода игры.
// Code placed at Plugins/iOS/CustomConnection.mm within the Assets folder.
#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];
// let's pretend for security reasons we dont want ANY cache nor cookies
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[request setHTTPShouldHandleCookies:NO];
// let's pretend we want special secret info in header
[request setValue:@"123456789"forHTTPHeaderField:@"Secret"];
return request;
}
@end
@interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
{
}
@end
@implementation UnityWWWCustomConnectionDelegate
- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
{
// we dont want caching
return nil;
}
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
// let's just print something here for test
[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
“Действие” происходит в методе allocRequestForHTTPMethod
, который запускается вызовом такого же метода в суперклассе:
@implementation UnityWWWCustomRequestProvider
+ (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
{
NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];
Оттуда вы отключаете стандартное кэширование данных, выполняемое iOS, и также отключаете куки:
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
[request setHTTPShouldHandleCookies:NO];
Далее, мы добавляем поле хедер названное “Secret”, которое предоставит некоторые дополнительные данные. В настоящей игре, это может быть значение, проверяемое сервером для подтверждения источника соединения.
[request setValue:@"123456789"forHTTPHeaderField:@"Secret"];
Теперь, когда у нас есть пользовательский класс для обработки запросов, нам также понадобится создать подкласс от UnityWWWConnectionDelegate
, чтобы настроить обработку связи:
@interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionDelegate
{
}
@end
Мы можем отключить кэширование данных вернув нулевое (nil) значение из метода connection:willCacheResponse:
:
- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
{
// we dont want caching
return nil;
}
Само соединение мы можем обработать из connection:didReceiveResponse:
, что должно вызвать такой же метод в суперклассе, чтобы действительно получить данные. В данном случае, при установке соединения мы просто печатаем сообщение в консоль, но вы можете реализовать всё, что захотите:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// let's just print something here for test
[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);
Пользовательский код весьма понятен для использования WWW класса в Unity - дополнительного кода в C#/JS скрипт добавлять не надо.