箱庭ハーブblog

7年目プログラマの趣味の小部屋

List<T>、配列、IEnumerableとキャスト

Array、IEnumerable<T>、Linq

ども。

C#では、配列とList<T>ではキャストの挙動が違います。
object[] a = new Type[0]; // OK
List<object> b = new List<Type>(); // NG

List<T>の要素型をアップキャストできないんですね。
ちなみに、IEnumerable<T>は明示的なキャストで可能ですが、
実体が配列だった時だけ成功して、List<T>だった場合は例外が発生します。

で、どうしてもキャストしたい場合は、シャロウコピーなりなんなりするわけですが、
System.LinqのCast<T>()でシャロウコピーできます。
List<object> b = (new List<Type>()).Cast<object>(); // OK
このCast<T>()、配列ならキャスト、それ以外ならシャロウコピーします。

VisualStudio2017をインストールしよう!

VISUALSTUDIO2017、Visualstudio2017、visualstudio2017


ダウンロード!

ども

Visual Studio 2017が正式リリースされたので、さっそくインストールしたい!
というわけで、サクッとダウンロードして、入れます。



全チェックすると、50GBになります…!?

2015よりさらに多くなったなオイ!
通常のBlu-rayに収まりきらんぞ!?

Unityなんかもインストーラの選択肢に入って、
だいぶサードパーティに優しくなりましたね。
(正直、光とSSD両方の環境がそろってないと、
インストールだけで2時間とかかかるんじゃなかろうか…)

2015の時は調子に乗って全部入れたけど、
今回は必要そうなものだけ入れる方針で19GB。

それでも19GBか…



自分は15分ぐらいでインストールが終わりました。再起動



再起動後にVisualStudio2017を起動すれば、初回画面に。


あとはMS開発アカウントでサインインすれば・・・



VisualStudioの初期画面!(まだ初期設定中!)


 
初期設定が終わると、ダークがデフォルトになります。


とりあえず、ここまででVSのインストールは完了。
Unityエディタからの紐づけも、2017に変えておきましょう。



テラシュールさんのところにやり方が載ってます。
【Unity】Visual Studio 2017 (RC)をUnityで使う



Browseした先は、こんな感じ。



設定が成功すると、Visual Studio2017になります。


Unityエディタから開くかどうか確認!
適当にスクリプトをダブルクリックして…



セキュリティが聞かれるので許可



開きました!なんか2015の時よりデフォルト設定がすっきりしてる!

今回はRC版などには手を付けられてなかったですが、
次のVisualstudioはβリリースから触りたいところ!

IEnumeratorとコルーチン、C#の使い方

ienumerator



コルーチン。C#ではイテレータ構文。
便利ですね。

便利というか、何か挙動やロジックに影響しないエフェクト書きたかったら、
コルーチンで書きたくなるのが人の思考ってもんよ。

yield return nullやWaitForSecondsなら、
全てのUpdate()の後に実行される事だけ意識すればOK。
使うだけなら何も難しくない。

Unityのライブラリは構造が洗練されているので、自分で制御するより楽。
停止と再開も自前で実装する必要がないし、とても使いやすい。

そんなですが、コルーチンを支えてるC#の文法の歴史を覚書してみます。

要約するとこんな言語機能です。

【1. .NET1.0とforeachとイテレータ】

.NET1.0時代、foreachを実現するための仕組みとして登場
仕組みはデザパタのイテレータそのままです。
 ・コレクションに、IEnumerableを実装し。イテレータを取得できるようにする
 ・イテレータそのものを表すのが、IEnumerator
 ・実際は「IEnumerableなしでも、GetEnumerator()が宣言されていればOK」(特殊文法)

【2. .NET2.0とイテレータ構文(イテレータブロック)】

.NET2.0時代に、yield return(中断)、yield break(終了)を使う構文が追加されました。
IEnumerableかIEnumeratorを返すメソッド=イテレータブロックにて使用可能です。
匿名メソッドと同じく無名○○系に見られる実装の簡略化が目的で、
イテレータを明示的にクラスとして定義する必要がなくなりました。
Unityで使用される書き方も、この仕組みを転用したものになります。

【3. Unityのコーチン】

・StartCoroutine(IEnumerator)でUnityのイベント発生に基づいてコルーチンできる。
・StopCoroutine(IEnumerator)で、該当のコルーチンを停止できる。再開もできる。
・yield returnする時、以下を返すと、nullと異なる再開タイミングになる
  ・WaitForSeconds(X) 指定した時間が経過するまで待機
  ・WaitForFixedUpdate() 次の物理演算終了後まで待機
  ・StartCoroutine(IEnumerator) 渡したコルーチンが終了するまで待機
・コルーチンの終了部にyield return hogeで、Currentから戻り値を得られる
・GameObjectが非アクティブになると動作を停止する
・コンポーネントがdisableになっても、動作は継続する

yield return で戻り値を返すことで、
イテレータ.Currentで戻り値を取得するという使い方が、なんともギーグな感じ。

ScriptableObjectとInstantiateとシリアライゼーションの使い方

scriptableobject、instantiate



2017-03-03
シリアライズルールに関して、追記しました。

ども、お疲れ様です。
知ってる人は知っている、ScriptableObjectのInstantiateのお話。

全体を俯瞰するには、下記の公式サイトをひとまず読むと良いでしょう。

スクリプトシリアライゼーション
https://docs.unity3d.com/ja/current/Manual/script-Serialization.html


ブログ内の記事では、こちらでも扱っています。

完全攻略、Unityシリアライゼーション
http://hakoniwaherb.blog.shinobi.jp/Entry/534/

ScriptableObject、便利ですね。
継承とポリモーフィズムが使えて、Prefabのようにpublicフィールドにリンク出来て、
エディタ上で編集できる。

最高です。

Serializable付加クラスと適切に使い分けることで、
大半の機能をエディタだけで処理することが可能になります。

で、今回はScriptableObjectとInstantiate。

1、Instantiateは何をしているのか

Prefabでおなじみ、Instantiateさん。複製してくれます。
Prefab(ひな型)を作ってリンクしておき、それをInstantiateするだけ。
なんとなくならすぐわかる。

しかし
  • どうしてPrefabの型はGameObjectなのか
  • どうしてInstantiateを調べるとシリアライズの話が出てくるのか
  • ScriptableObjectをInstantiateするとは、そもそもどういうことなのか

これ、仕組みを知ればすべて解決します。

単純。

Instantiateは、
シリアライズ可能なオブジェクトをシリアライズしてデシリアライズしているだけです。

うん、用語がわからない人は良くわからんですね。

シリアライズは、テキスト化です。
現在のメモリ上にあるオブジェクト(インスタンス)を、テキストに写し取ることです。

デシリアライズは、Deシリアライズです。
テキストから、オブジェクト(インスタンス)を作ることです。

「シリアライズ対象」「シリアライズされる」という単語は、
値が復元するかどうか、つまりコピーされるかどうかを表します。

このシリアライズのルールは、デフォルトでは次のようなルールになっています

大前提
1. シリアライズ可能な型は、以下の通り
 ・UnityEngine.Object継承クラス
 ・intなど基本型
 ・Serializable付加クラス
 ・Vector3、Quaternionなど、Unityシリアライザで特別に処理される構造体(※)
2. 1の配列、List<T>型もシリアライズ可能。Dictionary<TKey, TValue>は無理

(※)
これらのUnity内の構造体は、Serializableではないため、
Unityと関係ない.NETのシリアライザやサードパーティのシリアライザを用意すると、
シリアライズされない

詳細
1. privateメンバや自動プロパティの暗黙のフィールドも、ScriptableObjectなら対象である
1. privateメンバ、自動プロパティはシリアライズされない。
2. staticメンバはシリアライズされない
3. read onlyメンバはシリアライズされない
4. [NonSerialized]付加メンバは、シリアライズされない
5. UnityEngine.Object継承クラスであるメンバは、参照も復元する
6. UnityENgine.Object継承クラスでないメンバは、参照が復元しない!(事実上のクローン)

2017/03/13 追記
privateメンバや自動プロパティは、シリアライズ対象ではありませんでした。
Instantiateせずに使用した場合、値が保持されるように見えますが、
エディタを起動しなおしたり、実機実行でアプリを終了して再起動すると、
値が初期化されています。
基本的にシリアライズはMonoBehaviourと同じ挙動をする、という認識でOKです。

5と6に関しては、6が変に見えるかもしれませんが、
シリアライズの仕組みを考えると、むしろ5がすごいことをしていると言えるでしょう。
ポインタやシリアライズIDを元に参照を復元しているのですから、恐ろしい。

大前提に関して補足すると、
シリアライズ対象でない型、つまりSerializable付加でない非基本型は、
シリアライズされませんし、復元もされません。
Instantiate後のインスタンスはnull(structなら暗黙コンストラクタされた値)になります。

詳細の6に関して補足すると、
これはSerializable付加クラス型のメンバに対して起こる内容です。
Serializable付加クラス型はUnityEngine.Object継承型とは限らないため、
UnityID管理されず参照が復元されません。
しかしながら、Serializable付加クラスはシリアライズ対象ですから、値は復元されます。
結果として、Serializable付加クラス自体のインスタンスは別々になります。


2、ScriptableObjectとは何者か?

ScriptableObjectは、Prefabとよく似ています。
しかし、
Prefabと異なり、Instantiateする文化が言及されていないので、
いまいちよくわからない動作をするイメージがあると思います。

厄介なのは、Unityエディタ上とビルドしたアプリで挙動が異なることです。
Unityエディタでは、実行時の情報はアセットに反映・保存されますが、
ビルドした後は通常の手順では反映されません。

ここら辺は、下記のリンクの下の方にある説明が詳しいです。

テラシュールブログ ScriptableObjectについて
http://tsubakit1.hateblo.jp/entry/2014/07/24/030607

3、ScritableObjectとInstantiate

PrefabをInstantiateせずに使うと、どうなるでしょう。

弾のPrefabだったら、複製されないし、色々使い物になりません。
しかし、値置き場として使うなら、優秀です。

ScriptableObjectも同じです。

値置き場として使うなら、Instantiateせずに使えば優秀です。
当然、値を変更すると、
エディタ実行中ならばScriptableObjectのアセットの内容が変わっちゃいます。

========
→ ※注意
前述の通りエディタではなくアプリ実行中は、
最終的にアセットに保存反映されないため、アプリを再起動すると元に戻っています。
========

一方、Prefabと同じようにScriptableObjectをInstantiateすると、
クローンされます。

クローンされたScriptableObjectは当然元とは関係がなくなるので、
自由に挙動させることが出来るようになります。

前述の通り、ScriptableObjectが別のPrefabやScriptableObjectを
リンク(publicフィールド接続、アウトレット接続)していた場合、
その参照は復元されてしまうので、同じアセットを共有したくない場合は、
それらもInstantiateする必要があります。

まとめ

ScriptableObjectのInstantiateは、非常に強力な機能です。
ScriptableObjectをInstantiateせずに使う場合、
初期パラメータとしてしか使えません(セーブデータも無理)が、
Instantiateすれば、現在ステータスとセットで表現できるようになります。
(ステータスメンバはNonSerializedをつけることが重要です。)

目的に応じてInstantiateするかしないかを使い分けることで、
最適なパフォーマンスと構造が作れるでしょう。

Unityの回転のデフォルト

備忘録



公式サイトはここ
Unity の回転と向き
https://docs.unity3d.com/ja/current/Manual/QuaternionAndEulerRotationsInUnity.html


1. 初期配置(0,0,0)は、ワールド軸に一致。
2. Rotate(オイラー)回転の向きは、Z=X→Y、Y=Z→X、X=Y→Z
3. Rotate(オイラー)回転の順序は、Z、X、Y

一般的なやつですね

フリーエリア

takemori
Twitter : @takemori_kondo

1. Unityと戯れてます
2. Cake3は劣化じゃないRails

iOS
coming soon...

Windows
Html Editor - Nazuna
Managed DirectX サンプル集

beginning since
2006.08.17
renewaled on
2011.06.03

最新コメント

[2013/06/14 ミューネ]
[2012/08/30 ノートPC]