Unity

初心者が送る UnityでAPI通信講座


目的

unityで通信を行い、データベースへ情報を保存したり、データベースから情報を取得したりする。


学習内容

・URLから直接データを持ってくる

・データベースへ情報を保存する

・データベースから情報を取り出す


インターネット上の画像を描写する


新規Unityアプリケーションを作成する

新規アプリケーションを作成して開発を行うための準備を行います。

Unityを起動して、ページ上部にあるNEWを選択して下さい。

https://gyazo.com/f409583b987805393d5fd5018baac470

Project nameの入力欄に、「wwwtest」と入力して下さい。作成者が指定のフォルダ以下になっていることを確認します。3Dを選択した後に、Create projectを選択し、Projectを作成して下さい。

https://gyazo.com/cd26862e9dd6a5725876dd2104a7be80

以下のようになっていれば大丈夫です。

https://gyazo.com/f0c8b8568a58f11ca46787d46a93c11a


オブジェクトを配置する

シーン上にPlaneを配置して下さい。位置はInspectorビューのPossitionで指定できます。

Plane

Transform
x
y
z

Position
0
0
0

Rotation
0
0
0

Scale
1
1
1

以下のようになっていれば大丈夫です。

https://gyazo.com/1153d33a3a24c6fecc7f5c338334a472


Main Cameraの位置を変更する

GameビューにPlaneが上手く配置されるようにMainCameraの位置と回転を設定していきます。これらは、Inspectoreビューで設定できます。

Main Camera

Transform
x
y
z

Position
0
5
8

Rotation
30
180
0

Scale
1
1
1

https://gyazo.com/3827354ecb9b6abc8695d3839b90c261

Gameビューが以下のようになっていれば大丈夫です。

https://gyazo.com/d68054d45fe14461d3a38b67367a470f


Scriptsフォルダを作成する

Projectビュー内のAssets以下にScriptsフォルダを作成しましょう。

ProjectビューのAssetの上で右クリックをし、Createの中からFolderを選択して下さい。

https://gyazo.com/e68200c547cc455fd553850e69872486

すると、以下のようにNew Folderが作成されます。

https://gyazo.com/ea150c28055edb968598a86b2a905d25

New Folderを選択している状態で「New Folder」と書かれている部分をクリックすると名前を変更出来るようになります。名前を「Scripts」にして下さい。

以下の動画も参考にして下さい。

https://gyazo.com/c087f7d685238ef50baf36b5cb686eef


Scenesフォルダを作成する

Scriptsフォルダを作成したときと同様に、Scenesフォルダも作成しましょう。

以下のようになっていれば大丈夫です。

https://gyazo.com/7d2e412ac0a7454b0e57cf08d2a4f6e1


Sceneを保存する

⌘キーの後に、⌘キーを押したまま「s」を押して、Sceneを保存しましょう。Sceneの名前は「test」としましょう。

https://gyazo.com/bcdf0d2beeddc208cc810e9e0cb56b27

* Unityは突然ソフトがおちることがあるので、Sceneの保存はこまめに行うようにしましょう。


スクリプトを作成

インターネット上の画像をPlaneに描写するスクリプトを記述します。

ScriptsフォルダのなかにConnectionTest.csスクリプトを作成しましょう。

以下のようになっていれば大丈夫です。

https://gyazo.com/8f1a902a6c87266819560f7035ad4738


スクリプトに記述

実際にスクリプトを記述し、Planeに画像を描写しましょう。

ProjectビューのScriptsフォルダにある「ConnectionTest.cs」を以下のように編集して下さい。


Connection.cs

using System.Collections;

using UnityEngine;

public class ConnectionTest : MonoBehaviour {

string url = "http://cdn-www.dailypuppy.com/media/dogs/anonymous/coffee_poodle01.jpg_w450.jpg";

// Use this for initialization
void Start () {
StartCoroutine (Connect ());
}

// Update is called once per frame
void Update () {

}

private IEnumerator Connect(){
var www = new WWW (url);
yield return www;
GetComponent<Renderer> ().material.mainTexture = www.texture;
}
}


追加した部分を見ていきましょう。

6行目

    string url = "http://cdn-www.dailypuppy.com/media/dogs/anonymous/coffee_poodle01.jpg_w450.jpg";

文字列型(string型)の変数urlを定義し、画像のURLを代入しています。

10行目

StartCoroutine (Connect ());

コルーチンの開始を宣言します。

コルーチンとは実行を指定時間止める機能のことです。

18行目

private IEnumerator Connect(){

}

コルーチン関数の宣言を行っています。

unityでは通信を行う場合、通信が行われたフレームで値が返ってこないため、コルーチンを用います。

19行目

var www = new WWW(url);


var

Variant型と呼ばれ、何でも格納できる便利な変数です。スクリプトのコンパイル時に正しい型へと評価されます。

var a = 1;

var itemList = new List<int>();

と記述をすると、コンピュータが自動的にaはint型と、itemListはList型であると認識してくれます。つまり以下の記述と同じということになります。

int a = 1;

List<int> itemList = new List<int>();

以下の2つの場合に主にvarを使います。

・単なる初期化なのにきわめて長いコードになる場合

・長い文字数の同じ型を2回も書かなければいけないような場合

注意点としては、以下の2つがあります。

・varを使う場合は必ず初期化しなければいけない

・複数の変数を宣言することは出来ない

具体的には以下のようなスクリプトです。

var a;   \\初期化されていないのでエラーとなる

var a,b; \\複数宣言しているのでエラーとなる

*コンパイルとは、プログラミング言語で書かれたコンピュータプログラムを解析し、コンピュータが直接実行可能な形式のプログラムに変換することをいいます。


WWWクラス

WWWクラスとはWebにアクセスするためのクラスで、サーバーにGETとPOSTを行うことが可能です。

Webサーバからゲームのランキングやハイスコアなどのデータを取得する場合や、Webから画像を取得してテクスチャを生成したりするときに使用します。

20行目

yeild return www;

wwwの値が返ってくるまで処理を止めます。wwwの値が返ってくると、この次の行から処理が開始します。

21行目

GetComponent<Renderer> ().material.mainTexture = www.texture;


texture

WWWクラスに定義されていて、ダウンロードしたデータからTexture2Dを返す。

オブジェクトのテクスチャーの設定は、Rendererに設定されているMaterialインスタンスに用意されていて、テクスチャーイメージの設定はmainTextureというプロパティとして用意され、情報が保管されています。

よって、ここでは、ConnetctionTest.csがアタッチされているオブジェクトのテクスチャーイメージにwwwのデータをTexture2Dに変換したものを代入しています。

これにより、Planeにurlで指定した画像が張り付きます。


スクリプトをアタッチして実行

今作ったConnectionTest.csをPlaneにアタッチしましょう。

以下のようになっていれば大丈夫です。

https://gyazo.com/9166bf39cc48e342cd550d63f55af044

再生ボタンを押して、実行しましょう。

以下のようになっていれば、成功です。

https://gyazo.com/c175ea71992dbd2349544875c8e92ac7


光の反射をなくしましょう

現在のままだと、Planeに当たる光が反射してしまい、一部白くなってしまっています。

この光の反射をなくしましょう。

https://gyazo.com/61fdbb250106cfe9837d0145aef98df0


Materialの作成

光の反射をなくすためのMaterialを作成していきます。

ProjectビューのCreateのなかのMaterialを選択し、名前をPlaneとしましょう。

以下のようになっていれば大丈夫です。

https://gyazo.com/c023aa956605ffc7e1c6d7cdd91033ba

Planeを選択し、InspectoreビューのShaderのプルダウンメニューからUnlit->textureと選択しましょう。

以下の動画も参考にしてください。

https://gyazo.com/f84a2e926d7022a8ad77e6d892280fab


Materialをアタッチして実行

Planeに今作ったMaterialをアタッチしましょう。

以下のようになっていれば大丈夫です。

https://gyazo.com/83a7101fb5dec436586e2dee58eeb2f2

再生ボタンを押して、実行してみましょう。

以下のようになっていれば成功です。

https://gyazo.com/f7e14c67f44479293bca43f177951f3f


データーベースに情報を保存する

unityではデータベースとのやりとりはJSON形式で行います。

JSONとはRubyのハッシュオブジェクトのような形式です。あるキーに対して、あるバリューが紐付いています。ハッシュと同じく、バリューをハッシュのようにすることで入れ子構造を作ることも可能です。


Utilsのダウンロード

以下のボタンからLitJSON.dillをダウンロードしましよう。

ダウンロード

https://gyazo.com/53db20c625f1c35b4c25adc82edc3d4b

Finderのダウンロードの部分にLitJSON.dillというものが存在するのでそれをUnityのProjectビューにドラッグアンドドロップをしましょう。

https://gyazo.com/a0569c517f3d745ba9c855ef818e711f

分からない方は以下の動画も参考にして下さい。

https://gyazo.com/9c1895a2af5092416c75b73779184cfb


UserData.csの作成と編集

ProjectビューのScriptsフォルダを選択した状態でProjectビューのCreateを選択し、Folderを選択して下さい。新しく作成したフォルダをUserDataという名前にして下さい。

https://gyazo.com/089163d0046093bf8d4aa21364db2a73

Dataフォルダを選択し、Create->C# Scriptを選択し、UserData.csスクリプトを作成して下さい。

https://gyazo.com/a3930254b9abe1529e764840a0f817b0

UserData.csを以下のように編集して下さい。


UserData.cs

[System.SerializableAttribute]

public class UserData{

public string name;
public int age;
}


このスクリプトではクラスの定義のみを行うので、名前空間やイベント関数を必要としません。

名前空間とはスクリプトを作成したときに1,2行目に書かれいてるusingの次に書かれているもので、クラスの入っているパッケージを記述したもので、イベント関数とはStart関数やUpdate関数のことです。

では、スクリプトを見ていきましょう。

1行目

[System.SerializableAttribute]


System.SerializableAttribute

クラスとクラス内に定義されたpublicな変数をInspectorビューに表示し、Inspectoreビューで編集することを可能にするものです。

2~6行目

public class UserData{

public string name;
public int age;
}

UserDataクラスにstring型のnameとint型のageを定義しています。

これら2つの変数がInspectorビューで編集できるようになります。

後ほど、確認します。


JsonTest.csの作成と編集

Scriptフォルダを選択し、ProjectビューのCreate -> C# ScriptからJsonTest.csを作成して下さい。

https://gyazo.com/ce700694bad42062829f05b590493bcb

次に、JsonTest.csを以下のように編集して下さい。


JsonTest.cs

using System.Collections;

using UnityEngine;
using LitJson;

public class JsonTest : MonoBehaviour {

public UserData userData = new UserData();
public string url = "https://unity-api-falcon.herokuapp.com/api/users";

// Use this for initialization
IEnumerator Start () {
userData.name = "Yamada";
userData.age = 20;
string jsondata = JsonMapper.ToJson (userData);
print (jsondata);
WWWForm form = new WWWForm ();
form.AddField ("jsondata", jsondata);
var www = new WWW (url, form);
yield return www;
print (www.text);
}

// Update is called once per frame
void Update () {

}
}


3行目

using LitJson;

先程ダウンロードしたLitJsonを名前空間として使用しています。LitJsonはJSON読み書き用の名前空間で、データベースとの通信を行うために使います。

7、8行目

public UserData userData = new UserData();

public string url = "https://unity-api-falcon.herokuapp.com/api/users";

UserData型の新たな変数userDataとstring型の変数urlを生成しています。

urlにはデータベースのURLを代入しています。

11〜20行目

IEnumerator Start () {

userData.name = "Yamada";
userData.age = 20;
string jsondata = JsonMapper.ToJson (userData);
print (jsondata);
WWWForm form = new WWWForm ();
form.AddField ("jsondata", jsondata);
var www = new WWW (url, form);
yield return www;
print (www.text);
}

通信ではコルーチンを必ず用いなければならず、Start関数はコルーチンにすることも出来るので、voidではなくIEnumeratorと型宣言します。

12、13行目では、UserDataクラスの変数userDataのnameとageに値を代入しています。

14行目

string jsondata = JsonMapper.ToJson(userData);


JsonMapper.ToJson

引数のデータをネットワークで送受信できるよう(Unityの場合はJSON形式)に変換します。

今回の場合は変換したものをstring型のjsondataという変数に格納しています。

16、17行目

WWWForm form = new WWWForm ();

form.AddField ("jsondata", jsondata);


WWWFormクラス

WWWクラスを使用してWebサーバーにデータをPOSTするフォームを生成するヘルパークラスです。


AddField

WWWFormクラスのインスタンスに対して、使用します。第一引数にキー、第二引数にバリューを与えることで、送信する値を設定します。

今回においては、WWWFormクラスのインスタンス formを作成し、formにjsondataというキー、userDataをJSON形式にした値をバリューとするフィールドを作成していることになります。


空のGameObjectの作成

HierarchyビューのCreateからCreate Emptyを選択し、空のGameObject作成し、名前を「Jsontest」としましょう。

https://gyazo.com/59e13120429230fa9ccfae7691529141


スクリプトをアタッチして実行

Hierarchy上のJsontestオブジェクトに、先程作成したJsontest.csをドラックアンドドロップをしてアタッチしましょう。

https://gyazo.com/1f893a528dd2dc1c091bbb72d060f0b1

アタッチをすると、Inspectorビューにて先程定義したUserDateクラスを確認できます。

https://gyazo.com/e47793d9d174c7072c24c1bda621384d

最後にPlaneを非アクティブにしましょう。

HierarchyビューでPlaneを選択し、InspectorビューのPlaneの左のチェックボックスからチェックを外して下さい。

https://gyazo.com/1bd0dacb28f5e843afa997169c312b8d

それでは、再生ボタンを押して実行しましょう。

以下のようになっていれば成功です。

https://gyazo.com/6fd818b871965d14b2f1df9992dfe7d5


データベースから情報を取得する


スクリプトの作成と編集

ProjectビューのScriptsフォルダの中のDataフォルダ内にReceiveUserData.csスクリプトを作成しましょう。

https://gyazo.com/1253b1e5498d563c1177e502047179e0

スクリプトの作成が出来たら、以下のように編集しましょう。


ReceiveUserData.cs

[System.SerializableAttribute]

public class ReceieveUserInfoData {
public int
id,
age;
public string
name,
created_at,
updated_at;
}

このスクリプトは先程のUserData.csと同様にクラスの定義のみを行っています。

int型のageとstring型のnameに加え、データベースに保存したデータの番号を表すint型のidとデータベースに保存した時刻、変更を加えた時刻を表すstring型のcreated_at、updated_atを宣言しています。

以下のように、Inspectorビューで確認ができます。

https://gyazo.com/5ea080b3e5e28dee19a688bb06337485


JsonTest.csの編集

データベースから情報を受け取るための記述をJsonTest.csに加えます。 Scriptフォルダー内のJsonTest.csを以下のように編集して下さい。


JsonTest.cs

using System.Collections;

using UnityEngine;
using LitJson;

public class JsonTest : MonoBehaviour {

public UserData userData = new UserData();
public ReceieveUserInfoData receiveUserInfoData = new ReceieveUserInfoData();
public string url = "https://unity-api-falcon.herokuapp.com/api/users";

// Use this for initialization
IEnumerator Start () {
userData.name = "hikaru";
userData.age = 24;
string jsondata = JsonMapper.ToJson (userData);
print (jsondata);
WWWForm form = new WWWForm ();
form.AddField ("jsondata", jsondata);
var www = new WWW (url, form);
yield return www;
print (www.text);
receiveUserInfoData = JsonMapper.ToObject<ReceieveUserInfoData> (www.text);
}

// Update is called once per frame
void Update () {
print (receiveUserInfoData.name);
}
}


追記した部分を順に見ていきましょう。

8行目

public ReceieveUserInfoData receiveUserInfoData = new ReceieveUserInfoData(); 

先程作成した、ReceiveUserInfoDataクラスの変数receiveUserInfoDataを定義しています。

22行目

 receiveUserInfoData = JsonMapper.ToObject<ReceieveUserInfoData> (www.text);


JsonMapper.ToObject<>()

引数のJSON形式のデータを<>内で指定したクラスのオブジェクトに変換することで、Unity上で扱えるデータに変換します。

今回の場合はwww.testというデータベースから返ってきたJSON形式のデータに対して、ReceiveUserInfoData型を指定することで、receiveUserInfoDataがReceiveUserInfoData型のオブジェクトとなります。

27行目

print (receiveUserInfoData.name);

receiveUserInfoDataのうちnameの情報を毎フレームコンソールに出力する記述です。nameの部分をidに変えると、idの情報がコンソールに出力されます。


実行しよう

再生ボタンを押して実行してみましょう。実行後、すこしするとInspectorビューのReceive User Info Dataの部分にデータが入り、コンソールにそのnameの部分が出力されていれば成功です。

https://gyazo.com/eb7b4cb5689299ee160cd9366e960d4b

以上で、データベースとの通信ができるようになりました。これによって、ハイスコアやランキングの実装などが出来るようになります。