読者です 読者をやめる 読者になる 読者になる

AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

家を作ります

f:id:yasu9780:20170401214508p:plain

次のアップデートで家を作ろうと思って配置しているところです。
家具の色とか女の子っぽくないので、このへんも修正が必要( ゚Д゚)

前に$1で買ってた二階建てのアパートに、$3で買った一軒家の家具を入れ込んでるところです。
この$3の家がすごく細かく作られて、家具もしっかりついててとても$3とは思えないできです。

スクールガールズシミュレーター、現在ダウンロード722まで来ました。
10日で722ですね。昨日は1日で100DLされました。
評価も18人の方が評価されてて4.7と高評価です。ありがとうございます。
関連アプリのラインナップを見る限り、ゾンビとかVRで検索してきている人が多そうです。


こういう機能を追加したらいいみたいなアイデアは無数にあるのですが、ほかのゲームも作りたいので、色々考慮中です。


アプリ公開しました。公開直後にバグを見つけて再リリース(´・ω・`)
アプリ紹介サイトに登録されているけど、グラフで時間軸で変化が分かるのが分かりやすいし、ありがたい。
現時点で857DL(4/1)になりました。

http://applion.jp/android/app/com.Meromsoft.SchoolGirlsSimulator/market/

f:id:yasu9780:20170402211641p:plain
アパートの同じフロアに同級生が住んでますが、彼女の部屋に遊びに行って
ソファで並んでTVを見ています。
TVの前に置いてあるケーキとコーラを勝手に食べないように( ゚Д゚)

売店の売り上げを売店のおばちゃんの所持金にしたので、ランチタイム後はめっちゃ金持ってます( ゚Д゚)

SchoolGirlsSimulator関係

KUMAGAMESさんが、猫ペット導入してるわ!
もともとNEKOZ作ってた人だし猫好きなんだろうけど。声がやたらリアル「にゃあ」
www.youtube.com

自分も動物は導入しようと思ってたんだけど、飼育係で鶏を飼って、時々絞めては売店のおばちゃんに買ってもらう農園ゲームのノリを考えてたので、これみるとペットもいいなと。
犬にするかな。バイオハザードのゾンビ犬思い出すけど(´・ω・`)

自動販売機が日本式でやたらリアルでいい感じ。

黒髪ロングの猫耳だとRWBYのブレイクっぽくてかわいい。
f:id:yasu9780:20170326162811j:plain

(祝)7月にTokyoMXで放送決定
www.youtube.com


次に追加する仕様としては、やはり主人公の家を導入したい。どうせなら5人ぐらい住んでるアパートメントを学校の正門前に建設したい。
あと、学校外に24時間営業のコンビニを作って、帰宅後はそこで夕食の買い物をするとか。

本当はTheSimsみたいなゲームが作りたいんだけど、NavMesh使ってるから、ゲームの中でユーザーが部屋を増築したり家具を移動したりがやりにくいんだよね。
いづれはWayPoint探索で、実行時に障害物を移動できるような方向で改造したいと思う。
ただ二か月ぐらいこのゲームを開発してたんで、しばらくは別のゲームを作りたい気もしている。
www.youtube.com


TsundereSimulator2のDL数見たらもう10万から50万人になってる凄い( ゚Д゚)。ただバグが多いってレビューでは叩かれているけど。
もともとのTsundereSimulatorがDL数50万から100万なので、そこから集客しているのだろうか? 導線が謎だ。

現在のSchoolGirlsSimulatorは新着にも表示されないし、関連するアプリの一覧もまったく関係ない車のシミュレーターゲームばかりで、いったいどの導線からユーザーがアプリをインストールしているのか謎だ。
キーワード検索で来ているのだろうか?
SchoolGirlsとか、School Girlsだと、検索アプリ一覧に出るけど、
SchoolGirlだと検索結果に出てこない。

格安VPSのServersmanにfcgidを導入して高速化

ランダムマッチングのcgiをApacheBenchで速度を調べたところ、

Request per second がだいたい 2/sec

要するに一回の取得に0.5secぐらいかかっている。お、遅い! なんて遅いんだ!

これはやばい。さすがに月480円は伊達じゃない。

ということで、index.htmlに対して行うと

Request per second がだいたい 975.04/sec
さすがに十分早い。

ということは、遅い原因は、Apacheperlmariadbかのいづれか。
試しに、mariadbなしのCGIで調べると、
やはり Request per second だいたい2/sec

レコードが2件しかないのにmariadbが遅いってことはないだろ。
犯人は、perlapacheに絞られるが、index.htmlが遅くない以上、犯人はperlになる。

通常のcgiコンパイルやプロセス起動がHTTPアクセスの度に発生するので、このへんが格安VPSの劇遅いCPU環境で負荷になっているのではないだろうか。

参考ブログでも以下の言及があった。(10年前の記事w)

不必要なライブラリを極力ロードしないように気を付けているadiaryですら、
cgi実行時間の約9割がPerlのコンパイル時間です。

とうことで、このへんの負荷を低減するために、CGIプロセスが常駐するfastcgi環境を構築してみる。

yum install fastcgid

モジュールはこれであっさり入った。

locate "mod_fcgid.so"

ダイナミックリンクライブラリのインストール場所を確認する。
拡張子fcgiがfcgidで動くようにapacheの設定を変更。
httpdをrestartする


1文だけ表示するcgiを作って、通常とfastcgiで比較する

通常cgi
Request per second がだいたい 2.3/sec

fcgid
Request per second がだいたい 23.53/sec

おー!十倍速くなった! (それでも遅いんだけど。480円だし)
ただし、fcgiの中で、mysqlにアクセスするとうまく動いてない。
まだ調査中。

動いた。mysqlのハンドラをグローバル変数にしてて、その関係で動かなかった模様。
引数で渡したら動いた。
ただ、アクセス数を増やすとfailedの割合が増えるのでちょっととほほって感じ

kimoto.hatenablog.com

調べると、CGIのレスポンスの長さが変わったらfailedとみなす仕様らしい。
なんじゃそりゃ。
ランダムレコード取得だから、当然毎回長さは変わる。
SQLを動かした結果を表示せずにCGI終了させてみると、abのfailedは0になった。
別にCGIがこけているわけではない模様。

ab -n 50 -c 50でたたいても 24 Time per secondは出ていたので、めでたしめでたし。




fcgidで動かすperlスクリプト

#!/usr/bin/perl

use FCGI;

use CGI;
use strict;
use warnings;

my $request = FCGI::Request();

while ($request->Accept() >= 0) {

	our $cgi = CGI->new;
	print CGI::header(-charset=>"utf-8");

	print "FASTCGI";
}

exit;


参考
adiary.blog.abk.nu


tweeeety.hateblo.jp

爆弾追加

爆弾追加。
自陣深くまで引いておいて、ひきつけて爆弾で敵をせん滅w
爆弾というか地雷だな。

http://27.120.88.154/rts11.gif

対戦開始まで爆弾は見えないようにしておくといいですね。
軍人将棋のノリで( ゚Д゚)
爆弾だらけだどまずいので、設置コストは高めないとだめですが。

どの敵を狙うかという評価

AIの行動選択のうち、複数の敵がいる場合にどの敵を狙うか?は重要な戦略となります。
基本的には一番近い敵を狙うようにしていますが、その他の評価点として、

  • 味方が狙っていないフリーの敵を狙う
  • 味方が狙っている敵を狙う(数の暴力)
  • HPが減っている敵を狙う(とどめをさす)
  • HPが減ってない敵を狙う(まんべんなく攻撃する)

といった考え方ができます。


対戦させたみた感じでは、フリーの敵を狙うというのが有効みたいでした。
そのほかの戦略がだめなのは、あと一回矢が当たると死ぬ相手に、矢が3本当たるということは、限られた攻撃機会を無駄にしているわけです。
なるべくフリーの敵を失くすということは、無駄な攻撃を失くすという意味合いがありそうです。


下記は、同じ戦力で、左は(一番近い敵を狙う+フリーの敵を狙う)戦略で、右は戦略無し(一番近い敵を狙うのみ)
http://27.120.88.154/rts10.gif

このへんの戦略は、ゲーム作成する上で評価点として調整するところですが、
あえてユーザーにオプションとして開放するのもいいかなと思います。
ただ、フリーの敵を狙うのが最適解なら、みんな設定したほうがいいので、オプションの意味がなくなります。
ケースバイケースのオプションができれば、より望ましいと思います。

サーバーマッチングしてネット対戦する

サーバーからランダムマッチングできるようになった。

http://27.120.88.154/rts9.gif

Matchingボタンを押すとサーバーからランダムに対戦相手を取得する
Battleボタンで戦闘開始

マッチング後にユニットを増やしているが、これはできないようにした方がいいだろう。
クラクラの場合、マッチング後タイマーがあって、タイマーが来ると自動的に対戦開始になる。
あと、マッチングするたびにゴールドを消費する仕組みになっている。


マッチングは一覧から選ぶやりかたもあるが、それだと、別アカウントでつくった弱い相手を使って、不当に経験値を上げるといった恐れがでてくる
よって、クラクラはランダムマッチングしかないのだと思う。
ソーシャルゲームの農園ゲームなんかでは、別ユーザーの農園を代わりに収穫する機能があったりするが、放置農園を植民地にすることで、
どんどん収穫量を増やすとったことができてしまう問題点があった。
クラクラの場合、別アカウントを使うことで、援軍をつねに確保するといったチートはできてしまう。本来複数アカウントは禁止なんでしょうけど。


MySQLでのランダムレコード取得

SELECT s.* FROM data AS s INNER JOIN(SELECT CEIL(RAND() * (SELECT MAX(`id`) FROM data)) AS `id`) AS `tmp` ON s.id = tmp.id;

参考
qiita.com

MySQL: レコードがすでにあればUpdate。なければInsert

マップ配置データをサーバーに保存するにあたり、マップデータがすでにアップロードされていればUpdateし、新規であればinsertする処理を作りたい。


MySQLであればon duplicate key update機能を使う

INSERT INTO data (userid,data,datetime) VALUES(".$db->quote($userid).",".$db->quote($data).",NOW()) ON DUPLICATE KEY UPDATE userid=".$db->quote($userid).",data=".$db->quote($data).",datetime=NOW();"

同じuseridのレコードがあれば、dataとdatetimeのupdateが行われ、新規の場合は、Insertが行われる。

なお、重複チェックの対象であるuseridは、UNIQUEインデックス(かPRIMARY KEY)を指定しておく必要がある。
要するに、同じuseridのレコードは一つしかないという状態になっている。

同様な処理をするのに、以前は、まずselectしてデータがなければInsert。あればUpdateみたいなことをやっていたが、SQL発行が一回で済んで楽。


参考
qiita.com