mongoの負荷監視でちょっとつまづいた。
mongodbの監視でmongostatとmongotopコマンドを使いたかったのですが、
いくらコマンド打ってもlockedの値が表示されなくて詰んでました。
で、ドキュメント読み直した。
mongostat — MongoDB Manual 2.6.4
以下の記述があった。
The mongostat utility provides a quick overview of the status of a currently running mongod or mongosinstance. mongostat is functionally similar to the UNIX/Linux file system utility vmstat, but provides data regarding mongod and mongos instances.
で、読んでたけどよくわからん。
で、言われた。
「お前、mongosのステータス見てね?」
!
mongostatはデフォルトで27017番ポート見に行くんだけど、
私の環境では
mongos -> 27017
mongod -> 27018
で動いてた。
つまり、私はずっとmongosのステータスを見て
「lockが見えない!ムキー!」
って、なってたんですね。愚か。。。
お恥ずかしや。
pythonの軽量フレームワーク「Bottle」でpymongoを試してみました。
ちょっと仕事でpython使う機会あったので、なんか試してみたくてやってみた。
Bottle: Python Web Framework — Bottle 0.13-dev documentation
PyMongo 2.7.2 Documentation — PyMongo 2.7.2 documentation
で、やりたいこと
・webアプリ(webサーバ?)立ち上げる
・mongoにアクセス
・ユニットテスト書く
インストールはググるとたくさん出てくるので省略します。
pythonのバージョンは 2.7.5
bottleは手で落として、pymongoはhomebrewで導入しました。
・アプリの立ち上げ
8080番portでアクセスできるようにします。
1 ダウンロードしてきた「bottle.py」と同じディレクトリに「hello.py」を設置
hello.pyは以下の実装(bottle.pyのチュートリアルから引用)
from bottle import route, run, template @route('/hello/<name>') def index(name): return template('<b>Hello {{name}}</b>!', name=name) run(host='localhost', port=8080)
2 「python hello.py」を実行
Bottle v0.11.4 server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
3 「http://localhost:8080/hello/hogemoge」
たぶんこんな感じの画面でる。
OK!
・mongodbにアクセス
/hello/<name>で受け取ったnameをmongodbに保存します。
1 「pymongo」をインポート
import pymongo
2 受け取ったnameをmongoに保存する
コレクションを作成して、そこに詰めます
conn = pymongo.Connection()
db = conn.test
db.names
db.names.save({"name": name})
3 保存されたかどうか確認もできるように
現在保存されているnameの件数を画面に返しましょう
count = db.names.count()
return template('<b>Hello {{name}}</b>!<br/><br/>--- Access count ---<br/>{{count}}', name=name,count=count)
4 最終的にこんな感じの実装にしました
from bottle import route, run, template
import pymongo
@route('/hello/<name>')
def index(name):
conn = pymongo.Connection()
db = conn.test
db.names
db.names.save({"name": name})
count = db.names.count()
return template('<b>Hello {{name}}</b>!<br/><br/>--- Access count ---<br/>{{count}}', name=name,count=count)
run(host='localhost', port=8080)
5 画面はこんな感じ
アクセスするとAccess countが増えていきます。
・ユニットテスト書く
テスト書いてコンソール上から実行できるように
1 testクラス作成する
import hello
def test_hello_index():
assert hello.index("testman").find('Hello testman')
print "test close."
2 実行
nosetestで実行します。
----------------------------------------------------------------------
Ran 1 test in 6.213s
OK
と、こんなところで一旦終了。
bottleはすごい軽くて、pymongoも特に難しいこともなく使えて、
簡単なWEBアプリ組むにはもってこいな感じです。
ユニットテストも組めるし、設定さえ外の出せれば、それなりに大きいアプリなんかも、これで作れるんじゃないですかね!
作ったゲームのバグを直した話
using UnityEngine;
public class CoinController : MonoBehaviour
{
private Vector3 posArray;
private Vector3 pos1 = new Vector3(-6,26,0);
private Vector3 pos2 = new Vector3(-6,14,0);
private Vector3 pos3 = new Vector3(-6,4,0);
private Vector3 pos4 = new Vector3(0,20,0);
private Vector3 pos5 = new Vector3(0,9,0);
private Vector3 pos6 = new Vector3(6,26,0);
private Vector3 pos7 = new Vector3(6,14,0);
private Vector3 pos8 = new Vector3(6,4,0);
private Vector3 currentPos;
public AudioClip getCoin;
void Start() {
posArray = new Vector3{pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8};
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
AudioSourceController.instance.PlayOneShot(getCoin);
ChangePos();
}
}
void ChangePos() {
int i = (int)(Random.value * 7);
if (posArray[i].x == currentPos.x && posArray[i].y == currentPos.y) ChangePos ();
gameObject.transform.position = posArray[i];
currentPos = posArray [i];
}
}
なんでだろう。。。
で、ログ仕込んで確認したところ、、、最初は原因がよくわかりませんでした。
とりあえず、以下のようにしたら直りました。
void ChangePos() {
int i = (int)(Random.value * 7);
if (posArray[i].x == currentPos.x && posArray[i].y == currentPos.y) {
ChangePos ();
} else {
gameObject.transform.position = posArray[i];
currentPos = posArray [i];
}
}
で、再度考察したら原因がわかりました。コード的には前の状態でも問題ないと思っていたのですが、、、お恥ずかしい。
changePos(コインの位置を移動させる関数)はランダムで生成した変数から移動先の位置を算出するのですが、もし移動先の位置と現在のコインの位置が同じであれば、再度changePosが呼ばれるようになっています。これが原因でした。
どういうことかといいますと、、、順を追って説明します。
1 ユニティちゃんとコインが接触したタイミングでchangePosが呼ばれる(呼び出し①)
2 ランダム変数から移動先の位置を取得(posArray[A])
3 posArray[A]が現在のコインの位置と同じだったので再度changePosを呼び出す(呼び出し②)
4 再度ランダム変数から移動先(posArray[B])を取得し、現在のコインのポジションと別のポジションだったので、コインをその位置に移動(呼び出し②が完了)
5 呼び出し②が終わったタイミングで、呼び出し①の処理に戻ってしまう
6 ①がメソッド内部から②を呼び出している、かつ、呼び出し後の処理が分岐されていないためそのまま次の処理を継続してしまう
7 最終的に①の処理の最初で取得した移動先(posArray[A])に移動してしまう
8 posArray[A]は現在ユニティちゃんと同じ位置のため、一見すると同じ位置から移動していないように見えてしまう
と、いったことが原因でした。
再帰呼び出しとか、やるもんじゃないっすね。。。
ゆえに、if else で処理を分岐してあげることで、解決したというわけです。
いやあ、、、我ながらひどいコードでした。
ただ、リファクタけっこう好きなんで、けっこう楽しかったです。
やっぱりコード書いて、直して、書いて、直して、、、っていうのは楽しいですね。
過去の自分との対話みたいで。
このゲームではそんなにコード書いてないので、次作るやつは、もっとガッツリとロジック書けるようなゲームを考えたいですね。
画面上に表示したオブジェクトを再利用する
using System.Collections;
public class uni : MonoBehaviour {
private State state = State.Normal;
private GameMaster gm;
void Start()
{
gm = GameObject.Find("Root").GetComponent<GameMaster>();
}
void Update()
{
if(state == State.Inited)
{
state = State.Normal;
gameObject.rigidbody2D.isKinematic = false;
}
}
void OnTriggerEnter2D(Collider2D obj)
{
if (obj.name == "Ground" )
{
float f = Random.value * 8;
if (Random.value > 0.5f)
{
f = f * -1.0f;
}
gameObject.transform.position = new Vector3(f,6.0f,gameObject.transform.position.z);
gameObject.rigidbody2D.isKinematic = true;
state = State.Inited;
}
else if(obj.name == "UnityChan2D")
{
gm.substructLifeCount();
}
}
enum State
{
Normal,
Inited
}
}
ゲームサーバ勉強会に参加しました。
こちらに参加してきました。
講演者:@nsegaさま
■データベースを使った使用事例
■データベースを使った使用事例
AssetStoreの素材を始めて使った。
AssetStoreの素材を始めて使いました。
AssetStore自体はちゃんと知っていましたが、それを使ってゲームを作るのは初めてでした。
ぷよぷよ的なものを作ってみました。
ぷよぷよの中ってどうなってんだろ?
と思って、実際に作ってみようと思い、手を動かしてみた第一弾です。
仕組みとしては
・ブロックを配置できる位置を8×10に限定
・すべての位置で、現在ブロックが置かれているか否かを記憶
・ブロックが下に落ちるごとに置いてあるすべてのブロックに対して、隣または上にあるブロックと同じ色であるか?、を判定
・同じであれば削除
ってな感じです。
たぶんもっとシンプルなやり方があるかとは思いますが、
第一弾なので、まあいいかなと。
今回は久々にユニティちゃんを使わないでゲームを作成してみたのですが、
ゼロから何かを作るって言うのは、開放感があっていいですね。
あれがこうなっているから、こうしないといけないっていうのがないので。(もちろん、Unity使ってるので、Unityの制約みたいのには引っかかりますが)
ただ、それと同時にアセットストアの素晴らしさも実感しました。
ゼロから何かしようと思うとそれなりに壁にもぶつかるし、時間も掛かるので、
車輪の再発明しないで、本当に時間をかけるべきところに時間を使おう!
っていうスタンスを感じました。
ただ、自分以外の誰かに頼りっきりになって、
「なんでこれができないんだよ、むきー!」みたいになるのは愚かなので、
まあ、頼り過ぎず、一人でがんばり過ぎず、バランスが大切だなって思います。
それにしてもUnity、8割くらいまでできあがるのは早いですね。
しかしそこから細かい調整をするのが結構めんどくさいですね。
なんか、いろいろな所に手が届くのはすごくいいのですが、
本当にかゆい一点にはぎりぎりで届かない感じが出てます。
ただ、それを考慮しても
「なんとなく浮かんだことをパッと見せられる」
っていうののスピードがすばらしいです。
実際に見てみたらちょっと違うからこうしてみよう、みたいな変化のスピードにも、
十分対応できるんじゃないかと思います。
いやはや、Unity様々でございます(はーと)