PHPでもAndroidでも、過去の開発経験からいって、WebAPIに接続してデータを取得するという課題は必ずつきまとうし、また初回はつまづきが大きい。
でも一度やり方が分かってしまうと、あとは作っておいたライブラリファイルに処理を丸投げして終わりとか、コードのコピペ で終わりとか、さらりと出来てしまう。
なので、UnityでWebAPIに接続するサンプルを作っていた。
それなりに出来たのでGitHubにあげました。
https://github.com/ishiitakeru/Unity_WebApiConnectSample
主要なスクリプトはこれ
https://github.com/ishiitakeru/Unity_WebApiConnectSample/blob/master/WebApiConnectSample/Assets/script/ConnectWebApiSample.cs
説明。
WebAPIに接続して値をプロパティに格納する機能を持つのがWWWクラスのインスタンス。
POSTデータを送信するために使うのがWWWFormクラスのインスタンス。
WWWクラスをnewするときに WWWFormのインスタンスを引数に渡してやることでPOSTデータを送信する。
留意ポイントは、 WWWクラスのインスタンスは通信によって状態が変わるということ。
つまり、newした直後はWebAPIからのレスポンスがまだ受け取れていないので、取得した値を取り出せない。
しばらくして通信が完了すると、WWWインスタンスのプロパティから通信で手に入れたデータを取り出せる。
ということは、WWWインスタンスを生成したあと、その状態を時間経過に従って監視し続ける仕組みが必要。
そこで、コルーチンを使う。
コルーチンになっているメソッドでは、毎フレーム、yield return から次の yield returnまでが実行される。
つまり、コルーチンメソッドのすごいところは、 ひとつのメソッド内で時間経過で状態が変わることを取り込んで実現できるということだ。
そこで、WWWインスタンスによってWebAPIに接続するコルーチンメソッドは以下のような作りになるはず。
----------------------------------------------------------------------
private IEnumerator コルーチンメソッド名(){
//WebAPIにPOSTデータを送信するための WWWForm インスタンス
WWWForm my_www_form = new WWWForm();
//キーと値とのセットを登録
my_www_form.AddField("key", "value");
//WWWクラスのインスタンス作成
WWW my_www = new WWW(
"http://WebAPIのURL", //WebAPIのURL
my_www_form //POST送信値をセットしたWWWFormインスタンス
);
//↑ここまでは一度だけ実行されれば良い
//↓ここからは通信によるデータ取得が完了するまで繰り返し実行される必要がある
while(true){
//1フレームで、yield return から次の yield return まで実行される。
yield return null;
//WWW.isDone プロパティによって通信が完了したかどうかを調べられる。
if(my_www.isDone == true){
//通信完了
//WWWインスタンスからデータ取り出し
Debug.Log("Apiレスポンス : " + my_www.text);
break;
}else{
//まだ通信が完了してない
}//if
}//while
}//function
----------------------------------------------------------------------
コツ :
■WWWインスタンスは一度作ればいいので毎フレーム繰り返されるループの外で作っておく。
■WWW.isDone プロパティの確認を毎フレーム繰り返されるループ内で行う。
Androidの場合、別スレッドで通信処理を開始して、データ取得が終わったらそれを検知するコールバックメソッドからデータを取り出して、みたいにかなり複雑なことをやった記憶がある。
[Androidの場合]
■通信用にメインの処理とは別の非同期処理スレッドを作成し、通信はそこでしなくてはならない。
■通信完了を検知するコールバックメソッドを使い、通信で手に入れたデータをそこで取り出さないといけない。
UnityはAndroidに作りが似ているのかなと思ったけど、どうも、WebAPIとの通信においては非同期スレッドもコールバックメソッドも使わない(あるいは意識しないで良い)ということみたい。
その代わり、毎フレーム「yield return 」から「yield return 」まで繰り返し実行されるコルーチンという仕組みをきちんと理解する必要があるようですな。
仕事中に気づいたプログラミング上のTipsや備忘録をメモしておくための場所です。
[PHP][Android]など
ブログ主:いしいたける
メインのWebサイト(マンガ) : http://loveandcomic.com/
2016年5月14日土曜日
【Unity】コルーチンに登場するIEnumeratorとはなんぞや
Unityには処理をフレームごとに分割するコルーチン(Coroutine)という仕組みがある。
理解するためのキーワードが IEnumerator というクラス。
これは、yield return 文とセットで使われる。
これは、Listなどのコレクションに関連するクラスだが、コレクションそのものではなく、JavaでいうIterator のように「元となるコレクションがまずあり、それを反復処理するときに使う」クラス。
コルーチンのためのメソッドというものがまず作られる。
これは、返り値がIEnumeratorになるメソッド。
------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class CoroutineTest : MonoBehaviour {
//コルーチンで書き換える文字列
private string text_to_show;
//////////////////////////////
/**
* スタート
*/
void Start () {
//コルーチンをスタート
StartCoroutine(
SampleCoroutine()
);
}//Start
//////////////////////////////
/**
* コルーチンのテスト
* このメソッドはUnityで追加されたスクリプト(MonoBehaviour継承クラス)内に書かれる想定
*/
private IEnumerator SampleCoroutine() {
int i = 0;
while(true){
this.text_to_show = "test " + i;
i++;
//コンソールに出力
Debug.Log("text_to_show : " + this.text_to_show);
//2秒待つ
//n秒待たせるには、yield return 文でnew WaitForSeconds(n)を戻させなくてはならない。
yield return new WaitForSeconds(2);
}//while
}//function
}//class
------------------------------------------------------------------------
while(true) があるから無限ループのように見える、もしくは (yield) return のところで処理が終わってそうに見える。
実際には、yield return のところで処理が呼び出し元に帰る。
そして、このメソッドの返り値であるIEnumeratorのインスタンスがMoveNext()を実行すると、前回 yield return した続きから処理が再開され、次の yield return まで処理が走る。
Unityの場合、この MoveNext() は明示的には書かれず、Unityが見えないところで自動で実行する。
その仕組が、Unityの持つ「StartCoroutine(コルーチンメソッド)」という命令。
これは、Unity によって毎フレーム「MoveNext()」が実行されるというもの。
IEnumerator とは、Iterator のような、コレクションを反復処理する際に使う反復子というインターフェイスの一種。
MoveNext() というメソッドを持っているのが特徴。
IEnumerator というのはつまり、元になるコレクションを持ってて(IEnumerator がコレクションから取り出されるとも言える)、MoveNext() によって次の値次の値とアクセスできるということ。
で、IEnumerator を返り値としてyield return するメソッドというのは、MoveNext()によって次の値を返す(次のyield returnの戻り値を返す)コレクションであると見ればいい。
IEnumeratorの元(持ち主)に2つの系統があると考える。
■Listなどのコレクションインスタンス
■yield return を持ち、IEnumerator を戻り値とするメソッド(コルーチン)
以下の変数とメソッドとは、似たようなことをやろうとしている。
------------------------------------------------------------------------
変数 test_list(コレクションのインスタンス)
------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class IEnumeratorTest01 : MonoBehaviour {
void Start () {
//IEnumerator のインスタンス(コレクション変数)
List<string> test_list = new List<string>();
test_list.Add("test01");
test_list.Add("test02");
test_list.Add("test03");
//コレクションからIEnumerator を取得
IEnumerator test_ienumerator = test_list.GetEnumerator();
while (test_ienumerator.MoveNext()) {
Debug.Log(test_ienumerator.Current);
}//while
}//Start
}//class
------------------------------------------------------------------------
メソッド TestIenumeratorMethod()
------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class IEnumeratorTest02 : MonoBehaviour {
void Start () {
//IEnumerator のインスタンス(yield return を持つメソッドからの戻り値)
IEnumerator test_ienumerator_by_method = this.TestIenumeratorMethod("test");
while (test_ienumerator_by_method.MoveNext()) {
Debug.Log(test_ienumerator_by_method.Current);
}//while
}//Start
//////////////////////////////
/**
* IEnumeratorの元となるコレクションに相当するメソッド
*/
public IEnumerator TestIenumeratorMethod(string str){
yield return str + "01";
yield return str + "02";
yield return str + "03";
}//function
}//class
------------------------------------------------------------------------
IEnumerator.Current コレクションの中での現在地のオブジェクトを返す。
IEnumerator.MoveNext() boolean を返す。コレクションの現在地(Current)を次の要素に移動させ、次の要素がある場合はtrueを、ない場合はfalseを返す。
理解するためのキーワードが IEnumerator というクラス。
これは、yield return 文とセットで使われる。
これは、Listなどのコレクションに関連するクラスだが、コレクションそのものではなく、JavaでいうIterator のように「元となるコレクションがまずあり、それを反復処理するときに使う」クラス。
コルーチンのためのメソッドというものがまず作られる。
これは、返り値がIEnumeratorになるメソッド。
------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class CoroutineTest : MonoBehaviour {
//コルーチンで書き換える文字列
private string text_to_show;
//////////////////////////////
/**
* スタート
*/
void Start () {
//コルーチンをスタート
StartCoroutine(
SampleCoroutine()
);
}//Start
//////////////////////////////
/**
* コルーチンのテスト
* このメソッドはUnityで追加されたスクリプト(MonoBehaviour継承クラス)内に書かれる想定
*/
private IEnumerator SampleCoroutine() {
int i = 0;
while(true){
this.text_to_show = "test " + i;
i++;
//コンソールに出力
Debug.Log("text_to_show : " + this.text_to_show);
//2秒待つ
//n秒待たせるには、yield return 文でnew WaitForSeconds(n)を戻させなくてはならない。
yield return new WaitForSeconds(2);
}//while
}//function
}//class
------------------------------------------------------------------------
while(true) があるから無限ループのように見える、もしくは (yield) return のところで処理が終わってそうに見える。
実際には、yield return のところで処理が呼び出し元に帰る。
そして、このメソッドの返り値であるIEnumeratorのインスタンスがMoveNext()を実行すると、前回 yield return した続きから処理が再開され、次の yield return まで処理が走る。
Unityの場合、この MoveNext() は明示的には書かれず、Unityが見えないところで自動で実行する。
その仕組が、Unityの持つ「StartCoroutine(コルーチンメソッド)」という命令。
これは、Unity によって毎フレーム「MoveNext()」が実行されるというもの。
IEnumerator とは、Iterator のような、コレクションを反復処理する際に使う反復子というインターフェイスの一種。
MoveNext() というメソッドを持っているのが特徴。
IEnumerator というのはつまり、元になるコレクションを持ってて(IEnumerator がコレクションから取り出されるとも言える)、MoveNext() によって次の値次の値とアクセスできるということ。
で、IEnumerator を返り値としてyield return するメソッドというのは、MoveNext()によって次の値を返す(次のyield returnの戻り値を返す)コレクションであると見ればいい。
IEnumeratorの元(持ち主)に2つの系統があると考える。
■Listなどのコレクションインスタンス
■yield return を持ち、IEnumerator を戻り値とするメソッド(コルーチン)
以下の変数とメソッドとは、似たようなことをやろうとしている。
------------------------------------------------------------------------
変数 test_list(コレクションのインスタンス)
------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class IEnumeratorTest01 : MonoBehaviour {
void Start () {
//IEnumerator のインスタンス(コレクション変数)
List<string> test_list = new List<string>();
test_list.Add("test01");
test_list.Add("test02");
test_list.Add("test03");
//コレクションからIEnumerator を取得
IEnumerator test_ienumerator = test_list.GetEnumerator();
while (test_ienumerator.MoveNext()) {
Debug.Log(test_ienumerator.Current);
}//while
}//Start
}//class
------------------------------------------------------------------------
メソッド TestIenumeratorMethod()
------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class IEnumeratorTest02 : MonoBehaviour {
void Start () {
//IEnumerator のインスタンス(yield return を持つメソッドからの戻り値)
IEnumerator test_ienumerator_by_method = this.TestIenumeratorMethod("test");
while (test_ienumerator_by_method.MoveNext()) {
Debug.Log(test_ienumerator_by_method.Current);
}//while
}//Start
//////////////////////////////
/**
* IEnumeratorの元となるコレクションに相当するメソッド
*/
public IEnumerator TestIenumeratorMethod(string str){
yield return str + "01";
yield return str + "02";
yield return str + "03";
}//function
}//class
------------------------------------------------------------------------
IEnumerator.Current コレクションの中での現在地のオブジェクトを返す。
IEnumerator.MoveNext() boolean を返す。コレクションの現在地(Current)を次の要素に移動させ、次の要素がある場合はtrueを、ない場合はfalseを返す。
2016年4月10日日曜日
【C# .NET Framework】C#の勉強を始めました
エンジニア職で転職活動をしていて、Unityでのゲーム開発を仕事にできたらいいなあと思っています。
ただ、いままでUnityを使ったこともなければゲームで使うような C系の言語もやったことがないので、すこしずつ勉強を始めました。
まずはUnityで使う言語であるC#を勉強しようということで入門書を購入しコードを書きながら読み進める。
やっぱりなにか作らないと勉強もはかどらないなということで、複数の画像をひとつのウィンドウに同時に表示する画像ビューワーのWindowsのアプリケーションを作っていました。
まだプロトタイプですが今日作った分を GitHubにアップしました。
https://github.com/ishiitakeru/MultiImagesViewer/blob/master/MultiImagesViewer/MultiImagesViewer.cs
■ドラッグアンドドロップによって、そのディレクトリ内の複数の画像を横に並べて連続的に表示する。
■設定によって表示画像数を2~4枚から選択できる。
■ウィンドウのタイトル部分に開いているディレクトリのパスを表示する。
■矢印キーの左右で画像を次・前と順次入れ替えられる。
手応えとしては、C#はJavaに似てて、.NET Framework はAndroidに似てますね。
この練習用のアプリ、あと追加したい機能:
■矢印キーの上下でディレクトリ移動が出来る。
ただ、いままでUnityを使ったこともなければゲームで使うような C系の言語もやったことがないので、すこしずつ勉強を始めました。
まずはUnityで使う言語であるC#を勉強しようということで入門書を購入しコードを書きながら読み進める。
やっぱりなにか作らないと勉強もはかどらないなということで、複数の画像をひとつのウィンドウに同時に表示する画像ビューワーのWindowsのアプリケーションを作っていました。
まだプロトタイプですが今日作った分を GitHubにアップしました。
https://github.com/ishiitakeru/MultiImagesViewer/blob/master/MultiImagesViewer/MultiImagesViewer.cs
■ドラッグアンドドロップによって、そのディレクトリ内の複数の画像を横に並べて連続的に表示する。
■設定によって表示画像数を2~4枚から選択できる。
■ウィンドウのタイトル部分に開いているディレクトリのパスを表示する。
■矢印キーの左右で画像を次・前と順次入れ替えられる。
手応えとしては、C#はJavaに似てて、.NET Framework はAndroidに似てますね。
この練習用のアプリ、あと追加したい機能:
■矢印キーの上下でディレクトリ移動が出来る。
登録:
投稿 (Atom)