最近要做一个基于UE4的HTML5仿真项目,没真正做过HTML5的小白,表示很无所畏惧。
首先,找一篇UE4下H5的教程,简单学习一遍:
安装,环境,项目配置,(打包:不要pak;rendering:移动MSAA 选择NO MSAA;平台:HTML5,Packaging: 勾选Compress File during shipping package),最后下载一个X64的FireFox,或者Chrome。一个个搞下来,觉得已经七七八八了,信心满满。
二、拿个例子(“策略游戏”,又叫:StrategyGame)试验一下,StrategyGame本身不支持H5,不过难不倒我们,且如此来试试:
1、在支持的平台下拉框,勾选HTML5;
2、选择文件-->打包-->HTML5,选择一个目录,就开始等着吧,我这破机器,粗略估计花了20分钟;
3、在上一步选择的目录中,生成一个HTML5目录,进入该目录,找到HTML5LaunchHelper.exe,执行,启动了测试Web服务器,端口默认8000;
4、打开FireFox, 浏览器中输入:http://localhost:8000/StrategyGame.html。看到开始下载进度条,稍等几秒钟,就可以开始游戏啦。
三、用NodeJS的Express框架写了一个简易数据提供服务,执行:Node Sat.js。端口在:8081。链接地址:http://127.0.0.1:8081/A。
四、在UE4中,生成一个Actor,在Actor的BeginPlay()中,用Http模块去访问http://127.0.0.1:8081/A,并将结果AddOnScreenDebugMessage(), Alt+P播放一下,正常显示。
这一切都还是挺正常、挺简单的,然鹅,问题还没开始。
五、当我打包成HTML5以后,再测试,哇塞,没结果。后面便开始了我的漫漫探索之路:
1、可能是UE4的HTML5不支持“HTTP”请求,这个从之前的经验知道,HTML网页是用ajax请求数据的,又一百度,果然后人在说Emscripten,一个用来实现C语言和JavaScript相互调用的家伙,于是一骨脑的学了过了一遍Emscripten,学完了,也会一些你调我,我调你了。
2、再找一篇JavaScript的快速入门学习一遍,几天下来,基本语法什么的,都弄得差不多了。
3、于是:就跑到Actor中去,写一个ajax请求吧,于是,便有了:
#ifdef EMSCRIPTEN
extern "C" {
EM_JS(void, call_alert, (), {
alert('hello world!');
//throw 'all done';
});
EM_JS(void, getsatcount, (), {
$.ajax({
url: "http://127.0.0.1:8081/a",
data : {
zipcode: 97201
},
success : function(result) {
//$("#weather-temp").html("" + result + " degrees");
console.log(result);
//console.log('hello world!');
//callback(result)
},
error : function(result) {
console.log(result)
}
});
})
}
#endif
void AHttpActor::BeginPlay()
{
Super::BeginPlay();
#ifdef EMSCRIPTEN
getsatcount();
#endif
}
4、打包HTML5,漫长的等待之后,结果出来了,还是挺好的。
接下来的问题是,如何把返回的结果回调啊,再度娘吧。。。就在漫无目的的求索中的时候,
突然发现,UE4中有HTML5的实现,有个文件叫:HTML5HTTP.cpp,啊,原来前面的猜测都是错误的吗?
于是,迫不及待的翻了翻UE4的源码:...\Epic Games\UE_4.23\Engine\Source\Runtime\Online\HTTP\Private\HTML5目录
翻完之后,便又有了这一段代码:
void AHttpActor::MyHttpCall()
{
#ifdef EMSCRIPTEN
TSharedRef
#else
TSharedRef
#endif
Request->OnProcessRequestComplete().BindUObject(this, &AHttpActor::OnResponseReceived);
//This is the url on which to process the request
Request->SetURL("http://127.0.0.1:8081/a");
Request->SetVerb(TEXT("GET"));
Request->SetHeader(TEXT("User-Agent"), TEXT("X-UnrealEngine-Agent"));
Request->SetHeader(TEXT("Content-Type"), TEXT("application/json;charset=utf8"));
Request->ProcessRequest();
#ifdef EMSCRIPTEN
}
编译,打包成HTML5,浏览器又没出结果,伤心...哪儿错了...
这时,看到代码中有UE_Log(...),就想,这Log到哪儿去了呢,找啊找,原来在浏览器的F12中,唉,绕了一大圈,最后才绕回到超级无敌的F12,在Log中发现了问题:
已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8081/a 的远程资源。
对这个错误又是一无所知,唉,又一番尝试,一番折腾,捣鼓一会客户端,捣鼓一会Nodejs,再捣鼓一会UE,直到看到了这篇文章,https://www.jianshu.com/p/604f6d5b47d2,比较清晰的阐明了CORS的原理,才知道,原来B网站(UE4.StrategyGame),A网站(NodeJS),游戏页面(来自B网站)要访问A网站就存在跨域问题,要允许跨域,是要让A网站允许跨域,OK,明白之后,设置A网站的跨域就可以啦,如下:
//设置跨域访问
app.all('*', function(req, res, next) {
// 这里应该是来自UE4的网址:http://localhost:8000
if( req.headers.origin.toLowerCase() == 'http://localhost:8000'
|| req.headers.origin.toLowerCase() == 'http://127.0.0.1:8000' ) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", req.headers.origin);//
}
else
res.header("Access-Control-Allow-Origin", 'http://10.0.20.36:8000');
res.header('Access-Control-Allow-Headers', "Content-Type");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
// if (req.method.toLowerCase() == 'options')
// res.sendStatus(200); //让options尝试请求快速结束
// else
next();
});
最后:再介绍一下抓包工具:Fiddler, 很好用,下载后安装,即可使用,(通过使用代理,监听127.0.0.1:8888),实现抓包。