【Unity】アセットストアで地雷を踏まないための5つのTips
2017/7/10追記
アセットストアがアップデートされ、見た目が大幅に変わりました
一部のTipsがあまり意味をなしていない場合があります
あんまり変わってなかった
アセットストア
モデル、サウンド、エディタ拡張、完成プロジェクトまで様々なアセットを販売、購入できるプラットフォーム
高品質なアセット(普通に発注すればうん百万は下らなさそうなもの)も100$前後で買えたりします
Unityを使う一つの理由と言っても過言ではないんですが・・・
地雷が多いんじゃ
審査さえ通れば誰でも販売できる・・・そのため
- 品質がまちまち
- まともに動かすためには特定の手順が必要
- 他のアセットと競合
- importするとエラー
- etc
などなどの問題が多発します
C#やUnityスクリプトなどに深い知識がない人は、エラーを解決できずに泣く泣くアセットを使わない選択をすることもあると思います
なので、アセットストアで購入する際に地雷(が比較的多い)を選別するTipsを書こうと思います
ちなみに書いてる本人はアセットを15万円分くらい買ってます^p^
Tips.1 - 作成バージョンを見る
例でPlaymakerを見てみます
このトップ画面の下部にある
ここに注目します
「パッケージはUnity....で作られました」という表示があります
ここの部分の対応バージョンが自分の使用しているバージョンをサポートしているかを見てみましょう
この画像では最高で5.4.0となっています
つまるところ、現在最新版のUnity5.6.1で正常動作する保障はされておりません
表記がそうなっているだけで、5.6での動作を確認している場合もあるようです
さすがに、Unity5で使用したいのにUnity4で作成されたアセットなどの場合は気をつけましょう
Tips.2 - アップデートの頻度を見る
アセットは、アセットの開発元がユーザーからのバグ報告対応や、Unityのアップデートに合わせてバージョンアップする場合があります
このアップデートの頻度が高いほど、信頼度が高いです
バージョンの数字をクリックするとリリースノートを見ることができます
また、サポートウェブサイトとパブリッシャーサイトもチェックしてみましょう
詳細なアップデート履歴が観れる場合があります
ここが404NotFoundになっている場合、アップデートはほぼ絶望的と思ってもらって構わないと思います
Tips.3 - ディレクトリ構成を見る
アセットに含まれるファイルやフォルダ構成をパッケージ内容という部分で見ることができます
ここの判断基準は幾つかあります
-
StandardAssetsが含まれているかどうか
まず、StandardAssetsが含まれている場合が一番危険です
Unity4やUnity5のStandardAssetsが含まれている場合がある上に、ディレクトリが違う場合重複してインポートされます
そのため、DemoSceneなどで使用しているという理由でStandardAssetsが含まれている場合は注意しましょう
もちろんimport時にチェックボックスを外し、importしなければ問題はないです
-
パッケージのルートディレクトリが一つになっているかどうか
ルートディレクトリが一つになっていない場合(最近はアセットストアのルールで絶対になっているらしい?)
自分で作ったディレクトリと重複する可能性があるため、非常に困ります
これもおかしな話です、かなり少数ですがPluginsディレクトリに入っているアセットが幾つかあります
追記
Pluginsに入れる理由としてはAssemblyがfirstpassに移るからっていうのがありますね
— ケットシーウェア (@caitsithware) 2017年6月15日
C#で作っていてもjsからアクセスできるようになったり、ユーザーが無名空間に作ったクラス名と競合してもAssemblyが分かれるので衝突しないとか、いろいろ利点があります https://t.co/3Hv6n6plUX
Arbor2(https://www.assetstore.unity3d.com/jp/#!/content/47081)の作者様よりご指摘がありましたので引用させていただきます
Pluginsに入っていることはアセット提供側からするとメリットがあるため、逆によく考えられていることの方が多いかもしれませんね
なので、それ以外の場合(モデルデータや明らかにおかしいもの)は少し考えた方が良さそうです
- ソースコードの名前
ソースコードの名前がCameraControllerやGameControllerなど、重複する可能性の高い名前の場合注意が必要です
スクリプトを消すことでアセット自体が動作しなくなることもあり、コードを修正する必要が出てきます
-
ファイルの名前に全角文字やスペース、特殊文字が含まれているかどうか
これは基本的には問題にならないのですが、Gitなどを使用したバージョン管理をする場合非常に問題になります
一度繁体字が紛れていたことがあり修正に時間を取られました
気をつけましょう
Tips.4 - レビューではなくサポートフォーラムを見る
ページ下部にあるレビュー欄
仮でピックアップしてみましたが、全く当てになりません
現在のバージョンではないレビューの場合があるためです
また、1年前や2年前の投稿が出てくることはザラです、信用しないようにしましょう
現在進行形でアセットの評価をみたい場合はこちらを利用すると良いです
https://forum.unity3d.com/forums/assets-and-asset-store.32/
Unityの公式フォーラム内にある、AssetStore関連のスレッド群です
利用したいアセット名で検索することで、ユーザーの感想、問題点の共有やデベロッパーとのやりとりを見れる場合があります
私もデベロッパーに(本当にたまに)意見を言っています、だいたい拾ってくれますし丁寧に答えてくれることが多いです
英語ですが
Tips.5 - 使った人のレビューブログを見たり、可能なら直接聞く
当たり前の話ですが、一番確実です。
特にUnityはコミュニティが強いので、日本人もたくさんいます、聞きましょう
最後に
「超個人的」な印象ですがSimpleとかEasyとかついてるアセットをあまり信用してないです
判断基準の一つになれば幸いです、良いUnityライフを
アセットもバリバリ使ってる現在開発中のゲームの公式サイトはこれ(宣伝)
https://www.studiophantomisland.com/
よろしくお願いしますーす
BitBucketのプラン改定でLFS容量が10GBから1GBになった話
BitBucketのプラン改定
Pricing Updateというまあありていにいえば価格改定が行われ
その結果無料プラン、有料プランにLFSの容量が組み込まれた
改定前
リポジトリ容量2GB limit
LFS容量10GB limit
改定後
リポジトリ容量2GB limit
LFS容量1GB limit
(!!!!?????)
LFSの容量は有料プランの段階に応じて5GB -> 10GBと増え
それ以上はストレージ容量を月額で買う感じのようだ
値段は10$ / monthで100GB使える
結局
むしろよく10GBも使わせてくれてたよなと思いつつも、急に変えられて困った
支払い関係でpaypalが使えず(外部連携すれば使える)
JCBのカードしか持っていない弱小の僕はgithubの有料プランへ移行した
privateリポジトリを作るためにgithubの有料アカウントを取得
毎月5$払ってLFS容量を50GB買っている
だいたい月に12$弱持ってかれてる計算だ
Githubに移行してから
とりあえずリポジトリで使用しているLFS容量が9GBほどあったので、cloneに多大な時間がかかる
また、使用できるリポジトリの通信帯域制限50GBがあるのでcloneコケすると軽く数GBの帯域を持って行かれた
通信帯域制限はBitBucketにはなかったと思うので、Github有料にする前によく考えればよかったなーと思う
Nowでこんな感じ
兎にも角にも、サービスを使っているとこういうコストが生まれるので
やっぱり自前でサーバー立ててgitlabとか使った方が最終的には安く済みそうだなと思った。
終わり
【Unity】ZenjectのAsSingle(),AsCached(),AsTransient()の違い
Zenject使うじゃん
— ペンギン (@YutaDevelop) 2017年4月21日
AsSingleでBindするじゃん
UnBindするじゃん
もう一回Bindするじゃん
Injectされない!!!!!!
AsTransient使えば解決なんだけど、GC走って回収されてるのにキャッシュ残ってるってどういうことなんなんなん
調べてみた。
超適当にテストコード書いて挙動を確かめた
メソッドの名前が意味不明なのは許してほしい
挙動を理解しないとヤバい事故生みそうだなこれという結果になった
結果的にはAsSingle()でInjectされてる参照がUnbindで破棄されてなくて、Inject済みの参照をもう一回Bindし直してた
あとGCで回収されてなかった
そもそも
As〜ってなんぞやというと
BindするクラスやインスタンスのBind方法の定義である
https://github.com/modesttree/Zenject#binding
AsSingle(),AsCached()はキャッシュするのね〜
AsTransientはキャッシュ作らないのね〜くらいの認識だと
しぬ(しんだ)
AsTransient()
クラスをBindする際に複数インスタンスの生成を許容する
クラスがContainerにBindされている際、参照情報が一つであればResolveで解決出来る
しかし、Resolveは単一のインスタンスに対してのみ参照を解決するため
AsTransientでBindを複数回行っていた場合、multiple instanceエラーを吐く
AsTransientでのBindには必ず.WithId()を使用してIdentiferを定義するか
ResolveAllを使用した参照解決を図るようにした方が良い
また、As〜などの定義をしなかった場合はデフォルトでAsTransientになる
Factoryなどを使用したインスタンス生成もAsTransientになるため、Instantiateで複数生成したクラスに対してResolveするとエラー吐く、気をつけよう
(まあInstantiateした時点でResolveすることなんてほとんどないんだけど)
AsCached()
Bindされているクラスがすでにインスタンス化されている場合、同じインスタンスを使い回すようにする
また、UnbindするとCacheされていたインスタンスは全て参照を破棄される
同じインスタンスは使いまわしたいが、Unbindで破棄したい時はこれを使用する
クセがなく、取り回しがしやすいので動的Bindをする際は非常におすすめしたい
AsSingle()
クラスをBindする際にSingletonとして定義する
クラスがContainerにBindされている際は
「そのContainer内で唯一存在するクラス」となることが保障される
Bindされている際は、Cachedと同じ挙動をする
しかし、Unbindを呼んだ際に
Bindした自身の参照を他のクラスにInjectしなくなるが、生成したインスタンス自体は破棄されずキャッシュされたまま
のため、Unbindを呼び、その後もう一度同じクラスをBindしても
new()などが走らず、キャッシュされていた参照をもう一度Bindして使い回す
(HashCodeでやっているが、他にもResolveで返ってきた値の中身を書き換えたところどちらも書き換わった)
AsSingle()は必ず一つ、かつ一度しか生成されないオブジェクトに対してのみ使用しよう
まとめ
readmeには、「AsSingle()をほとんどの場面で使いたいと思うでしょうが〜」とか書いてあるけど
基本AsCached()でいいわ。
AsSingle()で動的Bindすると初期化走らせられなくてビビった結果、動作を知れたのでまあよかったと思う。
【Unity】Zenjectで禅の心を手に入れる
Zenjectについて
導入を躊躇っていたものの、あるところから脅しがかかったので本格的に使い始めた
基本的な使い方などはこちらをご参考いただければわかるのではないかと思います
Unity3DのDIフレームワーク、Zenjectの紹介 | Aiming 開発者ブログ
今回はちょっと具体的な使い方を模索してみました。
何ができるのか
リポジトリのreadmeを読めばわかる
DI(Dependancy Injection)を行うためのライブラリで、すっごい簡単に言うと
newの引数とか、シングルトンで引っ張ってきてたオブジェクトを、登録しておいたオブジェクトの中から勝手に引っ張ってきて自動で参照を入れてくれるやつ
って認識でいいと思う、もちろんこれは機能のごく一部に過ぎない
他にもいろいろできる、公式読んで
中身の話
Zenjectの基本は
- Containerにオブジェクトを登録
- Containerに登録したオブジェクトをインスタンス化(この時に引数などの参照が自動で持ってこられる)
- オブジェクトが作られたらごにょごにょする
になる
Containerは、登録されたオブジェクトが入ってるDictionaryみたいなもので
ここの中にオブジェクトが登録されていないと、参照を解決できない
また、自動で参照してくれるようにするためには、参照先のオブジェクトも登録してあげないといけない
つまり、こう
これは全てにおいて適用されるので、まずBindを忘れないようにしよう。
使い方
まだ全てを把握できているわけではないので、状況別で
SingletonにしていたManagerを、Singletonにしない
(MonoBehaviour継承クラスに、参照を渡す方法)
Zenjectには、ZenjectBindingというコンポーネントが存在する
こいつは、登録したコンポーネントを勝手にContainerに登録してくれるすごいやつ
実際に使ってみるとこうなる
Managerの中身は、普通のMonoBehaviour継承クラスになっている
使用する場合は、こう書く
MonoBehaviour継承クラスの場合は、Injectアトリビュートを使用することで自動で参照が設定される
非継承の場合は、newで渡してあげる
これで、Managerは自動で使いたいところで使えるようになるので、ただのstatic参照のためだけにSingletonである必要がなくなる
もちろん、同一インスタンスが一つしかないことを保証するために使うのはあり
同一クラスは一つのみ生成し、あとはキャッシュを使う.AsSingle()というBind方法が存在する
同じことをしてる人がいたので、こちらも
余談ですが、torisoupさんはいつも勉強になる記事をあげてくださっているので定期購読をお勧めします
また、Manager以外にもZenjectBindingに登録さえすればなんでも使えます
Playerとかカメラとかを登録すると捗るかもね
Pureクラスを好きなタイミングでBindしながら生成する
MonoBehaviourの参照を渡したりするPureクラスとか・・・
クラスがごちゃごちゃしがちな原因の一つだが、Zenjectを使用することで解決出来る
まずMonoBehaviour継承クラスで渡したいクラスをBindする
- シーンに最初から直置きしてあればZenjectBindingを使用する
- 動的に生成される場合は、Container.Bindを使用してContainerに登録する
動的生成する際に勘違いされがちだが
別にInstallerを使って記述しなくてもいい
DIContainerへのBindさえできればよく、さらに
DIContainerはBindされているので好きなクラスにInjectで引っ張ってこれる
好きなタイミングでBindすればいいと思う
試しに、ボタンを押したらHogeをBindして生成するにはこうする
GameManagerはBindInstallerか何かでBindしてあげる必要があるが
BindさえすればDIContainerを引っ張ってこれるのでこういう書き方ができる
Container.Resolve<Hoge>()はBindされているオブジェクトをインスタンス化してreturnするメソッド
他にも.TryResolve<T>()などのメソッドが用意されているので、動的バインドする基底クラスかヘルパーを作ることをお勧めする
Resolveについては公式を
https://github.com/modesttree/Zenject#dicontainer-methods-resolve
ちなみに、BindされたPureクラスは明示的にUnBindしない限り参照を握られ続けるため破棄されない
Disposeメソッドなどを使い、破棄するタイミングでContainer.UnBind<Hoge>()を呼んであげよう
(これって非推奨だったりするのかな、知っている人がいたら教えてください)
その他
.FromNew
.FromMethodsとかは紹介したかったのですが、長くなりそうなのでまとめたときにでも
DIContainer.Inject
DiContainer.Instantiate
は今試してます。追記予定。
処理速度とかの測定はしてないんだけど、Bindは結構重いらしい
まあそうだろうねって感じだけど、これも測らないといけないね
終わり
禅の心強いわー
【Unity】StateMachineBehaviourについてと注意まとめ
StateMachineBehaviourとは
過去記事
AnimatorのStateにAddComponentできるスクリプト
(MonoBehaviourみたいな感じ)
クラスに継承させることで使用できる
役に立たない公式リファレンスはこれ
https://docs.unity3d.com/jp/540/ScriptReference/StateMachineBehaviour.html
動作
基本的には用意されたコールバックをoverrideすることで使用する
- OnStateEnter
- ステートマシンがこのステートを評価している場合、最初の Update のフレームで呼び出されます。
MonoBehaviourで言うところのStart()
- OnStateUpdate
- 最初と最後のフレームを除いて Update フレームごとに呼び出されます。
MonoBehaviourで言うところのUpdate()
- OnStateExit
- ステートマシンがこのステートを評価している場合、最後の Update のフレームで呼び出されます。
MonoBehaviourで言うところのOnDestroy()
Update()が完全に流れなくなるフレームで呼ばれる
----------この辺からよく知らずに使うと闇---------------------------------
- OnStateIK
- MonoBehaviour.OnAnimatorIK の直後に呼び出されます。
IKを使用した処理を行う
overrideすると、IKの処理を自前で実装することになり(Animator.SetIK〜を使う)
Stateに対してIKが自動で適用されなくなる
base.OnStateIKを呼んでもダメ
基本overrideする必要なし
- OnStateMove
- MonoBehaviour.OnAnimatorMove の直後に呼び出されます。
Animationに設定されたRootAnimationの処理を行う
Animation内のPosition、Rotation、Scaleに関わる処理が行われるため
overrideすると、Stateに対してRootAnimationが適用されなくなる
base.OnStateMoveを呼んでもダメ
基本overrideする必要なし
AnimationCrossFade時のStateの取り扱いについて
CrossFadeのリファレンス
AnimationがCrossFadeしている時(durationが0以上の時)
CrossFadeが終了するまで、CurrentStateはCrossFade元のまま
さらに、normalizedTimeもそのまま加算され続ける
normalizedTimeを使用した処理をする時は、CrossFadeを使用しないようにするか
自前でnormalizedTimeを使用しよう
最後に
用法用量を守って使う
基底クラスを作ろうとしてOnStateMoveとOnStateIKをoverrideすると痛い目にあう(あった)
【Unity】OnStateMoveをoverrideするとRootMotionが適用されずに詰む
StateMachineBehaviourについてのまとめを読んでください
概要
Unity.ver 5.4.4
UnityにはStateMachineBehaviourというものがある。
Unity - スクリプトリファレンス: StateMachineBehaviour
AnimatorのStateに紐づけられるスクリプトで、そこそこ便利
その中にOnStateMoveというoverrideできるメソッドがある
日本語のリファレンスはこんな感じ
何も書いてないに等しい
それで今回は表題の通り地雷を踏んだ
RootMotion
RootMotionはAnimationに適用されているポジションや回転をオブジェクトに作用させてくれる機能で、それがなぜか効かなくなって半ギレしていた
(Apply Root Motionはチェックを入れていて、そのほかもろもろもすべてokだった)
StateMachineBehaviour用の基底クラスを作成して、処理を共通化した時に効かなくなったので何かあるなと思い調査
結果、StateMachineBehaviourのOnSTateMoveがRootMotionのPosition更新制御を行っていて、それを直接overrideして書き換えている様子
なので、overrideしているとそのStateにセットされているアニメーションは適用されなくなるらしい
base.OnStateMove()を呼んでみたものの、適用されなかったので
OnStateMove()は自前で移動処理を書かないなら
絶対にoverrideしてはいけない
でFA、OnStateUpdateで間に合わせよう
この辺の仕様はマジでリファレンスに書いとけよUnity
UnityのコーディングにVisual Studio for Macを導入して一週間が過ぎた
誰か俺にVSforMacを入れる勇気を
— ザツヨウペンギン (@YutaDevelop) 2017年2月23日
入れました、導入した後にやった設定と感想をつらつらと書きます
とりあえずPreview版とはいえ、まあなかなかでした
導入・インストール
New Release Preview: Visual Studio for Mac | Visual Studio
ここからインストールしてください
導入・Unity側の設定
Preferences を開いて
External Tools からExternal Script Editor でインストールした Visual Studio for Macを指定してあげる。
これでスクリプトファイルを開くと動くぞ!
とはいかない、このままだとインテリセンス(補完)が効かない
導入・VSforMac側の設定
※機密プロジェクトがあるので名前がバレないように「あ」を入力してます
Open から、Unityのプロジェクトディレクトリの中にある.sinファイルを選択して、ソリューションを開こう
.sinファイルがない時は、Unityでスクリプトを選択して開けば多分自動生成されるはず
これでインテリセンスが効くようになる
ただこのままだと死ぬほど使いづらいので色々カスタムする
カスタマイズ・エディタカラー
まずはエディタのカラーを変える、白背景とか、謎の文字色とかゴメンだし
Visual Studio から ユーザー設定を開く
余談だけど日本語のメニューなのいいよね。
インターフェースを エンジニア大好き Dark にした
テキストエディターからColor Themeを選択、選択すればエディタが変更されるので好きな色を選ぼう
現状Theme編集機能はないらしい
自分でカスタマイズしたテーマがあるときは、MonoDevelopなどからエクスポートして持ってこよう
自分はOblivion派なので、今回は割愛
カスタマイズ・ポリシー
ソリューションごと、あるいはグローバルでコードフォーマットなどを定義できる
ここから新しくポリシーを作る
基本的にはコードの書式設定から、C#の設定項目を変更していく
自分の好きなようにやろう
ソリューションごとにポリシーを適用できるので、プロジェクトを複数抱えてても安心
ポリシーにAttribute改行の設定項目がない件について
VSforMac
— ザツヨウペンギン (@YutaDevelop) 2017年2月23日
アトリビュートの自動改行マジで何とかしろよ…_:(´ཀ`」 ∠):
こいつさえなければ…
あとアトリビュートの中身にインテリセンス効かない
— ザツヨウペンギン (@YutaDevelop) 2017年2月23日
KUSO
Unity使ってると頻繁に出てくるSerializeField変数を一行で宣言したい時、アトリビュートで勝手に改行されるのでその度にCmd+Zを押すことになる
その上アトリビュートで囲むと補完されないので一回一回手打ちになる
カスタマイズ・コードテンプレート
とりあえず上記の問題を解決するためによく使うアトリビュートをテンプレート化した
追加する時はユーザー設定からCode Snippetsを選択して、追加をする
また、$class$などの記述を行うことでフリー入力を作ることもできるので活用する
今回、アトリビュートでよく使うSerializeFieldを登録した
ただ、テンプレートに
[SerializeField] $class$ $field$
みたいな感じで記述すると勝手に改行されたのでやらないことにした
わけわからんので製品版で早く設定追加してほしい
ただ海外フォーラム見てると超昔から言われてるのに開発者がResharperを使ってるからいつまでも追加されないとかなんとか
カスタマイズ・パフォーマンス
とりあえずで上記の設定を終え、使ってみると
インテリセンス遅すぎワロタ状態
だった
とにかくクッソ重い、ちなみに使用してるmacは2015年モデルのフルカスタマイズなのでスペックが低いわけじゃないと思う
なので、パフォーマンス改善をする
まずは何はともあれテキストエディタからアニメーションを無効に
強調表示とかも消す
他にも視覚効果をOFFっていく
効果があるかはわからないものの、コードの動的コンパイルが走るので解析も毎回走るんじゃないかと思い解析も切った
だいぶ早くなった
カスタマイズ・キーバインド
人それぞれすぎるので割愛、設定しとくと楽やで(提案)
最後
頻繁に落ちる上に操作不能になるMonoDevelopよりは使いやすい
VisualStudioCode、Atom、VimとかのエディタよりIDE派なので今後に期待したい・・・特にアトリビュートとパフォーマンス
メモリ2GB食われるのでメモリの残量には気をつけよう
もうしばらく使ってみる