関数テーブル
if文はそこまで嫌いではないのだが、switchはとても嫌いだ。 というのもswitchを使うときは大抵その関数が大きくなるからだ!!(自分の書き方的な所もあるのだろうが) だからといってswitchをif文に変えれば嫌いじゃなくなる!! というわけでもない。 結局のところ関数の大きさによってはif文だろうがなんだろうが嫌いになるわけで。。。
こういった条件分岐により関数が大きくなる場合は各条件の内容を全て関数にして関数テーブルを利用することで1関数のサイズを小さく保ってやる。
[func03.cpp]はメンバ関数ポインタを利用しての実装
[func11.cpp]はC++11で追加されたstd::function・std::bindを利用しての実装
両方とも各関数を配列の中に格納し、インデックスで各関数を呼び出すことができる。 見てわかるように[func03.cpp]は呼び出し時に特定のインスタンスに対して関数の呼び出しを行っているのがコードを見るとわかるが、[func11.cpp]のテーブル作成時にインスタンスに対して束縛しているためただ関数を呼んでいるようにみえる。(この様に見せない記述方法もあるけど) [func11.cpp]の場合特定のクラスに対して紐付いているわけではないので、戻り値と引数さえ一致していればどんな関数でも入れることができる。
pythonでのデータ型
タプル
タプルは複数の要素から構成される。 初期化後に内包する値に対して変更することができないimmutableなコレクションとなる
python_tuple = ( "year", "month", "day", 1, 3 ) print( python_tuple )
タプルで要素に対してアクセスする場合は配列と同じようにindexを指定してアクセスする
print( python_tuple[0] ) print( python_tuple[1] ) print( python_tuple[2] )
タプルの内包要素数はlen関数で調べることが可能
print( len( python_tuple ) )
リスト
リストはタプルと同じように複数の要素から構成される。 リストはタプルと違い内包する値に対して変更を行うことが可能なmutableなコレクションとなる
python_list = [ "year", "month", "day", 1, 3 ] print( python_list )
各要素のアクセスや要素数はタプルと同じように行える
print( python_list[0] ) print( python_list[1] ) print( python_list[2] ) print( len( python_list ) )
リストの末尾に要素を追加する場合list.append関数を使用する
python_list.append( "time" ) print( python_list )
リストの末尾に複数の要素を追加する場合list.extend関数を使用する
python_list.extend( [1, 2, 3, 5] ) print( python_list )
リストから要素を取り出す場合list.pop関数を使用する
popValue = python_list.pop( 2 ) #指定したindexの要素の値を取り出す print( python_list ) print( "popValue =" + str( popValue ) ) popValue = python_list.pop() #引数を指定しない場合末尾から取り出す print( python_list ) print( "popValue =" + str( popValue ) )
リストから要素を削除する場合list.remove関数を使用する
python_list.remove( "year" ) print( python_list )
ディクショナリ
リスト・タプルと同じ様な構造ではあるが、キーと値がセットで内包されている
ディクショナリの宣言方法
python_dict = { "year" : 2013, "month" : 3, "day" : 31 } print( python_dict )
ディクショナリ型ではタプル・リストのようにindexでのアクセスをする場合は keyを配列の演算子に指定してやる
python_dict = { "year" : 2013, "month" : 3, "day" : 31 } print( python_dict["year"] ) print( python_dict["month"] )
要素に対してアクセスする場合はdict.get関数を使用することでも取得できる
python_dict = { "year" : 2013, "month" : 3, "day" : 31 } print( python_dict.get( "day" ) ) print( python_dict.get( "ddd", "NON" ) ) #キーが見つからなかった場合第2引数を返す
要素数はタプル・リストと同じように行える
python_dict = { "year" : 2013, "month" : 3, "day" : 31 } print( len( python_dict ) )
ディクショナリに要素を追加する場合dict[key] = valueと キーに対して代入をするようにすれば追加される
python_dict = {} python_dict["year"] = 2013 python_dict["month"] = 3 python_dict["day"] = 31 print( python_dict )
C#でUnixTimeを扱う
C#では時間計算をする際にDateTimeクラスを利用する。 DateTimeクラスではUnix時間を習得をすることができない。 そのためC#でUnixTimeを利用する場合utcから算出する必要がある.
UnixTimeは開始はUTCで1970年1月1日0時0分0秒から計算開始なので 現在のUTCからUnixTimeを引くことで現在時刻のUnixTimeを得ることができる。 ただUnixTimeから日本での時間を算出する際は指定時間のUnixTimeに対してUnixTimeの開始時間を換算するだけだとUTCでの時間で表現されるので日本時間にはならない。 そのためUTCから9時間(日本はUTC+9のため)進めてやる必要があるがDateTimeクラスに内部で計算をしてくれるメソッドがあるのでそれを利用して日本時間にしてやればいい。
C#での型変換
C#のキャストで詰まった所があったので忘れないように書いておこう。
C#の型変換は暗黙的変換と明示的変換の2つがある。
暗黙的型変換
変数に対して別の型の変数を代入すると自動的に型を変換してくれる機能。
int a = 10; long b = a; float c = 10.0f; double d = a;
このように普通に代入式を書いてやるだけで int → long float → double へと変換を行ってくれる。
ただ、暗黙的変換は変換後に情報が失われない場合にのみ可能という条件がつく。 例えば
long a = 10; int b = a; double c = 10.0; float d = c;
64bit整数→32bit整数への変換を行った場合コンパイルエラーになる。
明示的型変換
暗黙的変換で変換できない場合はこちらの明示的型変換を使用してキャストをしてやる必要がある。 暗黙的型変換でエラーになるコードも
long a = 10; int b = (int)a; double c = 10.0; float d = (float)c;
この様に「(変換後の型)変数名」という式にすることで変換を行うことができる。
※だからといってなんでも変換出来るわけではなく文字列型から値型などの無理な変換は行うことはできない。
ここまでは大まか知っていたが今回詰まったのは※で書いたなんでも変換出来るわけではない部分でどういった変換が可なのか不可なのかを知らなかったので発生した。
minijsonを利用してパースされたデータ取り出そうとした際にfloat型に変換しようとした際に[System.InvalidCastException]となってしまった。 minijsonでは値を全てobject型で保存してありobject型から型変換を行う際は明示的型変換でも変換が行えず例外になっていた。
object a = 1.0; float b = (float)a; // InvalidCastException
object型のデータを変換する場合元の型(minijsonの少数データならdouble型)に一度変換を行った後に変換を行ってやる必要がある。
プリミティブ型であればobject型から変換する場合であればConvertクラスを利用することで変換を行うことができる。
double型→object型→float型に変換したい場合は下記のようになる。
object a = 1.0; float b = System.Convert.ToSingle( a );
MonoBehaviourのUpdateメソッド
MonoBehaviourクラスのオーバーライドメソッドの中にUpdate関連のメソッドが複数ありそれぞれの違いを調べてのでまとめておく。
MonoBehaviourクラスに用意されているUpdate関数は下の3つがある。
Update
毎フレーム呼び出されるメソッド
LateUpdate
Updateメソッド同様に毎フレーム呼び出されるメソッド
Updateメソッドよりも後に実行されるためカメラの追従のように特定の処理の後に実行して欲しい場合に使うとよいかも。
FixedUpdate
一定間隔で呼び出されるメソッド
Updateメソッドは処理の重さによってコールされる間隔が変化するため物理演算などの正確な値を取得したい場合に利用する。
以上!!(内容はほぼリファレンスのコピーやん)
それぞれのUpdateメソッドは通常のコールタイミングが違う以外の差としてTime.timeScaleを0にして時間経過を停止してやった場合FixedUpdateが呼ばれなくなったがUpdateとLateUpdateメソッドは呼ばれた。
Unityでdot by dotの表示をする方法
Unityで2D機能がサポートされたのでいろいろと触ってみたけど
2Dスプライトをdot by dotで表示をする場合適切に設定をしてやらないとダメなので備忘録として書き記す。
まずゲームの2D描画用のカメラの設定を「Projection」から「Orthographic」に変更。
変更するとカメラのinspectorに「Size」という設定項目が表示される。
Cubeなどのプリミティブ型をScaleで設定した値そのままのピクセル数で画面上に表示をしたい場合は
「画面の高さ ÷ 2」で算出された値をサイズに設定してやればよい。
void Awake () { camera.orthographicSize = Screen.height / 2; }
スクリプトでやる場合Awakeで「画面の高さ ÷ 2」の値をsizeに設定してやればOK。
※このスクリプトの役割がこれだけなので削除してやったほうがいいかもしれないが。。。。
プリミティブ型を「1スケール値=1ピクセル」で表示する場合はこれでよいのだが2DSpriteの場合は 「Pixels To Units」という
指定ピクセル数を1Unityメートルで扱うようにする設定項目があるのでこいつを弄ってやる必要がある。
カメラのサイズを「画面の高さ ÷ 2」にした場合は「1スケール値=1ピクセル」として扱うようになるので
Spriteの「Pixels To Units」設定を同様に扱うように「1」の値を当てはめてやればいい。
例 iPhone4サイズでやる場合 縦960なので カメラサイズ:480 Pixels To Units:1
この設定の場合は1スケール値とピクセル数をイコールにする場合の設定なのでNGUIなどと一緒に利用する場合
UI部分とゲーム画面でScene上の見え方が違ってしまう。
同一にしたい場合はSizeを1に設定してやる必要があるので「Pixels To Units」をカメラサイズ1に対しての値に設定をしてやる必要がある
480:1 = 1:x x=480
となるので「Pixels To Units」を480に設定してやればdot by dotで表示することができる。