More Related Content Similar to 「宴」実装時に得られたUnityプログラムノウハウ
Similar to 「宴」実装時に得られたUnityプログラムノウハウ (20) More from Ryohei Tokimura
More from Ryohei Tokimura (6) 「宴」実装時に得られたUnityプログラムノウハウ2. 概要
• Unityにおけるプログラム一般( C# )
• これが重要!どうやって探して、どこに渡す?
• シリアライズ
• コルーチン
• エディタ拡張
• より具体的なプログラムについて
• 2D
• 画面サイズに対応
• プロジェクト設定
• ADVエンジン(シナリオ解析)
• エクセルの読み込み
• リソースのDLとメモリ管理
• セーブロード
41. シリアライズって?
• Wikiより引用
• コンピュータプログラミングにおいて、シリアライズ、もしくはシリアル
化 (serialize) という用語は、次のような異なる2つの意味を有する。
• ある一つの資源を、複数の主体が利用しようとするときに、それを調
整(同期)して、一つの時点では一つの主体だけがそれを利用する
ようにすること。この意味では逐次化という訳語が用いられる。対義
語は並列化である。
• ある環境に存在しているオブジェクトをバイト列やXMLフォーマットに
変換すること。この意味では直列化という訳語が用いられる。同義
語にMarshallingがある。対義語は直列化復元ないしデシリアライズ
である。
67. コルーチンからコルーチンを呼ぶ
void Load()
{
StartCoroutine( CoLoad ());
}
IEnumerator CoLoad()
{
yield return StartCoroutine(CoLoadSub1());
yield return StartCoroutine(CoLoadSub2());
}
IEnumerator CoLoadSub1()
{
yield return new WWW(url1);
}
IEnumerator CoLoadSub2()
{
yield return new WWW(url2);
}
コルーチン内部で
yield return StartCoroutine()
とする。
この例では →
CoLoadSub1()が終わってから、
CoLoadSub2()が始まる
68. コルーチンをMonovehavior以外で使う裏技
public class MainClass : MonoBehaviour
{
SubClass sub = new SubClass();
void Load1()
{
StartCoroutine(sub.CoLoad1());
}
void Load2()
{
StartCoroutine(sub.CoLoad2(this));
}
}
//コルーチンをもつ通常のクラス
public class SubClass
{
//コルーチン
public IEnumerator CoLoadSub1()
{
yield return new WWW(url1);
}
//コルーチン内部でStartCoroutineを使うには、MonoBehaviourを渡す
public IEnumerator CoLoadSub2(MonoBehaviour parent)
{
yield return parent.StartCoroutine(CoLoadSub1());
yield return new WWW(url2);
}
}
StartCoroutineはMonovehaviorからしか呼べ
ない。
IEnumerator で宣言するコルーチン自体
は通常のC#のクラスでもOK。
その内部でさらにStartCoroutineをした
いなら、Monobehaviorを渡してやるとい
う手もある。
71. OnValidateが便利
/// <summary>
/// インスペクターから値が変更された場合
/// </summary>
void OnValidate()
{
dataTbl.RefreshDictionary();
}
リファレンス http://docs-jp.unity3d.com/Documentation/ScriptReference/MonoBehaviour.OnValidate.html
インスペクターのエディタ拡張をせずに、
インスペクターで値が変えられたときの
操作を記述できる。
簡単な処理ならこれでOK
参考ソース Utage¥Scripts¥GameLib¥CustomProjectSetting¥Node2DSortData.cs
72. OnValidate +MarkAsChangedパターン
参考ソース Utage¥Scripts¥GameLib¥2D¥2D¥Node2D.cs
/// <summary>
/// インスペクターから値が変更された場合
/// </summary>
protected virtual void OnValidate()
{
MarkAsChanged();
}
/// <summary>
/// 毎フレームの最後の更新
/// </summary>
protected virtual void LateUpdate()
{
if ( CachedTransform.parent != lastParent || hasChanged )
{//構造に変化があった
Refresh();
}
}
インスペクターでの変更だけなく、
・スクリプト内部からのsetなどで変更されうる
・パラメーターが多く、かつ更新による負荷が大きい
など、ある程度複雑になる場合は
「変更があった」というフラグのみ設定して、
LateUpdateやUpdateでチェックして一度だけ変更す
るという手もある。
73. EditorGUILayout.PropertyFieldを使うと楽
参考ソース Utage¥Editor¥Scripts¥Inspector
UtageEditorToolKit.PropertyField(serializedObject, "engine", "Engine");
UtageEditorToolKit.PropertyField(serializedObject, "isAutomaticPlay", "Is Automatic Play");
UtageEditorToolKit.PropertyField(serializedObject, "startScenario", "Start Scenario Label");
public static void PropertyField(SerializedObject serializedObject, string propertyPath,
string label, params GUILayoutOption[] options)
{
SerializedProperty property = serializedObject.FindProperty(propertyPath);
if (property == null)
{
Debug.LogError(propertyPath + " is Not Found");
}
else
{
EditorGUILayout.PropertyField(property, new GUIContent(label), options);
}
}
メンバ変数名 インスペクターに表示する名前
EditorGUILayout.PropertyFieldを使
うと、stringやMonobehavior、
Vector3、enumなどの型によらず
適切なGUIで表示してくれる。
細かい制限をかけない(エディタ
拡張しないでよい)パラメーターに
関してはこれで書いたほうが楽
エディタ拡張をする場合でも、なるべく簡単に書く。
109. ファイルロードの課題
• Resouces.Loadは?
• ダウンロードできない
• アプリサイズが増える
• リソースの修正にはアプリ自体のアップデートが必要になる
• AssetBundleは?
• UnityProじゃないとAssetBundleの作成ができない
• Unityのアップデートによっては、過去のAssetBundleと互換性が取れない
• サウンドのStream再生ができない。(メモリ消費が大きい)
• WWWは?
• 毎回ダウンロードすることになる
参考ソース Utage¥Scripts¥GameLib¥File¥AssetFileWork.cs
113. • 目的は、LoadFromCacheOrDownload と殆ど同じ
• つまり、ファイルのバージョン管理つきのDLとローカルへの保存
• ただし、アセットバンドルではなく.pngや.wavなど汎用的なファイルを扱う
• メリット
• アセットバンドル化しないので、pngなどはサイズが小さいままDLできる
• Unityのバージョンアップに左右されない
• →アセットバンドルはUnityのバージョンアップでDLしなおしになる可能性がある
• デメリット
• 今のところアセットバンドルに未対応
• つまり、3DモデルなどはDLできない
• 将来的にはアセットバンドルも併用したいけど検討中。
デバイスキャッシュ
参考ソース Utage¥Scripts¥GameLib¥File¥AssetFileManager.cs
123. C#のシリアライズは・・・iOSで使えない
• セーブデータはやはりバイナリで作りたいところだが・・・
• C#のクラスを自動でバイナリ化してくれるBinaryFormatter を使う?
参考ソース http://forum.unity3d.com/threads/140606-iOS-Basic-BinaryFormatter
public static void SaveToBinaryFile(object obj, string path)
{
FileStream fs = new FileStream(path,
FileMode.Create,
FileAccess.Write);
BinaryFormatter bf = new BinaryFormatter();
//シリアル化して書き込む
bf.Serialize(fs, obj);
fs.Close();
}
iOSでは使えない
(使える場合もあるようだが、
非常に限定的なので非対応
と思ったほうがいい)