お茶漬けびより

学んだことを整理する場所です。主に、C++, Unreal Engine 4 (UE4) を扱います。

UE4 で http 通信を行う

少し前に UE4 で http 通信をしようと思い、ネットで方法を探していたのですが、 バージョンの違いか、手順が悪いのか、上手くいかず悩んだ末、UE4 の公式ドキュメントの方法で出来たので、その方法をまとめます。

以下、自己責任で行って下さい。

UE4.10 How To Make HTTP GET Request in C++ - Epic Wiki

上記のURLの方法をそのまま行えば出来ます。

ただ、php 周りの説明が分かっている前提なので、その辺補足出来たらいいなと思い、この記事を書くことにしました。

環境

  • Windows 10
  • UE4.14.3
  • VisualStudio 2015
  • XAMPP 3.2.2

プロジェクトの作成

まず、新規プロジェクトでC++のタブを選択します。 そして、基本コード(BASIC CODE)を選択します。

f:id:pickles-ochazuke:20170213214210p:plain

すると、VisualStudio が立ち上がると思います。気長に全ファイルを読み込むのを待ちます。
読み込めました? では、ビルドしましょう。
とくに問題が起こらないとは思うので、次に進みます。

アクタの作成

UE4 のエディタで http を取得するアクタを作ります。
まず、コンテンツブラウザの新規追加を選び、新規 C++ファイル… を選択します。親クラスは、Actorを選択します。
ファイル名は何でもいいです。今回は、GetHttpActorとしました。あと、パブリック、プライベートは特に選択しませんでした。
クラスを作成をクリックして、リコンパイルが終わるのを待ちます。

ソースコードの編集

では、プロジェクトの中身をいじっていきます。

Build.cs

”プロジェクトファイル名”.Build.cs という名前のファイルが VisualStudio のソリューションエクスプローラーにあると思います。
今回、自分のプロジェクト名は、MyProject(つまりデフォルトの名前)にしたので、MyProject.Build.cs というファイルがあるはずです……ありました。

f:id:pickles-ochazuke:20170213220228p:plain

見つかりましたか? よく探してくださいね。ソリューションエクスプローラーの検索を利用するといいかもしれません。例えば、.Build.cs で検索してみましょう。Games のフォルダ内を探して下さい。もう見つかった? お疲れ様です。では、次に行きましょう。

先ほど見つけたファイル(画像だと MyProject.Build.cs)を開いてください。

MyProject.Build.cs

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore"});

"Http", "Json", "JsonUtilities" という一文があると思います。バージョンによっては違うかも……。 PublicDependencyModuleNames.AddRange を探すといいかもしれません。見つけたら、{}内に以下を追加します。
すると以下のようになると思います。

MyProject.Build.cs

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Http", "Json", "JsonUtilities" });

このファイルはこれで以上です。

Engine.ini

次は、Engine.ini ファイルを探します。VisualStudio は使いません。そこには表示されないからです。 プロジェクトフォルダが保存されている場所に移動してください。そして、今回のプロジェクト名のフォルダの中に移動します。Saved/Config/Windows と移動して下さい。もしかしたら Windows がないかもしれません。Config 以下まで移動したら、Engine.ini を探して下さい。自分は、MyProject/Saved/Config/Windows の下に Engine.ini がありました。そして、てきとうなテキストエディタで開きます。

そして、一番下に以下を追加します。

Engine.ini

[HTTP]
HttpTimeout=300
HttpConnectionTimeout=-1
HttpReceiveTimeout=-1
HttpSendTimeout=-1
HttpMaxConnectionsPerServer=16
bEnableHttp=true
bUseNullHttp=false
HttpDelayTime=0

追加したら、保存して閉じて下さい。またVisualStudio に戻ります。

GetHttpActor.h

http を取得するアクタを作ったと思います。そのヘッダファイルを開きます。
今回だと、GetHttpActor.h です。 まず、以下のようにインクルードファイルを追加します。

GetHttpActor.h

#include "Runtime/Online/HTTP/Public/Http.h"

public: 以下に次の内容を追加します。

FHttpModule* Http;

/* The actual HTTP call */
UFUNCTION()
void MyHttpCall();
 
/*Assign this function to call when the GET request processes sucessfully*/
void OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);

ヘッダファイルは以上です。

GetHttpActor.cpp

次は、ソースファイル GetHttpActor.cpp をいじります。まず、コンストラクタ AGetHttpActor() に以下を追加します。

Http = &FHttpModule::Get();

そして BeginPlay() に以下を追加します。

MyHttpCall();

以下のメンバメソッドを追加します。

GetHttpActor.cpp

/*Http call*/
void AGetHttpActor::MyHttpCall()
{
TSharedRef<IHttpRequest> Request = Http->CreateRequest();
Request->OnProcessRequestComplete().BindUObject(this, &AGetHttpActor::OnResponseReceived);
//This is the url on which to process the request
Request->SetURL("http://localhost:8081/WebApi/getint.php");
Request->SetVerb("GET");
Request->SetHeader(TEXT("User-Agent"), "X-UnrealEngine-Agent");
Request->SetHeader("Content-Type", TEXT("application/json"));
Request->ProcessRequest();
}

/*Assigned function on successfull http call*/
void AGetHttpActor::OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{

 //Create a pointer to hold the json serialized data
 TSharedPtr<FJsonObject> JsonObject;

 //Create a reader pointer to read the json data
 TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());

 //Deserialize the json data given Reader and the actual object to deserialize
 if (FJsonSerializer::Deserialize(Reader, JsonObject))
 {
 //Get the value of the json object by field name
 int32 recievedInt = JsonObject->GetIntegerField("customInt");

 //Output it to the engine
 GEngine->AddOnScreenDebugMessage(1, 2.0f, FColor::Green, FString::FromInt(recievedInt));
 }
}

ひとまずは、コピペで構いません。
お疲れ様です。C++ に追加することは以上で終了です。
ビルドが通るか確認しましょう。

これで、GetHttpActor をレベル上に置けば http を取得してくれるのですが、今の状態で行っても http は取得できません。http を発行してくれるサーバがないからですね。では、サーバの準備をしましょう。

XAMPP

サーバを立てる方法はいろいろありますが、今回は XAMPP を使います。 インストールの方法は、ネット上にたくさんあるので、そちらにお任せします。 例えばこれを見るといいでしょう。

XAMPP を立てるときにセキュリティが気になる人は、セキュリティの設定を行うか、ネット回線を切ってしまいましょう。

たぶん XAMPP を使って Apache を立てるとエラーが発生すると思います。 その場合、以下の記事を見ると解決するかもしれません。

余裕があれば、別記事にまとめたいと思います……。

PHP ファイルの作成

XAMPP を上手く入れることが出来ましたでしょうか? お疲れ様です。あと少しで完了です。では、XAMPP を無事インストールしたので、PHP のファイルを作ります。

以下の内容をコピペして下さい。

getint.php

<?php
    //Create a variable to be used in 
    $theVar = array('customInt' => 5);
 
    //Set the headers
    header('Content-Type: application/json');
 
    //Encode the variable, and save the encoded string
    $encoded = json_encode($theVar);
 
    //Output it
    echo $encoded;
?>

そして、getint.php というファイル名にして保存します。 このファイルを以下に置いて下さい。

C:\xampp\htdocs\WebApi

WebApi フォルダは作る必要があると思います。XAMPP をインストールするときに、保存場所を変更した場合は、 C:\ の下にないかもしれません。getint.php ファイルを置くことが出来たら、少しだけ C++ ファイルをいじります(Apache のポート番号を変えていなかったら必要ないかも)。

C++ 側の URL を編集

GetHttpActor.cpp を開いて下さい。 そして、void AGetHttpActor::MyHttpCall() の中を見ます。

Request->SetURL("http://localhost:8081/WebApi/getint.php");

という一文があると思いますが、この SetURL の中身を変えます。 見ると分かるかもしれませんが、中身は URL を表しています。 注意してほしいのは、 localhost:8081 の 8081 です。Apache のポート番号とここのポート番号が合っていないと、正しく処理することが出来ません(URLの場所が見つからないからです)。

サーバを立てる

SetURL の中身を書き換えたら、XAMPP の Apache の Start のボタンをクリックして下さい。すると Apache の文字の周りが黄緑色みたいになると思います。黄色や赤色だと何か問題が発生していると思います。エラーの内容をコピペして検索してみましょう。

問題がない場合、サーバを立てることに成功しています。実際に確認してみましょう。ブラウザを開いて、以下のように入力します。

例えば、http://localhost:94/ とします(ポート番号は人によって異なります)。すると以下のような画面が表示されます。

f:id:pickles-ochazuke:20170214230230p:plain

SetURL と同じURLを指定してみましょう

http://localhost:94/WebApi/getint.php

すると以下のような文章が出ると思います。

{"customInt":5}

これが出ていれば成功です。
では、VisualStudio の方でビルドをします。成功したら、UE4 エディタに戻り、GetHttpActor を選択します。右クリックをして、「GetHttpActor に基づくブループリントクラスを作成します。」 を選択します。そして、てきとうなファイル名(自分は、MyGetHttpActor にしました)を設定し、てきとうな場所に作って下さい。そして、 MyGetHttpActor を開きます。開いたら、コンポーネントを追加で視覚的に置いてあることが分かるようなものを追加しましょう。自分はキューブを追加しました。そしてコンパイルをして、レベル上に配置します。

確認

最後に確認です。

  • XAMPP は正常に動作していますか?
  • Apache は正常に動作していますか?
  • ブラウザを開いて、http://localhost:94/WebApi/getint.php にアクセスすると、php のコードが正しく動いていますか? PHP のコードをコピペしていたら {“customInt”:5} のように表示されるはずです。
  • VisualStudio は正しくビルド出来ていますか?
  • SetURL の中身は http://localhost:94/WebApi/getint.php になっていますか?
  • UE4 のレベル上に GetHttpActor を継承したブループリントクラスのインスタンスが置かれていますか?

では、UE4 エディタのプレイをクリックしましょう。
以下の画像のように文字が表示されるはずです。

f:id:pickles-ochazuke:20170214231918p:plain

無事、http 通信をすることが出来ました。とても小さなことですが、これだけでもいろいろ幅が広がります。長くなりましたが、以上です。 お疲れさまでした。

おわりに

http 周りのソースコード調べないとなぁ……。
あと、分かりづらいところがあればコメントを下さい。