Gobe2というフィットネストラッカーを購入してからそろそろ半年になるので、ここでレビュー的なものを書いてみようと思います。
- Gobe2はフィットネストラッカーの一つ
- デザインは…厚い
- 時計として使えなくはない
- 一日の摂取カロリーは、多分あってるような気がする
- Gobe2「水を飲め水を」
- バッテリーは3日も持たない
- アプリは「雰囲気で使う」
- 結論
- 関連
続きを読む
Gobe2というフィットネストラッカーを購入してからそろそろ半年になるので、ここでレビュー的なものを書いてみようと思います。
続きを読む
今回は構造体を配列(NativeArray)にした時の、そのアクセスについてです。
最近よく紹介されているECSやC# Job Systemといった機能では、構造体をNativeArrayに乗せて一括制御するアプローチが見られます。
というのもECSやJobSystemはDODの考えでメモリ内にデータが散らばるのを嫌がるので、殆どStructで実装されています。
それ自体は大した問題では無いのですが、基本的に構造体の配列は参照渡し出来ないので少しコードが冗長になる印象があります。
出来れば構造体でも参照渡しで直接値を書き換えたい所です。
今回はそれを色々とやってみます。
C#で参照渡しといえばrefやoutです。
構造体などの基本的にコピーを生成する受け渡しであっても、refを指定しておければ参照を渡して中身を書き換えることが出来ます。
ただ残念なことに、通常の構造体なら問題なくとも配列に対してとなると上手くはいきません。配列(インデクサー)は残念ながらoutやrefを使えないのです。
最終手段です。unsafeを使います。ポインタを使用してNativeArrayの各要素に直接語りかける訳です。
GetUnsafeReadOnlyPtrを使用してNativeArrayのポインタを取得、あとは要素をズラせば中身が取れます。
ただ、何かの処理を行う場所でもunsafeを要求するのは余り良くないかもしれません。
なおNativeArrayにfixedは必要ありません。
またNativeArrayは連続していますがComponentDataArray等のECSがInjectする要素は連続してるとは限らないので、要素をずらした時に正しく取れない点に注意です。
Incremental Compilerを導入すると、C#7.2が使えるようになり要素のrefが使えるようになります。ソレに合わせてArrayElementAsRefというAPIが追加されるので、コレを使って要素をrefで取得してメソッドに受け渡す的な事も出来るようになります。
UnsafeUtilityExって、もう少し良い名前は無かったのか感あるので、今後変わる気もします。
Incremental Compilerの効果についてのまとめです。
要するにC# 7.2がつかえるようになる他、コンパイル時間短縮も期待出来ます。
但し、現在は記事で紹介されているような、manifest.jsonを書き換えなくともpackagemanagerから導入出来ます。
Unsafeの設定方法について
今回はTimelineの機能を使用するが、「目標地点が異なる」場合を対処する方法についてです。
例えば「距離の異なる崖をジャンプで超える」や「位置が毎回異なる敵に攻撃を仕掛ける」といった物をTimelineで制御する場合の話です。
移動で考えつくのはアニメーションによる移動ですが、これは基本的に固定の距離を移動する物になります。AnimationControllerを動かすキャラクターにセットする事でTimelineで指定された位置ではなく「現在座標からの移動」に設定することが可能ですが、距離が異なる場合にはアニメーションでの実現は難しいです。
それこそAnimationClipを動的に作るとかしない限り。
想定した座標以外でも移動するため、「指定した座標から指定した座標へ移動」する法式を使用します。
とは言え初期機能ではこの機能は含まれていないので、Default Playablesに含まれるTransofrm Tween Trackを使用します。
上手く使うと、下のように長さの異なる崖を同じTimelineで飛び越える事が出来るようになります。
アニメーションは「ジャンプ前」「ジャンプ開始」「ジャンプ中」「着地開始」「着地」「立ち上がる」の5つの動きで構成されていますが、ちゃんとTimelineで調整したので、違和感なく移動が出来ています。
実際にTransform Tween Trackを使用してみます。
まずはキャラクターの移動パスを作成します。単純なもので、スタート地点と終了地点にGameObjectを配置するだけです。
オブジェクトにはアイコンを付けておくと色々と楽です。選択とか
なお、オブジェクトの向きも影響します。移動方向に向きを変えたい時とかはオブジェクトの向きを気をつけたほうが良いです。
次にDefault Playablesを導入します。
https://assetstore.unity.com/packages/essentials/default-playables-95266
あとはTimeline側の設定です。
トラックを右クリックすると追加出来るメニューにTransform Tween Trackが増えてるので、コレを追加します。
Trackには動かす対象のTransformをセットします。今回の場合はユニティちゃんのルートTransform。
次にクリップ側でAdd Transform Tween Clipを足して、移動タイミングを指定します。最初のタイミングではスタート地点からスタート地点へ、次はスタート地点からゴールまで、最後はゴールからゴールまで。
同じ位置への移動はゲームを再生するとそれ程必要無いかもしれませんが、プレビューだとコレが無いと上手く動きません。
これで、崖から崖へのジャンプが実現出来ます。
ここで一つ悩ましい問題が、TimelineでキャラクターのTween開始地点と実際のキャラクターの位置がズレている場合です。何もしないとTimeline開始時にワープしてしまいます。
これを解決するには、Ease In Durationをセットします。
これで開始点とTimelineの座標とのブレンドが行われて、いきなりワープする事は無くなります。
カーブを表現したい場合、二つの移動をブレンドします。
例えば下のように二つの移動を持つ場合、この二つをブレンドするとカーブになります。
パスエディターが欲しい? ・・・それな
プレビュー外して、もう一回入れる。
特にTransform Tween TrackはGraph生成時に座標の取得を行っているので、コレがモロに来ます。
Transform Tween TrackはExpose Propertyで実現しているので、登録が面倒です。なのでstartとendをTimelineの子プレハブ的な感じで生成しておいて、startとendを動かすのが良いです。
もしくはScriptableObjectに格納したVector3に準じて動く感じに改造するとか。
移動系トラブル
tsubakit1.hateblo.jp普通にキャラを動かす場合
今回はunityでunsafeなコードを使う方法についてです。
以前はUnityは公式的にはUnsafeはサポートしていませんでしたが(unsafeを使う手順は存在して、IL2CPPもunsafe向けコードを出力していた)、Unity 2018.1辺り?からオプションとしてunsafeに対応したみたいです。
まず検証用に適当なunsafeを使用したコードを用意してみました。
構造体の配列を持っているコードで、各要素に対して直接内容の書き換えを行っています。
元々のコードはこちら。
実行結果を確認すると、ちゃんとyの中身をxに再設定出来ています。
また3つ目の要素に12を直接代入出来ている事も確認出来ます。
なおコードにはIl2CppSetOptionを使用しています。これはIL2CPPでC# からC++に変換する際のオプションで、unsafeでも効果があります。
特に[Il2CppSetOption(Option.NullChecks, false)]はポインタのアクセス時のコストを回避出来ます。ArrayBoundsChecksはポインタ上では要らんですが、まぁ。
Il2CppSetOption.NullChecksやArrayBoundsChecksはNativeArray使う分には要らんかな?どうだろう(未検証
Unsafeなコードを利用したい場合、PlayerSettings > Other SettingsのAllow 'unsafe' Codeを有効にします。
少し注意すべきなのが、Assembly Definition FileにもAllow Unsafe Codeのオプションがあります。これはAssembly Definition File毎にunsafeを許容するかの設定になっています。
少しややこしいですが、PlayerSettingsのallow unsafe codeはプロジェクト全体の設定(ADFが設定されていないコード全て)ですが、Assembly Definition Fileで更に個別に設定できるという感じみたいです。
もしIl2CppSetOptionが必要な場合(速度が欲しくてunsafeを使用してる)場合には、Il2CppSetOptionAttribute.csも必要です。
Il2CppSetOptionAttributeは{インストールしたフォルダ}/Editor/Data/il2cpp以下にあるのでプロジェクトに突っ込んでおきます。
もしAssembly Definition Fileを使用してる場合は、依存関係の構築も忘れずに。
お馴染みJacksonDunstan.comのIL2CPPでunsafeを使用した時にどのようなコードが生成されるのかの解説記事
C# 7.2の機能を使用したい場合はincrementalcompilerを導入します。
unsafeはコチラが分かりやすいです
さり気なくunsafeとか使ってたりします。