-------
http://unitygems.com/memorymanagement/October 21, 2012
---------
Static 関数
Static 関数は非Static クラスで実装することが出来て、この場合クラスの Static メンバのみが関数の中でアクセス出来る。static 関数はクラスをinstanceでなくclass経由でコールされ、存在してないかもしれないメンバをアクセスするのは不具合のもとであるため理屈に合う。
逆に、引数を渡すことは可能であり、この種の関数を使用することは良くあるはずだ。
Vector3.Distance(vec1.vec2); vec1.Normalize(); Application.LoadLevel (1); if (GUI.Button(Rect(10,10,50,50),btnTexture)){}このリストはどこまでも続けることが出来る。二つめの例は static メソッドでないことに留意してほしい。Vector3 型 の vec1インスタンスを通してコールされる。その他の例は static 関数をコールするためにクラスが使用されることを示す。
Static 関数は非Static関数よりも速い傾向があり、それはインスタンスの関数のコンパイラのコールはインスタンスの存在チェックでわずかなオーバーヘッドが生じるためであり、static 関数の場合はクラスが存在することが保証されている。ただし、この時間はきわめて小さな差だ。
もうひとつの Static クラスの長所はその存在が永続的でコンパイラに既知であるため、C# では、拡張メソッドを定義するために使用できることだ - これらは、どのような型の変数にでも追加できる関数のようなメソッドだ。これも static の良いところで、この方法で拡張したクラスは実際には開かれておらず(private および protected 変数は拡張メソッドで利用可能でない)、しかし、既存オブジェクトに新しい関数を提供するのに良い方法であり、開発者にとってコードが読みやすく、より簡単なAPIにつながる。例えばTransform に新しい関数を追加できる。
transform.MyWeirdNewFunction(x);
拡張関数の例:
既存のものを拡張する配列のための関数を作成したいとして(順に並べる、ソートの関数、等)、static 関数を宣言してこのリストを拡張することが出来る。
using UnityEngine; using System.Collections; public static class ExtensionTest { public static int BiggestOfAll(this int[] integer){ int length = integer.Length; int biggest = integer[0]; for(int i = 1;i < length;i++){ if(integer[i] > biggest)biggest = integer[i]; } return biggest; } }static 関数を宣言していて、渡された引数が関数をコールしているインスタンスであることを確認して下さい。この引数の型を修正することは他のオブジェクトで作業することを可能にします。
次に配列を宣言して値で埋めます。
using UnityEngine; using System.Collections; public class Test : MonoBehaviour { int[] array = {1,25,12,120,12,6}; void Start () { print(array.BiggestOfAll()); } }配列名のドットを入力すると、自身の新しい関数が候補として自動表示されるはずだ。
新しくより汎用的な、型に関わらず配列を受け入れる関数を作成すると決めた場合はstaticなジェネリック拡張メソッドを実装する。
using UnityEngine; using System.Collections; using System.Collections.Generic; public static class ExtensionTest { public static T TypelessBiggestOfAll <T> (this T[] t){ int length = t.Length; var biggest = t[0]; for(int i = 1;i < length;i++){ biggest =((Comparer <T>.Default.Compare(t[i], biggest) > 0) ? t[i] : biggest); } return biggest; } }using System.Collections.Generic; が追加されていることに留意してほしい。コンパイラはTの型が分からないため、値を < または > で単純に比較できない。しかし Comparer<T> 使用できる。例では、3つ組の演算子が使用されている。始めのうちはコーディングが少し難しいかもしれないが、行数を何行か節約できる。
using UnityEngine; using System.Collections; public static class GameManager{ public static void ClampTransform(this Transform tr,Vector3 move, Vector3 min, Vector3 max){ Vector3 pos = tr.position + move; if(pos.x < min.x ) pos.x = min.x; else if(pos.x > max.x) pos.x = max.x; if(pos.y < min.y ) pos.y = min.y; else if(pos.y> max.y) pos.y = max.y; if(pos.z < min.z) pos.z = min.z; else if(pos.z > max.z) pos.z = max.z; tr.position = pos; } }
a が実行され、もし true ならば b がコマンド実行され、もし false ならば c がコマンド実行される。通常の if 文と比較した長所は 比較から戻された値にある。
result = a ? b : c; 結果は a にもとづいて値 b または c を受け取る
これにより配列の異なる型を宣言して、同じ関数を使用することが可能だ。
using UnityEngine; using System.Collections; public class Test : MonoBehaviour { int[] arrayInt = {1, 25, 12, 120, 12, 6}; float[] arrayFl = {0.5f, 52.456f, 654.25f, 41.2f}; double[]arrayDb = {0.1254, -15487.258, 654, 8795.25, -2}; void Start () { print(arrayInt.TypelessBiggestOfAll()); print (arrayFl.TypelessBiggestOfAll()); print (arrayDb.TypelessBiggestOfAll()); } }
これにより 120, 654.25, 8795.25 の値が出力される。
次にこれが便利となる事例を示したい。多くの Unity ユーザはオブジェクトを領域内に制限する方法を聞く。例えば、オブジェクトを画面の範囲内に保持したい場合、次の関数を使用してオブジェクトの Transform を はさむ(Clamp)することができる。
そしてこのようにして必要なところでどこでも使用することができる:
Vector3 minVector = new Vector3(-10,0,-10); Vector3 maxVector = new Vector3(10,0,10); transform.ClampTransform(move,minVector,maxVector);この例では、オブジェクトは平面(y が 0 で固定して制限されていて、 (0,0,0) を中心に 20 x 20 の箱の中に収められる。
------
2013年に入ってもUnityの学習を積極的に進めようぜ!
0 件のコメント:
コメントを投稿