困った時の自分用メモ

読んだ本を考察してメモったり、自分でいじった物の感想をメモったりする場。週1更新を目指します。

Unityの話~StreamingAssets以下に全角文字のファイル名のファイルがあると、Android実機転送が失敗する話~

StreamingAssetsフォルダ以下に、全角文字が入ったファイル名を置くと、Android実機転送時に、

 

C:\****\cocos_android\android-sdk-windows\build-tools\build-tools-23.0.1\aapt.exe package -v -f -F raw.ap_ -A raw -0 ""

stderr[
raw\����������.lua: error: Invalid filename.  Unable to add.
]
stdout[
Found 67 custom asset files in raw
]

 

とか言われて、怒られる。注意されたし。

Luaの話~処理をLuaに移して感じた事~

〇便利だと感じる事

スクリプトの修正をしても、コンパイルが走らない
⇒Unity側も、マルチスレッドコンパイル?とか、待ち時間軽減しようと頑張っているけど、Luaなら待ち時間0。マジで0。修正して即プレイボタン押せる。
っていうか、Lua側の設計や使い方次第で実行中に読み込む処理のリロードも可能だと思われる。

 

〇不便だと感じる事

・ブレイクポイントデバッグが不可能
⇒ログ出力デバッグになる。ただ、実行時エラーは、Unity側から読み込んだ物は行数、doFileで追加したスクリプトに関しては、ファイル名と行数がUnity上にログ出力されるので、そこまでエラー箇所が意味不明な状態にはなりにくい。

・self関係がめんどくさい
⇒関数呼び出す時に、Class.Func()とClass:Func()で、引数に渡るものが変わってしまい、これ関係でバグ調査難航が何回もあったので、ルール決めとかないとアカンと思う。

・Utility機能系皆無。ほぼ自作
⇒あんまりLuaの書籍読んだり情報調べたりしてないから、もしかしたらそういうのあるのかもしれないけど、今のところ生のLuaのみで頑張って処理を書いている。

 

※パフォーマンスやApple申請関係のコスト・リスクは度外視のお話ですので、あしからず

 

Luaの話~データ設定でCSVを使う事が無くなるかも?~

ゲーム開発をした事がある人なら、誰しも一度はデータ設定の事について悩んだことがあると思う。
恐らく、大抵は「表計算ソフト」で入力されたものを、「プログラム上で扱える形式」に変換し、「変換された物を読み込んでパースし管理する」処理を記述する、
といった事をしたことがあるのではないかと思う。

しかし、Luaを使う場合は、
Luaスクリプトが、そもそも「プログラムで読み込める形式」(プレーンテキスト)で記述されている
・プレーンテキストなので、当然アセットバンドルにも組み込める(はず)なので、後から更新可能
Luaスクリプトで記述した物は、そのままオブジェクトとして利用可能←ここ重要

上記の特性から、変換とパースという作業が必要なくなる。
特に、3番目の記述した物が即利用可能というのが大きい。

例えば、こんな感じだ。

-----

EnemyConfig.lua

Enemy0001 = {
    ID = "0001",
    Name = "スライム",
    Hp = 3,
    Mp = 0,
    Attack = 1,
    EXP = 1,
}

Enemy0002 = {
    ID = "0002",
    Name = "ゴブリン",
    Hp = 5,
    Mp = 0,
    Attack = 3,
    EXP = 3,
}

GameMain.lua

function SpawnEnemy()
    local enemy1 = Enemy0001
    Print("名前"..enemy1.Name)--こんな関数はないけど、何か画面に表示する処理だと思ってもらえれば
    Print("HP"..enemy1.Hp)
    
    local enemy2 = Enemy0002
    Print("名前"..enemy2.Name)--こんな関数はないけど、何か画面に表示する処理だと思ってもらえれば
    Print("HP"..enemy2.Hp)
end

-----

UnityC#側だと、ScriptableObjectが似たような機能になるのかな?使った事ないんだけど(殴

もちろん、設定する要素数が増えたり、設定項目が複雑だったりすると、表計算を一次入力として利用し、
Luaスクリプト形式に変換する、といった事をやった方がいいと思うけど、
それでも、いちいちパース処理や管理クラス、読み込みマネージャを作る必要が無いのがいいかなと思う。
C#側でそれやろうとすると、それらを自動で作成するコードジェネレータを作らなければならなくなるのだが、
型のメタデータとか設計するのが非常にめんどくさいし、追加・保守も面倒だ(経験談

Luaなら、配列・小数・関数呼び出し設定からオブジェクト保持すらできるので、柔軟性は高い

-----
EnemyConfig.lua

-- クラス定義
EnemyParameter = {}
function EnemyParameter.new(hp, mp, atk, exp)
    local this = {
        LocalHp = hp,
        LocalMp = mp,
        LocalAttack = atk,
        LocalExp = exp,
    }
    
    this.Hp = function(self)
        return self.LocalHp
    end
    --以下、MPなども書く
    return this
end


Enemy0001 = {
    ID = "0001",
    Name = "スライム",
    Parameter = EnemyParameter.new(3, 0, 1, 1),--オブジェクトを持たせる事も可能
    FloatValue = 1.11,--小数も可能だし
    TableValue = {1,2,3,4,5},--配列(Luaではテーブルというけど)も可能
}

Enemy0002 = {
    ID = "0002",
    Name = "ゴブリン",
    Parameter = EnemyParameter.new(5, 0, 3, 3),
    FloatValue = 1.11,--小数も可能だし
    TableValue = {1,2,3,4,5},--配列(Luaではテーブルというけど)も可能
}

GameMain.lua

function SpawnEnemy()
    local enemy1 = Enemy0001
    Print("名前"..enemy1.Name)--こんな関数はないけど、何か画面に表示する処理だと思ってもらえれば
    Print("HP"..enemy1.Parameter:Hp())
    
    local enemy2 = Enemy0002
    Print("名前"..enemy2.Name)--こんな関数はないけど、何か画面に表示する処理だと思ってもらえれば
    Print("HP"..enemy2.Parameter:Hp())
end

-----

Lua側に全て処理を逃がすと、こういう事もできるようになるよ、というより「僕はそうやっているよ」というお話でした。

※パフォーマンスやApple申請関係のコスト・リスクは度外視のお話ですので、あしからず

Luaの話〜IOS実機で動かす際に、ネイティブプラグイン化する時の注意点〜

ぶっちゃけ、なんでこれで上手くいくかわからんけど、LUAのネイティブプラグインを作る時に、そのXCodeプロジェクトでいくつか設定が必要。

 

◯BuildSettings

・Architectures

→arm64 とだけにする

・Build Active Architexture Only

→No

◯Build Options

・Enable BitCode

→Yes

 

この辺やらないで作ったDLLでUnityのIOSビルドすると、XCode側のビルド終了間際に、そのDLLはarm64対応してる?だとか、BitCode EnableはYesになってる?的なことを指摘されるエラーが出るので、注意。

Luaの話~ブロック内のスコープ関係の話~

やらかしたミス

for i = 1, #skillTable do
    local table = skillTable[i]
    local val = #table
    LuaUnityDebugLog(#this.SkillMaxLevelList)
    table.insert(this.SkillMaxLevelList, val)
end

これをやると、table.insertの部分で「insertがnilっす」というエラーになる。
(正確には、attempt to call field 'insert' (a nil value))

理由は恐らく、local tableによって、このブロック内のtableは、skillTable[i]を指してしまっている為だろう。
んじゃ、本家のtableにアクセスしたい場合ってどうすればいいの?

シラネ^p^

 

とりあえず、tableって名前付けない事が一番。

Unityの話〜IOS実機にアプリを入れる時の注意点メモ〜

とりあえず、

MACのOSのバージョンを最新に(OS X El Capitan)(10.11.6)

XCodeのバージョンを最新に(8.1)

・UnityからXCodeプロジェクトを作成できて、ビルドが正常に通る、というところまでは上手くいくとする

 

詰まったところ。

・コードサインニング周り

→予め、AppleIDを作っておいて、プロジェクトメニューのGeneral→Signing→Teamを、その作ったアカウントに紐付ける。これは、毎回手動で設定する必要がある(Jenkinsからコマンドラインでビルドする場合は、何かしら方法はあると思う)。

・デバイス設定周り

→ビルド成功しても、このアプリは信頼されてないよ的なことを言われるので、デバイスの設定→一般→デバイス管理→登録してあるメアド?→信頼するを行う

Luaの話~LuaからUnity側へ、全角文字列を送る方法~

Lua側で設定をして、その設定をそのままUnity側に送るという事を想定している。

例えば、キャラクターの説明文などをLuaスクリプト上に記載しておき、それをUnity側に送ってTextに貼りつければそのまま表示される、といった具合だ。

 

で、そういえば全角文字列の表示検証した事なかったなと思い、試しに送ってみたら、見事に表示されない。

 

IntPtr res_s = NativeMethods.lua_tolstring(luastate, i, out res);
string resString = Marshal.PtrToStringAnsi(res_s);

 

このresStringが空になったのだ。

luastateを見る限り、文字列として認識している何かが格納されている、というところまでは判明したのだが、そもそもresの中身が0なので、LuaDLL側での処理で、送っているバイト文字が何か形式違反していて認識されていないのだろうと仮定し、それじゃあLuaスクリプト側の文字コードとかその辺が原因だろうという事で、色々試してみた。

 

sjis ⇒ 空文字

unicode ⇒ エラー(attempt to call a string value

UTF-8 ⇒ 空文字

unicode(BOM有) ⇒ 成功

UTF-8(BOM有) ⇒ 成功

 

というわけで、対症療法だけやるなら、Luaスクリプト文字コードUTF-8のBOM有にしておけばいいっぽい。

 

ただ、なんでそうなっているのかは、LuaDLLのプログラムまで見にいく元気がないので、今回は置いておくことにする…。