みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

Unity Boo言語のまとめ(入門・基本編)

UnityのBoo言語の日本語の簡単なまとめです。Booに入門する人向けですが、みーが書式を忘れた際に参考にするためのものでもあります。

この記事はものすごく長いので、cmd+F か Ctrl+F で検索機能を駆使していただければ使いやすくなると思います。

Booとは

Pythonな.Netですね。通じる人にはこれで通じるはずです。つまり、表記はPythonっぽい、.Netです。静的言語で、それなりにたくさんのプラットフォームで動作します。UnityではjavascriptとC#とBooの3つの言語が使えますが,1つのスクリプトファイルが1つの言語で記述されていれば,複数の言語を混在することが可能です.

Unityでの書式(MonoBehaviour)

UnityのBooスクリプトは以下が原形である。

import UnityEngine
class example(MonoBehaviour):
    def Awake():
        #インスタンスが読み込まれた時に1度だけ呼び出される
    def Start():
        #いずれかのUpdate()が呼び出される直前に一度だけ呼び出される
    def Update():
        #毎フレーム呼び出される

つまり、defで関数を定義する。Pythonとは違ってclassの中にはself引数を伴わない。Awake(), Start(), Update()の順番に呼ばれて、Update()は定期的に呼ばれる。

public, private修飾詞の用途

Unityではpublic変数はinspectorパネルから変更・参照できる。キャラクターの座標など、パネルから操作したいものはpublicにすると便利である。

privateは他のclassからアクセスできないようにするためのもの。classの内部変数とかはこれを使って定義する。

private t1 as int
public t2 as int = 3
static public t3 as int = 4

変数と型

Booは静的言語なので、変数の型を指定する必要がある。Booは変数の型を推測しようとしてくれるので、書かなくてもよいことも多い。

s1 as int       #int型の変数s1を宣言
s1 = 1          #s1に1を代入
s2 as int = 3   #int型の変数s2を宣言し、3を代入
s3 = 1          #int型の変数s3を宣言し、1を代入(コンパイラは型を推測してくれる)
s4="abc"        #string型の変数s1が宣言され、"abc"が代入される

ポイントは、asを使うことと、型の推測があること。foo as intのようにasは後置修飾な使い方をする。1を代入すればintだろうなーと推測してくれるし、2.33を代入すればsingleだろうなーと推測してくれるが、トラブルを避けるためにもできるだけ型は明示しておいたほうがよいとみーは思う。

型について、int, bool, doubleなど、一般的なものと同じだが、1つだけ注意するべきことがある。floatではなく、singleという名前であること。single, double, (triple)...という統一感ある名前にしたかったのかもしれない。みーがはじめにむっちゃハマったので要注意!

v as float #error
v as single #OK

GetterとSetter

getNumber()やsetNumber(v as int)などをいちいち定義するのはすごく面倒なので、GetterとSetterを利用することをオススメします。これを使えば、例えば下の例のように、番号をsetするときに0以上の番号のみとする、という処理も簡単に書くことができます。また、privateに設定したnumber変数は外部からアクセスすることができませんが、getterとsetterは当然publicなので、外部からアクセスすることが可能です。下の例でコメントアウトしてある行では、number変数に直接アクセスしようとするとprotectionエラーが発生します。

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        car = Car()
        car.Number = 1
        Debug.Log(car.Number)
        car.Number = -1
        Debug.Log(car.Number)
        #car.number=1  ## "Car.number" is inaccessible due to its protection level.
    
    def Update ():
        pass

class Car:
    private number as int
    Number as int:
        get:
            return number
        set:
            if value>0:
                number = value
            else :
                number = 0
    
>>>1
>>>0

classのインスタンス化 (new演算子みたいなやつ)

Booではnew演算子はありませんが、

boo = Boo(1)

とすれば完了です。newを書く手間が省けていい感じです。

コメント

# これはコメント
// これはコメント
/* これはコメント */
/*  これは
コメント
だよー
複数行バージョン
 */

pythonの#流儀も、Javaの//流儀も、/* */も使用できます。

演算子

比較演算子

とりあえず、==を使って下さい。細かい所は下記を見て下さい。

数学

  • 足し算    a + b
  • 引き算    a - b
  • 掛け算    a * b
  • 割り算    a / b
  • 余り    a % b
  • 累乗    a ** b
  • 右へビットシフト    a >> b
  • 左へビットシフト    a << b

論理演算子

  • AND演算子    a & b
  • OR演算子    a | b
  • XOR演算子    a ^ b

キャスト

cast, as の2つがあります。

cast は データ型の変数をキャストするのに使用します。例えば下の例ではsingleがintにキャストされています。

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        z = 123.4 
        zz = z cast int
        Debug.Log(z) # 123.4
        Debug.Log(zz) # 123

asで型を指定してから暗黙なキャストを利用するのもおっけーです。

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        z = 123.4
        zz as int = z 
        Debug.Log(z) # 123.4
        Debug.Log(zz) # 123

このテクニックは後述するfor文で暗黙に行われるキャストを理解するのに重要です。

http://docs.codehaus.org/display/BOO/Casting+Types

関数

def example1():
    #引数なし、戻り値なし
def example2(w as string):
    #string型の引数w、戻り値なし
def example3() as string:
    #引数なし、string型の戻り値あり
    return "hello!"

asを使って型を指定します。

ループ

for

for i in range(10): とすれば、10回ループします。iには0から9までが代入されます。下の例で暗黙のキャストを説明します。

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        items = [7,8,5,4,1,2]
        for i in items:
            Debug.Log(i)
        for i as int in items:
            Debug.Log (i+1)
        #for i in items:
            #Debug.Log (i+1) # Operator "+" cannot be used with a left hand side of type "object" and a right hand side of type "int".

8行目で、as intとしてiの型を明示していますが、これによってlistから取得されたObject型がint型にキャストされています。これをしないと、iなら出力されるのに、1を足したら出力されないという奇妙な現象が発生します。inで取得された変数はObject型であることを忘れないようにしてください。

while

これは簡単です。Trueでなくなるまで繰り返すだけです。

i = 0
while i < 10:
    print (i)
    i++
>>>0から9まで出力

リスト

リストはPythonではお馴染みですね。Booでもほとんど同様に使用できます。リスト内包表記も、スライスも、なんでも来いです。

len(list)             #リストの要素数を返す
list.IndexOf("me")    #"me"があるindexを返す。つまり検索
list.Add("new item")  #"new item"をlistの最後に追加
list.Insert(4,"abc")  #index 4に"abc"を追加
list.Remove("bbb")    #"bbb"を削除
list.RemoveAt(1)      #index 1を削除
list.Remove(0)        #remove the zero item (not 1st item)
list += ["new"]       #"new"を最後に追加
list.Extend(["one","two"]) #"one","two"を最後に追加
list.Pop()            #最後の要素を返し、削除

スライスとリスト内包表記の例。パイソニストなら[for in if]は華麗に使いこなしたいところです。以下は小さな偶数の2乗を返すサンプルです。 

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        list = [x*x for x in range(20) if x%2==0]
        Debug.Log(list) # [0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
        Debug.Log(list[2]) # 16
        Debug.Log(list[2:4]) # [16, 36]
        Debug.Log(list[:4]) # [0, 4, 16, 36]
        Debug.Log(list[-3:]) # [196, 256, 324]
        Debug.Log(list[:]) # [196, 256, 324]
        Debug.Log(list == list[:]) # True
        Debug.Log(list is list[:]) # False

ちょっとしたことですが、リストのクローンは[:]とするだけでよいです。

検索

とりあえず、inを使えればオッケーです。

if "foo" in mylist:
    print "foo is in mylist"
if mylist.Contains("foo"):
    print "contains foo"
if "baditem" not in mylist:
    print "baditem is not in mylist"

文字列

文字列のフォーマット

\$を使う方法と、%を使う方法と、Formatを使う方法があります。お好きなものをどうぞ。それぞれで速度が違うのかもしれませんが、特に問題ではないでしょう。

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        vv = 2
        Debug.Log("value is $vv") # value is 2
        x=0.1
        y=0.2
        Debug.Log("position = ({0},{1})" % (x,y)) # position = (0.1,0.2)
        Debug.Log(string.Format("position = ({0},{1})", x, y)) # position = (0.1,0.2)

文字列のキャスト

文字列から数値にするには、Parse()を使います。数値から文字列にするには、ToString()を使います。

import UnityEngine

class test (MonoBehaviour): 
    def Start ():
        v = int.Parse("1000")
        Debug.Log(v+1) # 1001
        w = single.Parse("123.4")
        Debug.Log(w*2) " 246.8
        s = w.ToString()
        Debug.Log(s) # 123.4
        Debug.Log(s[:2]) # 12

Array (配列)

array()を使います。多次元配列なら、matrix()をどうぞ。Arrayの要素数はもちろんlen()です。

#1次の配列
a as (int) = array(int,20) #Arrayを作成
for i in range(len(a)):
    print(a[i])

#多次元配列
b as (int,3) = matrix(int,10,10,10)
for i in range(len(b,0)):
    for j in range(len(b,1)):
        for k in range(len(b,2)):
            print(a[i,j,k])

Enum

enumのあとに、列挙していけばEnumが作成されます。

enum Number:
        Zero
        One
        Two
        Three

b = Number.One
print("$b")
if b==Number.Three:
        print("b is not Number.Three")

Class

Pythonではdef init(self): を使用してクラスの初期化をしますが,Booでは def constructor(): を使用します.Pythonなのにコンストラクタというのは気持ちが悪いです...(T_T) ちなみにディコンストラクタもあります.

class Car:
    private number as int
    def constructor(_a as int):
        number = _a
    def destructor():
        pass

 

とりあえず以上です。適宜追加していきます。