投稿者「moku」のアーカイブ

moku について

iPhone, iPad & Android アプリを開発している mokuApps です。

[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

Panels of the Dead

Welcome to the world of Panels of the Dead!
Experience the fear of the approaching zombies!

This game is a panel tap type puzzle game.
The goal is to defeat the zombies while paying attention to life and water and survive for as long as possible.

– Strategy by choosing weapons
Normally you consume life to defeat zombies by knife.
By acquiring ammo, you can defeat zombies by handgun without consuming life.
You can also use a machine gun or a grenade to strike horde of zombies.

– Change in visibility due to the passage of time in the game
Every time you tap a panel or use a weapon, the time in the game elapses.
Visibility gets worse at night, and distant panels become invisible.
You need a strategy like keeping supplies in the daytime, just like a zombie drama.

– Upgrade by points acquired
When the game is over, you can acquire points according to the time you survived and the number of defeated zombies.
You can use that point to increase the maximum value of life and water, gain skills, and be able to play the next game advantageously.

– Skills
Life, water, weapon enhancements and the other 4 categories a total of 41 kinds of skills are available.
Since the number of slots where skills can be set is limited, try searching for the strongest combination of yourself.

– Achievements
There are more than 300 achievements in 32 types, and you can earn bonus points by achieving it.

* As you upgrade it takes a long time for one game , but you can interrupt it at any time during the game and resume from the interruption data next time.

App Store Android app on Google Play

パネルズ・オブ・ザ・デッド

パネルズ・オブ・ザ・デッドの世界へようこそ!
迫りくるゾンビの恐怖をお楽しみください!

本作はパネルタップ方式のパズルゲームです。
ライフと水分に注意しながらゾンビを倒し、できるだけ長く生き延びるのが目的です。

・武器の選択による戦略性
通常はナイフによりライフを消費してゾンビを倒します。
弾薬を獲得するとハンドガンによって、ライフを消費せずにゾンビを倒すことができます。
またマシンガンやグレネードでゾンビを一網打尽にすることもできます。

・ゲーム内の時間経過による視界の変化
パネルをタップしたり武器を使用するたびにゲーム内の時間が経過します。
夜になると視界が悪くなり、遠くのパネルが見えなくなります。
昼の内に物資を確保しておくなど、ゾンビドラマさながらの戦略が必要になります。

・獲得したポイントによりアップグレード
ゲームオーバーになると、生き延びた時間や倒したゾンビの数に応じてポイントが獲得できます。
そのポイントを使用してライフや水分の最大値を増やしたりスキルを獲得して、次のゲームを有利に進めることができるようになります。

・スキル
ライフ・水分・武器の強化やその他の4カテゴリ計41種類のスキルが用意されています。
スキルをセットできるスロットの数は限られていますので、自分だけの最強の組み合わせを探してみましょう。

・達成項目
32種類・合計300段階以上の達成項目があり、達成することでボーナスポイントを獲得できます。

※ アップグレードしていくと1ゲームにかかる時間が長くなってしまいますが、ゲーム中はいつでも中断して、次回に中断データから再開していただくことができます。

App Store Android app on Google Play

[Unity]:MonoBehaviour.OnApplicationPause()の挙動

[検証バージョン]
Unity 5.1.2p2
iOSシミュレータ 8.4
Android Genymotion 4.2.2 API 17

アプリがバックグラウンドに入った時・および復帰した時の処理を記述するMonoBehaviour.OnApplicationPause()

この中に記述する処理が重く時間がかかり途中でアプリが強制終了された場合、どのような挙動になるのか検証してみた。

・検証方法
OnApplicationPauseでバックグラウンド退避時の処理中に数秒待機してデバッグプリントを行う。

using UnityEngine;

public class GameController : MonoBehaviour {
	void OnApplicationPause(bool isPause) {
		if (isPause) {
			Debug.Log("OnApplicationPause()");
			System.Threading.Thread.Sleep(3000);
			Debug.Log("3 seconds lator..");
		}
	}
}

・iOSの場合
アプリ起動中にホームボタン2度押し→アプリを終了

-> applicationWillResignActive()
OnApplicationPause()
3 seconds lator..
-> applicationDidEnterBackground()
-> applicationWillTerminate()

ちゃんと3秒後にデバッグプリントされた後に、バックグラウンド→終了となっている。

ただし、OnApplicationPauseをコルーチンにした場合はバックグラウンドに入った時点で処理が一時停止してしまうので注意が必要。

・Androidの場合
ハードウェアボタンでアプリの一覧を表示→アプリを終了

OnApplicationPause()のデバッグプリントのみで、処理は途中で中断されてしまった?

Androidの場合は、OnApplicationPause()での処理には注意が必要みたい。

[Unity, NGUI]:スクロールビューにスクロールバーを追加する

[検証バージョン]
Unity 5.1.2p2
NGUI 3.9.1

スクロールビューの基本についてはこちらをどうぞ。

1.スクロールバーの背景となる部分とつまみの部分、計2つのスプライトを作成。
スクロールバーのスプライトを追加

ヒエラルキー上での配置はスクロールビューの配下以外であればどこでも大丈夫。

垂直方向のスクロールバーの場合は2つのスプライトの高さを合わせておく必要がある。
見た目的につまみ部分が前面に表示されるようにDepthの設定もお忘れなく。

2.スプライトにコライダーを設定
スクロールバーの背景部分をクリックして移動する機能が必要なければ、背景用のスプライトにはコライダーを設定しなくても大丈夫。
コライダーの設定は目的のスプライトを選択した状態で、メニューバーから「NGUI」-「Attach」-「Collider」とするのが簡単。

3.適当なオブジェクトにUIScrollBarコンポーネントを追加
UIScrollBar

UIScrollBarコンポーネント用にNGUI Widgetを作ってその配下に先ほど作成したスプライトを配置しておくのが綺麗だと思う。
目的のオブジェクトを選択した状態でメニューバーから「NGUI」-「Attach」-「Scroll Bar Script」。

UIWidgetではなく適当なオブジェクトでも大丈夫だが、UIScrollView自体にUIScrollBarコンポーネントを追加するとスクロールバーの挙動がおかしくなる。

4.UIScrollBarの設定
UIScrollBarの設定

Foreground, Backgroundにそれぞれつまみ用・背景用のスプライトを設定。
Directionも適切に。

5.スクロールビューにスクロールバーを設定
UIScrollViewにスクロールバーを設定

スクロールビューのインスペクタにScroll Barsの項目があるので、Horizontal/Vertical目的の方にスクロールバーを設定。

ここで一度実行すると、UIScrollBarのValueなどの値が反映されるので、そこでスクロールバーの初期位置などを設定できる。
UIScrollBarの設定

Sizeが、スクロールビュー配下の全体サイズに対する表示範囲。スクロールビューに対して2倍のサイズのものを配置していれば0.5となる。
Valueがつまみの初期位置、0〜1。