アセットバンドルへのスクリプトを含める
Unity 3.5アップグレードガイド

Unity3.5から4.0へのアップグレードガイド

GameObjectのactiveの状態

Unity 4.0 ではGameObjectのアクティブ(active)状態の操作の仕方が変わりました。GameObjectのアクティブ状態は親子構造の子のGameObjectへ引き継がれるので,非アクティブのGameObjectの子は全て非アクティブになります。新しい挙動は古いものよりも役に立つと思いますし,いつもこの方法にすべきです。また今後実装予定の新しいGUIシステムではこの新しい挙動に依存し,それなしでは実現が不可能です。残念なことですが,新しいUnity 4.0の挙動のせいで今まで作っていたプロジェクトを修正するためにいくつか作業が発生してしまいます。下記がその作業項目です:

旧仕様:

  • GameObjectはアクティブかそうでないかは.activeプロパティで定義されます。
  • これは.activeプロパティのチェックで判定と設定が可能です。
  • 一つのGameObjectの アクティブ状態はその子のGameObject群には影響しません。自分の子全てに影響させたいのであればGameObject.SetActiveRecursively を呼ぶ必要があります。
  • 親のGameObjectでSetActiveRecursively を使うと,その前までに設定していた子のGameObjectのアクティブ状態は失われます。親と子のGameObjectに対しSetActiveRecursivelyを使って非アクティブ→アクティブにすると,それらは全てアクティブになります。もし子のアクティブ状態を維持したいのであれば,それらを手動でアクティブを設定しなくてはなりませんでした。
  • プレハブはアクティブ状態を含まなかったので,Prefabからインスタンスを作った後は必ずアクティブでした。

新仕様:

  • GameObjectがアクティブかそうでないかは,それ自身とその上の全ての親の ,.activeSelf プロパティで定義されます。もしそれ自身の.activeSelf プロパティとその親全ての.activeSelf プロパティがtrueならば,GameObjectがアクティブになります。もし親のいずれかがfalse ならば,そのGameObjectは非アクティブになります。
  • これは.activeInHierarchyプロパティを使って判定されます。
  • GameObjectの.activeSelf 状態はGameObject.SetActiveで変更出来ます。その前まではアクティブだったGameObjectでSetActive (false) を呼ばれると,そのGameObjectとその子全て非アクティブになります。その前までは非アクティブだったGameObjectでSetActive (true) を呼ばれると,そのGameObjectとその子全てアクティブになります。子たちはその親全てがアクティブになってはじめてアクティブなります。(例:全ての親の.activeSelf をtrueに設定)
  • これは次のことを意味します:アクティブ状態は親から引き継ぐものなので,もはやSetActiveRecursively は必要なくなりました。さらに次のことも意味します:ヒエラルキーある箇所でアクティブ/非アクティブはSetActiveを呼んでも,子の以前のアクティブ状態は保存されます。
  • プレハブはアクティブ状態を含むようになったので,Prefabから作ったインスタンスはその状態に準じます。

例:

3つのGameObjectA,B,Cがあり,BとCはAの子であるとします。

  • C.SetActive(false) を呼び出すことによって,Cを非アクティブにします。
  • ここでは,A.activeInHierarchy == true, B.activeInHierarchy == true,C.activeInHierarchy == false となります。
  • 同様に,A.activeSelf == true,B.activeSelf == true,C.activeSelf == false となります。
  • 同様に,A.activeSelf == true,B.activeSelf == true,C.activeSelf == false となります。
  • そうなると,A.activeInHierarchy == false,B.activeInHierarchy == false,C.activeInHierarchy == falseとなります。
  • 同様に,A.activeSelf == false,B.activeSelf == true,C.activeSelf == falseとなります。
  • ここでA.SetActive(true)を呼び出すことによって,再び親をアクティブにします。
  • そうなると,A.activeInHierarchy == trueに戻り, B.activeInHierarchy == true, C.activeInHierarchy == falseとなります。
  • 同様に,A.activeSelf == true,B.activeSelf == true,C.activeSelf == false となります。

エディタでの新しいアクティブ状態

これらの変化を可視化するために,Unity 4.0のエディタでは,非アクティブのGameObjectは,Hierarchyで暗く表示されます(それ自身が.activeSelfプロパティがfalse,またはその親がそうなっていれば)。Inspectorでもアイコンは暗く表示されます。GameObjectの自身の.activeSelf プロパティはactiveチェックボックスをオンにすると反映されます。親状態に関係なく切り替えることができます(ただし,すべての親がアクティブである場合,このチェックだけでそのGameObjectをアクティブになります)。

これは,既存のプロジェクトにどのように影響するか:

  • GameObject.activeプロパティとGameObject.SetActiveRecursively()関数の廃止によって,あなたのコードの中に影響を与える可能性のあります。
  • しかし,それらはまだ機能しています。GameObject.active の値を読むことは GameObject.activeInHierarchyの値を読み取ると同等であり,GameObject.activeを設定することとGameObject.SetActive()の呼び出しと等価です。GameObject.SetActiveRecursively()を呼び出すことは,そのGameObjectとそれのすべての子にGameObject.SetActive()を呼び出すことと等価です。
  • 3.5からの引き継がれるシーンでは,シーン内の全てのGameObjectのselfActiveプロパティは,3.5で設定していたactiveプロパティが引き継がれて,インポートされます。
  • 結果として,Unityの以前のバージョンからインポートされたプロジェクトは(コンパイラの警告はあるものの)期待通りに動作するでしょう。ただしそれは,(Unity 4.0で利用できない)非アクティブのGameObjectがアクティブの子GameObjectを持つことに依存していないことが前提です。
  • 結果として,Unityの以前のバージョンからインポートされたプロジェクトは(コンパイラの警告はあるものの)期待通りに動作するでしょう。ただしそれは,(Unity 4.0で利用できない)非アクティブのGameObjectがアクティブの子GameObjectを持つことに依存していないことが前提です。

アセット生成工程パイプラインの変更

4.0の開発の過程で,当社のアセットインポートパイプラインは,パフォーマンス,メモリ使用量,安定性を向上させるために,内部のいくつかの重要な工程が変更されました。これらの変更はほとんどの部分については影響はありません。以下の例外を除いて:アセット内のオブジェクトは,インポートパイプラインの最後の最後まで以前にインポートされたバージョンのものが存続し,最後に完全に置き換えられます。

最初のパートでは,ポストプロセス時には,アセット内のオブジェクトへ正しい参照を取得することはできないことを意味し,次のパートでは,ポストプロセス中の変更を保存している間,前のインポートしたバージョンへ参照を使う場合,それらの変更が失うことを意味します。

永続的ではないという理由で,参照が失われる例

次の短いコード例でみてみます:

public class ModelPostprocessor : AssetPostprocessor
{
    public void OnPostprocessModel(GameObject go)
    {
        PrefabUtility.CreatePrefab("Prefabs/" + go.name, go);
    }
}


Unity3.5では,これはメッシュ等の正しい参照を持ったプレハブが生成されるでしょう。これは全てのメッシュが既に永続化されているからです。しかし,Unity4.0の場合ではそうならないので,同じポストプロセサーでもメッシュへの参照が切れたプレハブを作成します。それは,Unity4.0のはまだ元のモデルプレハブ内のオブジェクトへの参照を解決する方法を知らないという単純な理由です。正しくmodelprefabをコピーするには,すべてのアセットのインポートをやり過ごすOnPostProcessAllAssetsを使うべきです。そうするとmodelprefabをみつけて,上記のように新しいプレハブを作成します。

前にインポートして,捨てられるアセットへの参照の例

二番目の例は少し複雑ですが,実際にあった,3.5で正常に動いたものが4.0で動かなくなったケースです。ここではScriptableObjectは簡単なメッシュへの参照を持っているとします。

public class Referencer : ScriptableObject
{
    public Mesh myMesh; 
}


モデル内のメッシュへの参照を持つアセットを作成するために,このScriptableObjectを使います。その後ポストプロセッサで,その参照を持ってきて,別の名前を付け,モデルを再インポートした際にメッシュの名前は最終的な結果はポストプロセッサが決定します。

public class Postprocess : AssetPostprocessor
{
    public void OnPostprocessModel(GameObject go)
    {
        Referencer myRef = (Referencer)AssetDatabase.LoadAssetAtPath("Assets/MyRef.asset", typeof(Referencer));
        myRef.myMesh.name = "AwesomeMesh";
    }
}


これはUnity3.5でうまくいきましたが,Unity4.0で既にインポートされたモデルを完全に置き換えられますので,前回のインポートからメッシュの名前を変更しても影響はありません。ここでの解決策は,何か他の手段によってメッシュを見つけて,その名前を変更することです。注意するべき最も重要なことは,Unity 4.0ではポストプロセッサに与えられた入力を修正する「だけ」にするべきで,同じアセットの以前にインポートされたバージョンをあてにしないことです。

メッシュの読み取り/書き込みオプション

Unity 4.0では Mesh のImport Settingsに “Read/Write Enabled” オプションが追加されました。このオプションがオフにすると,Unityはゲーム内でのメッシュデータのコピーをアンロードすることができるので,メモリを節約できます。

ただし,あなたは単にスケーリングしたり,や非線形なスケールを使用して実行時にメッシュをインスタンス化したりしている場合は,あなたはそれらのインポート設定で “Read/Write Enabled” を有効にする必要があります。その理由は,非線形なスケーリングはメッシュデータをメモリ内に保持する必要があるからです。通常,ビルド時にこれを検出しますが,メッシュは,実行時にスケーリングやインスタンス化されるときには,これを手動で設定する必要があります。そうしないと,ビルドされたゲームの中で正しくレンダリングされない場合があります。

メッシュの最適化

Unity 4.0のModel Importerは,メッシュの最適化が改善されました。Unity 4.0ではModel Importer の “Mesh Optimization” チェックボックスがデフォルトで有効になっており,最適なパフォーマンスを出すためにメッシュ内の頂点の順序を変更します。あなたのプロジェクト用の,メッシュの頂点の順序に依存するポストプロセスのコードや効果は,この変更によって壊れる可能性があります。その場合には,Mesh Importerの “Mesh Optimization”はオフにしてください。SkinnedClothコンポーネントを使用している場合は特に,このメッシュの最適化は,あなたの頂点ウェイトのマッピングが変更されることがあります。あなたが3.5から引き継いだプロジェクトでSkinnedClothを使用しているのであれば,影響を受けるメッシュの “Mesh Optimization”をオフにするか,新しい頂点の順序と一致するように頂点ウェイトを再構成する必要があります。

モバイル入力

Unity 4.0 によりモバイル センサー入力はプラットフォーム間の整合性が改善され,具体的にはモバイルプラットフォームで典型的な入力をハンドリングする場合にコードの記述する量が少なくなっています。改善により加速度センサーおよびジャイロセンサー入力は iOS および Android で同じように画面の向きに従います。この変更を活用するには,入力に関わるコードのリファクタリングを行い,加速度センサーおよびジャイロセンサー入力のハンドリングを行う際のプラットフォームおよび画面の向きに固有のコードを削除します。iOSで従前の仕様をそのまま使用したい場合は Input.compensateSensors を false に指定します。

アセットバンドルへのスクリプトを含める
Unity 3.5アップグレードガイド