如雨露の日記

学んだことを書いていくサイトです。もし誤りがあれば指摘していただけると嬉しいです。

Facebook Bot APIをさくらインターネットのレンタルサーバーで動かしてみた

最近BOTが熱いですね。

一斉に情報を送信できたり、対話形式でのやりとりから情報を入手できるというのはとてもよさそうです。

さて、今回はSPAJAMというハッカソンでFacebook BOT APIを使ってみて色々と可能性を感じたのと情報がまだ少ないかなと思ったので導入的なものを書いてみました。

さっそく解説をしていきたいと思います。

こちらで開発者登録をしてない方は登録してください。

Facebook開発者 - 開発者向けFacebook

登録が完了したら、画面右上のマイアプリから新しいアプリを追加してください。

f:id:ninataka_japan:20160418142523j:plain

WWWでウェブを選んで適当なApp名を入れたらSkipしちゃって構いません。

 

f:id:ninataka_japan:20160418143919j:plain

Appを作ったら、Facebookページを作成 | Facebookから架空の人物やら適当に作ってください。

作ったらAppの画面に戻って左下にあるMessangerからトークンを生成しましょう。

生成するといってもFacebookのページを選ぶだけです。

その下にあるWebhookでユーザーからメッセージが飛ばされたときにコールバックされるURLを指定できます。

最初はFacebook側から送信されるものをきちんと処理しているかチェックされているようなので、正しくコードを書いてください。

public function hook() {
$hub_verify_token = "FacebookBotTest"; // 適当なトークン
if ($_GET['hub_verify_token'] == $hub_verify_token) {
echo $_GET["hub_challenge"];
} else {
echo 'error';
}
}

hub_verify_tokenの部分は自分で作成します

中身はなんでも大丈夫ですが、Facebook側から送るトークンと一致するようにしてください。

上手く行けばこのような画面になると思います。

なお、SSLが必要で送信先のURLはhttpsであるのが条件です。

さくらインターネットのコントロールパネルのドメイン設定→共有SSLを利用するに設定してください。

f:id:ninataka_japan:20160418155344j:plain

これで、アクセストークンとWebhookの設定が完了です。

では、BOTを起動しましょう。

curl -ik -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token="

 この<token>の部分に生成したページアクセストークンを設定してください。

 問題なければ

"success":true

と帰ってくるはずです。

これで問題なくBOTが動作するはずです。

ただ、今の段階ではBOTから何も帰ってこないので先ほど設定したWebhookのURLの中身を書き換えましょう

public function hook() {

define('VERIFY_TOKEN', 'あなたが設定したトークン');
$method = $_SERVER['REQUEST_METHOD'];
$access_token = "あなたのアプリのアクセストークン";


if ($method == 'GET' && $_GET['hub_mode'] == 'subscribe' &&
$_GET['hub_verify_token'] == VERIFY_TOKEN) {
echo $_GET['hub_challenge'];
} else if ($method == 'POST') {

// メッセージ受信
$json_string = file_get_contents('php://input');
$json_object = json_decode($json_string);
$from_user_id = $json_object->entry{0}->messaging{0}->sender->id;
$message = $json_object->entry{0}->messaging{0}->message->text;

//メッセージ作成
$post = <<< EOM
{
"recipient":{
"id":"{$from_user_id}"
},
"message":{
"text":"{$message}"
},
"notification_type": "REGULAR"
}
EOM;

$url = "https://graph.facebook.com/v2.6/me/messages?access_token={$access_token}";
$headers = array(
"Content-Type: application/json"
);

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$output = curl_exec($curl);
}
}

 改行されてないな・・・見難くてすみません。

 これで動くはずです。

動かない方はコードの中にerror_logを出力するようにして内部で何が起きてるのかを確認できるようにしてみてください。

私のはこのような感じです。

f:id:ninataka_japan:20160418221704j:plain

これはただ単にメッセンジャーから受け取った文章と同じ文章を返すだけですが、簡単に出来ますね。

トークン関係で悩むやつなんていないよね。

 

StateMachineBehaviourを使ってみる

Unity5ではステートにStateMachineBehaviourを継承しているスクリプトがアタッチできるようになり、そのステートの再生中にコールバックが呼ばれます。

一覧

・OnStateEnter ステートが呼ばれたとき(Updateの最初)

・OnStateUpdate ステートが呼ばれたとき(最初と最後以外のUpdate)

・OnStateExit ステートが呼ばれたとき(Updateの最後)

・OnStateMove MonoBehaviour.OnAnimatorMoveの直後

・OnStateIK MonoBehaviour.OnAnimatorIKの直後

 

実際に追加してみるとこの様な感じです。

f:id:ninataka_japan:20150727195158j:plain

1つだけではなく、複数スクリプトをアタッチすることが出来ます。

なので処理を細分化し、よりコンポーネント指向っぽい感じになりますね。

写真だと移動スクリプトと向きの変更スクリプト、アニメーションの速度変更スクリプトです、前者2つはともかく後者はなんでこんなことしてるか不思議に見えますよねw

Player制御のスクリプトがすっきりしそうです。というかUpdate内

のコードがほとんどなくなりました。

f:id:ninataka_japan:20150727195849j:plain

f:id:ninataka_japan:20150727203243j:plain

ちょうど今は敵キャラクターの制御を作成していて、EnemySTMを継承させてMoveというスクリプトからEnemyControllerの処理を呼び出しています。

敵キャラクター、プレイヤーの制御もこれでだいぶ作りやすくなったのではないでしょうか。

Photon Unity Networkingを試してみる(Animation)

原因がわかりました。

それは後述するとして、さっそくやり方を書いていきます。

今回はアニメーションを使うので前回と違ってアニメーションをしてくれるキャラクターが必要です。

 ここからSDユニティちゃんをダウンロードしましょう。

インポートした後にPrefabsのSD_unitychan_humanoidをHierarchyにD&Dした後にアタッチされているスクリプトを全てRemove Componentしてください。

今回はmecanimのアニメーションはシンプルにしました。

新しくAnimatorを作成してアニメーションを2つ追加しましょう。

f:id:ninataka_japan:20150717190446j:plain

 float型のRunSpeedをParametersに作成して

遷移条件を0.1でそれぞれGreater,Lessに設定してください。

f:id:ninataka_japan:20150717190448j:plain

f:id:ninataka_japan:20150717190449j:plain

作成したAnimatorをSD_unitychanのAnimatorのControllerにアタッチ。

これでmecanimは作成完了。

さて、UnityChanControllerのスクリプトはこちら

RunSpeedに値を流し込んでアニメーションが遷移するようになっています。

 後はこのようにコンポーネントを追加して

f:id:ninataka_japan:20150717190902j:plain

中身はこの様に設定してください。

f:id:ninataka_japan:20150717191135j:plain

これで完成!!、のはず

これをResourcesフォルダに新しくPrefabを作成してこれまで設定をしたSD_unitychanをプレハブ化してください。(私はUnityChanとしてプレハブ化しました)

あとはNetworkManagerの中のPhotonNetwork.Instantiateで生成するオブジェクトをプレハブ化したSD_unitychanに変更してビルド、実行してみてください。

このようになりましたか?


uploaded by ninataka_japan on GIFMAGAZINE

なっていれば完成です。お疲れ様でした。

なお、私が時間がかかっていた部分は同期オブジェクトが静止しているにもかかわらず、同期先でオブジェクトが動いていたことです。原因はPhoton Transform ViewのSynchronize PositionのExtrapolate Optionの設定ミスでした。

Extrapolateは、速度と最後の更新から経過した時間と位置を元にオブジェクトの今の位置を推定します。そのため、速度があまり変わらないオブジェクトに適していますが今回のようにユーザーが走らせたり止まらせたりできるものでは使わないほうがいいでしょう。

私はこちらもSynchronize Valuesにしていたので同期オブジェクトが動いてしまっていたんですね。

基本Disableにしたほうがいいかもしれません。

今回は以上です。

 

ユニティちゃんライセンス

このコンテンツは、『ユニティちゃんライセンス』で提供されています

UnityでGoogle Street Viewを表示させる

思った以上にアニメーションの同期に時間がかかっています。アニメーションは同期しているのですが、なぜかPositionがカクカクで・・・。

なので先にこっちを記事にします。

さて、Google Street Viewみなさん試したことありますよね?

今回はUnityでGoogle Street Viewを表示させてみようと思います。

コードはこちら

googleのstreet viewのURLを叩くときに経度と緯度、画像のサイズ、画像の向き、ズームとかいろいろ指定できるみたいです。すごい。

基本的にはlatitude,longtudeを変えるだけで使えると思います。

Skyboxの6面画像をStreet Viewから取得して張り付けしているだけなので特に変わったことをしているわけでないかと。

Skyboxは動的に作成しようとしたのですが、ビルドした後でエラーで怒られていたので外部からmaterialを生成してShaderをSkybox/6 Sidedにしたものをスクリプトにアタッチしてください。

 

LINQを使ってみる

C#LINQなるものがあるらしい。

というのを前から知っていたのですが、使う機会がなく半年くらいそのままでした。

しかし先日に後輩からUniRx便利ですよっ!!ってめっちゃ押されたので調べてみた

便利そうですね(小並)。

マウスのダブルクリックとか値を監視してイベントの発生とかしてくれるのはよさそう。Reactive Extensionsっていうらしい。

けれども、私は知識として前提条件のLINQを何も知らない!!ということでとりあえず触ってみることにしました。

まずは資料をネット探して、読んで同じ問題を解いてみました。

Unityで書いてます。(調べたとき丁度Unityを開いていたので)

まずは、最初に普通にコードを書いてみて

f:id:ninataka_japan:20150708172836j:plain

外部に数列生成部分を分けてみる。

f:id:ninataka_japan:20150708172833j:plain

f:id:ninataka_japan:20150708172835j:plain

それをLINQで取得するようにしてみる。

 

f:id:ninataka_japan:20150708172838j:plain

・・・とりあえず完成。

GetNaturalNamberからTakeWhileで条件を満たすものだけをWhereに流して、Whereで問題にそった3と5の倍数のみを取り出してSumで合計する。

ってことでいいのでしょうか。

書いてある事だけじゃ写経になってしまいますのでProject Eulerから問5を解いてみました。わざわざLINQ使ってすることではないのは分かっていますが、学習用ということで…w

f:id:ninataka_japan:20150708172839j:plain

もうチョイ抽出条件綺麗に書きたいなって感想しかない・・・

書き方は分かりました。が、ラムダ式とかまだ知らないことがさらに見つかったのでまだまだ覚えるべきことはありますね。

他の人の役には立たないけど、備忘録ということで今回の記事です。以上。

Photon Unity Networkingを試してみる(続き)

前回の記事の続きです。

前回の記事ではLerpで移動を行っていたため、同期のズレが目立ちました。

そこで公式で最もスムーズとされているSynchronize Valueを使ってみます。

まずはコードを書き直しましょう。

追加したのは this.GetComponent<PhotonTransformView>().SetSynchronizedValues(speed: move, turnSpeed: 0);

です。

SetSynchronizedValues(Vector3 speed,float turnSpeed)で速度と回転速度を修正、同期された値の更新を行います。

これでビルドをするとこんな感じに。



だいぶ滑らかに、リアルタイムに同期できているのではないでしょうか?

明日か明後日にはアニメーションの同期をやりたいと思います。

Photon Unity Networking 1.5 を試してみる

Unityでネットワークを簡単に実装する方法としてPhotonがよく使われています。

ネットワーク処理を殆ど書かずにリアルタイム通信ゲームが作れる優れものです。

ただ、色々なサイトでPhotonの記事が書かれているのですが、1.5の記事をあまり見かけなかったので自分で作ってみることにしました。

まずはPhoton Unity NetworkingをダウンロードしてUnityにインポート。

次にシーンを新しく作成して、空のゲームオブジェクトを作成してオブジェクト名をNetworkManagerにしてください。

Scriptフォルダを作成しNetworkManager.csを作成、開いてください。

さて、このNetworkManagerにはオンライン対戦でよく使われるルームの作成、ルームへの入場等を行ってもらいます。

 このスクリプトのPlayerMake()でプレイヤーとなるゲームオブジェクトをInstantiateします。このオブジェクトは相手側にも生成しないといけないのでPhotonNetwork.Instantiate()で生成をしましょう。このスクリプトNetworkManagerにアタッチしてください。

その後にProjectのなかにResourcesフォルダを作成、その中にPrefabを作成し名前をsampleCubeにします。

HierarchyからCubeを作成したらsampleCubeにprefabとして保存してCubeを削除。

Resources/sampleCubeを選択し以下の様にスクリプトとRigidbodyをアタッチ

・Photon VIew ・・・ Observed Componentsに監視するスクリプトを指定する。同期処理が書かれているスクリプトは全てここに。

・Photon Transform View ・・・ アタッチされているゲームオブジェクトのPosition、Rotation、Scaleの同期はこれ1つで大丈夫。

f:id:ninataka_japan:20150702234510j:plain

中身はこのように設定しています。

f:id:ninataka_japan:20150702235221j:plain

 

Synchronize Positionの設定

・Enable teleport for greater distances 同期が一定値以上ずれた場合オブジェクトをテレポートして位置を強制的に変更するか。

・Teleport if distance greater than その値以上同期がずれたらテレポートします。

・Interpolate Option(オブジェクト補間) 補完オプション。設定しないことはないと思う。

  1.  Disable(無効) これを設定することはほとんどないはず。
  2. Fixed Speed(固定速度) 固定されたスピードで動くオブジェクトならこれ。
  3. Estimated Speed(推定速度) 現在の座標と直前の座標から速度を割り出して移動させる。ゆっくり移動するものならこれ。
  4. Synchronize Value(値を使って同期) スクリプトで直接値を設定して同期する。一番スムーズ、けどデータ量増える。
  5. Lerp(線形補完) お手軽に使えるLerp。とりあえず動かしたいときはこれ。

・Extrapolate Option(オブジェクト補外) 補外オプション。過去のデータから現在どこにいるのか推測する。あくまでも推定。

・Draw synchronize position error(同期位置誤差の表示) Sceneに座標が表示される。

 

Synchronize Rotation/Scaleの設定

・Disabled(無効)  新しい値を受信したらオブジェクトに適用

・RotateTowards/MoveTowards オブジェクトがターゲットに向かって回転/スケールする。

・Lerp オブジェクトを指定値に向かって回転/スケールするらしい。

説明は以上です。

今回はLerpで行ってみましょう。

画像のように設定すれば大丈夫かと思います。Photon Viewにのbserved ComponentsにPhoton Transform Viewの設定をするのを忘れずに。

あとは適当にオブジェクトを移動する処理でも書いてsampleCubeにアタッチしてください。こんな感じで。

あとはビルドしてみて同期されるかどうか確認してください。Lerpで移動同期しているので滑らかではありますが、少し反映が遅れているはずです。

次回はSynchronize Valueの方法を試してみようかな。

若干疲れているので書き間違えていたりしたらすみません。