月別アーカイブ: 2017年2月

[Unity]:プレファブのYAMLを直接編集して子を削除する

[検証バージョン] Unity 5.5.1p3

直接編集はファイルの破損などの危険があるため、各自で判断の上、バックアップをちゃんととってお試しください。

追記:

ヒエラルキービュー上でプレファブの子を削除するとプレファブとの関連付けが解かれたように見えますが、実はその状態でApplyをすることができます。
Twitterでご教示いただきました。ありがとうございます!


階層構造を持つオブジェクト群をプレファブ化した場合、その子の一部を消すことってできませんよね?

プロジェクトビューからは子の一部を削除することはできないし、ヒエラルキービューで子を削除しようとするとプレファブとの関連が解けてしまいます。
子を追加してApplyはできるけど、削除はできないんです。

※ もしUnityの通常の操作でプレファブの一部の子だけを消すことができるのでしたら教えてください。

なんとかならないかと思い、まずはプレファブのインスタンスが置かれているシーンファイルをのぞいてみました。
(シーンファイルはデフォルト設定ではバイナリになっているので、Editor SettingsでAsset SerializationのModeをForce Textにしないと中身を見ることができません)

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
 ・
 ・
 ・
(ライティングなどのシーン設定に関する記述)
 ・
 ・
 ・
--- !u!1001 &1314774805
Prefab:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications:
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalPosition.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalPosition.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalPosition.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.w
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_RootOrder
      value: 0
      objectReference: {fileID: 0}
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 100100000, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
  m_IsPrefabParent: 0

どうやらプレファブとの関連付けが記述されているだけで、プレファブファイルの方を直接編集してやれば上手くいきそうです。

※ ただし、以下の場合は関連付け以外の情報がシーンファイルに含まれるので注意が必要です。
・プレファブ化した元のオブジェクトがそのままシーンに残っている場合
・プレファブをインスタンス化したものにコンポーネントや子オブジェクトを追加した場合。

それではプレファブのファイルを編集してみます。

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
  m_ObjectHideFlags: 1
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications: []
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 0}
  m_RootGameObject: {fileID: 1006150272106676}
  m_IsPrefabParent: 1
--- !u!1 &1006150272106676
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4721125990716184}
  m_Layer: 0
  m_Name: GameObject
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!1 &1271471559630830
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4955832607490314}
  - component: {fileID: 33287708229778766}
  - component: {fileID: 65699820418463966}
  - component: {fileID: 23228631480229132}
  m_Layer: 0
  m_Name: Cube
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &4721125990716184
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1006150272106676}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children:
  - {fileID: 4955832607490314}
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &4955832607490314
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1271471559630830}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 4721125990716184}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &23228631480229132
MeshRenderer:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1271471559630830}
  m_Enabled: 1
  m_CastShadows: 1
  m_ReceiveShadows: 1
  m_MotionVectors: 1
  m_LightProbeUsage: 1
  m_ReflectionProbeUsage: 1
  m_Materials:
  - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
  m_StaticBatchInfo:
    firstSubMesh: 0
    subMeshCount: 0
  m_StaticBatchRoot: {fileID: 0}
  m_ProbeAnchor: {fileID: 0}
  m_LightProbeVolumeOverride: {fileID: 0}
  m_ScaleInLightmap: 1
  m_PreserveUVs: 1
  m_IgnoreNormalsForChartDetection: 0
  m_ImportantGI: 0
  m_SelectedEditorRenderState: 3
  m_MinimumChartSize: 4
  m_AutoUVMaxDistance: 0.5
  m_AutoUVMaxAngle: 89
  m_LightmapParameters: {fileID: 0}
  m_SortingLayerID: 0
  m_SortingOrder: 0
--- !u!33 &33287708229778766
MeshFilter:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1271471559630830}
  m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!65 &65699820418463966
BoxCollider:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1271471559630830}
  m_Material: {fileID: 0}
  m_IsTrigger: 0
  m_Enabled: 1
  serializedVersion: 2
  m_Size: {x: 1, y: 1, z: 1}
  m_Center: {x: 0, y: 0, z: 0}

「— !u!1001 &100100000」のような記述から始まるひとかたまりが一つのオブジェクトやコンポーネントを表しているのがわかります。
前半がオブジェクトに関する記述、後半がコンポーネント。親子関係はTransformコンポーネントの部分に記述されています。

「m_Name:」にオブジェクト名が書かれているので、今回消したい子オブジェクト’Cube’を探します。

--- !u!1 &1271471559630830
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4955832607490314}
  - component: {fileID: 33287708229778766}
  - component: {fileID: 65699820418463966}
  - component: {fileID: 23228631480229132}
  m_Layer: 0
  m_Name: Cube
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1

先頭に書かれている「— !u!1 &1271471559630830」の「1271471559630830」がこのオブジェクトの固有のIDです。
このIDでファイル内を検索すると4つのコンポーネントが付いていることがわかります。

そのうちの一つTransformコンポーネントに関する記述をみてみます。

--- !u!4 &4955832607490314
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1271471559630830}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 4721125990716184}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

今度はこのTransformコンポーネントのID「4955832607490314」で検索すると、親のTransformの記述が見つかります。

--- !u!4 &4721125990716184
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1006150272106676}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children:
  - {fileID: 4955832607490314}
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

ここの「m_Children:」というところに子のTransformのIDが書かれているので、この行を削除してしまいます。

--- !u!4 &4721125990716184
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1006150272106676}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children:
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

あとは、先ほど見つけたオブジェクトに関する記述と4箇所のコンポーネントに関する記述を消すだけです。

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
  m_ObjectHideFlags: 1
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications: []
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 0}
  m_RootGameObject: {fileID: 1006150272106676}
  m_IsPrefabParent: 1
--- !u!1 &1006150272106676
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 5
  m_Component:
  - component: {fileID: 4721125990716184}
  m_Layer: 0
  m_Name: GameObject
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &4721125990716184
Transform:
  m_ObjectHideFlags: 1
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  m_GameObject: {fileID: 1006150272106676}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children:
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

これでプレファブファイルがUnityで読み込まれたタイミングでプレファブと全てのインスタンス化されたオブジェクトから子オブジェクト’Cube’が消えます。

インスタンス化してシーンに置かれたオブジェクトに個別に編集を行なっている場合にはシーンファイルにゴミが残る可能性があるので、くれぐれもご注意ください。

以前にUnityのYAMLを読んでみようみたいな記事を見かけたことがあったのですが、まさか本当に自分が読むことになるとは思ってもいませんでした^^;
しかし実際にのぞいてみるとかなりシンプルで分かりやすいですね。
ちなみにプレファブをインスタンス化したものに施した変更はシーンファイルの中の「Prefab:」のところに追記される形で記述されます。

警告はしましたが実際はコンポーネントのパラメータを変更したり、コンポーネントを削除してる場合は今回の編集では影響受けないみたいです。
ただし削除するオブジェクトにコンポーネントを追加していたり、配下にさらに子を追加したりしているとシーンファイルにゴミが残るみたいです。

以下は削除したCubeオブジェクトに適当なスクリプトを追加、また配下にSphereを追加していた場合のシーンファイルです。

--- !u!1001 &1314774805
Prefab:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Modification:
    m_TransformParent: {fileID: 0}
    m_Modifications:
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalPosition.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalPosition.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalPosition.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.x
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.y
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.z
      value: 0
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_LocalRotation.w
      value: 1
      objectReference: {fileID: 0}
    - target: {fileID: 4721125990716184, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
      propertyPath: m_RootOrder
      value: 0
      objectReference: {fileID: 0}
    m_RemovedComponents: []
  m_ParentPrefab: {fileID: 100100000, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884, type: 2}
  m_IsPrefabParent: 0
--- !u!1 &1314774806 stripped
GameObject:
  m_PrefabParentObject: {fileID: 1271471559630830, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884,
    type: 2}
  m_PrefabInternal: {fileID: 1314774805}
--- !u!114 &1314774807
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 0}
  m_GameObject: {fileID: 1314774806}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: c75fe1ad4fe3e493ab421c02f41fed06, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 
--- !u!4 &1314774808 stripped
Transform:
  m_PrefabParentObject: {fileID: 4955832607490314, guid: 6071afa7dc4674b5ebaa3a0fa0c5c884,
    type: 2}
  m_PrefabInternal: {fileID: 1314774805}

Unityのヒエラルキービュー上では問題なさそうに見えますが、シーンファイルにはしっかりゴミが残っているようです。

ISUTA(イスタ)様に「エレベータ体重パズル」をご紹介いただきました!

ISUTA(イスタ)様に「エレベータ体重パズル」をご紹介いただきました!
ISUTA様、また素敵なレビュー記事を書いてくださったみきしろ様、誠にありがとうございます!

シンプルだけどかなりハードな計算パズル『エレベーター体重パズル』アプリが楽しくて可愛い♪

Elevator Capacity

Let’s sort cute characters so that total weight of them will be perfect for the max load of elevators!

‘Elevator Capacity’ is a simple addition puzzle game… but the later stages are pretty tough!

Let’s challenge the total 300 stages of begginers’, middle and advanced level!

Tips for puzzle out:
· Even if one elevator becomes perfect, it is not always the correct answer.
There may be other combinations of that weight.

· There is also a character with a weight of two or three characters.
For example, if there are 45kg and 50kg characters on a perfect elevator, you can replace them with a 95kg character and sort them into separate elevators.

· Let’s fine-tune after sorting by guesswork.
For example, if an elevator load is 198/200kg, it will be perfect if you can replace a character with another weighing 2kg heavier.

· If you got stuck …
Let’s look the answer from the pose menu and try again.
The combination of weight will change, but it might be easy to solve.

App Store Android app on Google Play

エレベーター体重パズル

可愛いキャラクター達の体重の合計がエレベーターの積載重量にぴったりになるように振り分けよう!

エレベーター体重パズルはシンプルな足し算パズルゲームです…が、後半のステージはかなり手強いぞ!

初級・中級・上級レベル各100ステージの合計300ステージにチャレンジしよう!

クリアのヒント:
・1つのエレベーターがぴったりになってもそれが正解とは限らない。
その重量になる組み合わせは他にもあるかも知れませんよ。

・1人で2,3人分の体重のキャラもいる。
例えば、ぴったりになっているエレベーターに45kgと50kgのキャラがいたら、95kgのキャラと入れ替えて別々のエレベーターに振り分けることができるよ。

・適当に振り分けてから微調整してみよう。
例えば、あるエレベーターが198/200kgならば、体重が2kg重い人と入れ替えられればぴったりになるよ。

・どうしても詰まったら…
ポーズメニューから答えを見てやり直してみよう。
重量の組み合わせは変わるけど、解きやすい組み合わせになるかも知れないよ。

App Store Android app on Google Play

Galaxy Blocks

Erase blocks like crazy!
Let’s compete high score with rivals around the world!!

· Tips for high score
1. Erase blocks quickly & continuously
Keep erasing blocks quickly, to become a combo and chance of high scores!
Winning score will increase gradually to 2 times, and 3 times by the combo bonus.
But try to be careful because it is lost combo, if you do not erase the next block during the display of the combo.

2. Erase same color blocks continuously
Additional combo occurs when you erase same color blocks continuously!
By multiplying with continuous combo, high score will grow more and more!!
Let’s take aim from color of the most numerous blocks in the first glance!

3. Upgrade
Upgrade with the point acquired by playing game or the bonus!
You can aim for a higher score!

App Store Android app on Google Play

Galaxy Blocks

タップでブロックを消しまくれ!
世界中のライバル達とハイスコアを競おう!!

・ハイスコアのコツ
1.ブロックを素早く消し続ける
素早くブロックを消し続けるとコンボになってハイスコアのチャンス!
コンボボーナスで獲得スコアが2倍、3倍とどんどん増えるぞ。
だけどコンボの表示がされている間に次のブロックを消さないとコンボ消失だから注意しよう。

2.同じ色のブロックを連続で消す
同じ色のブロックを続けて消すと追加コンボが発生!
連続コンボと掛け合わせて、どんどんハイスコアが伸びるぞ!!
ぱっと見で数の多い色から狙っていこう!

3.アップグレード
ゲームをしたりボーナスで獲得したポイントでアップグレード!
よりハイスコアを目指せるようになるぞ!!

App Store Android app on Google Play