LoginSignup
0
0

More than 1 year has passed since last update.

Luaのメタテーブル内のテーブルに注意

Posted at

Qiitaの記事書くの初めてです。

Defoldというゲームエンジンを使ってたらLuaでちょっと気になることがあったのでメモ書き。
完全な自己理解なので間違ってたら教えてください。

問題

自力で書いた物理判定を使いたくて、Lua Moduleを使ってゲームオブジェクトとは別の物理判定用のテーブルを用意してそこで設置などの判定をしていた。

で、そのテーブルに基本の情報(速度とか摩擦とか)を持つメタテーブルを設定したんだけど、一部うまくいったりいかなかったりした。
 具体的には、メタテーブル内のテーブルへのアクセスうまくいかなかった。例えば、速度はvmath.vector3()で設定したんだけど、Bの速度を変更したらAの速度のみ変更になったりする感じ。

原因の予測

これはシンプルにLuaがtableを代入したときにすべて参照渡しになることと、メタテーブルの仕様が(たぶん)原因だった。
 普段↓こんな感じで書いてたんだけど

objs = {}
obj_meta = {}
obj_meta.name = "name"
obj_meta.max_spd =10
obj_meta.spd ={x =0,y=0}

function make_objects(name)
 local o = {}
 o.name = name
 setmetatable(o,{__index = obj_meta})
 table.insert(objs,o)
 return o
end

メタテーブルはこの時、新しいobjのmax_spdにアクセスしようとしたときに、obj_metaのmax_spdにアクセスするので、10が返る。spdも同様。

ただし、新たな値を代入するとき。

 local p = make_object("player")
 p.max_spd = 9
 p.spd.x = 100

とかするとき、max_spdのような値はobjのpの中に新しいmax_spdを作って、以後それにアクセスするようになる。
 でもspdのようにテーブル内の要素を変更するときは、metatable内のspdを変更することになってしまっていた。なので、spd.xを変更したときに別の要素のも変更されてしまっていたんだ、と思う。

解決法

メタテーブルの中にテーブルを入れないか、初期化の時に

 local p = make_object("player")
 p.spd = {x =0,y=0}

ってするみたいな感じにして解決した。

参照渡しと値渡しって混乱するなあ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0