20190830のUnityに関する記事は4件です。

Unity Addressable Asset Systemを試してみた (その1)

前提

  • unity 2018.4.7f1
  • Addressables 1.1.10
  • 導入から簡単に使ってみるところまで
    • アセットに含まれるプレハブとスプライトを使って、スライドショウを実行します。

公式ドキュメント

導入

  • パッケージマネージャーを使ってAddressablesを導入します。
  • Window (Menu) > Package Manager > Pakkages (Window) > Addressables > Install (Button) SS-13.png

Addressablesの初期化

  • Addressablesウィンドウで初期化を実施します。
  • Window (Menu) > Asset Management > Addressables > Addressables (Winodow) > Create Addressables Settings (Button) SS-1.png

設定

  • Addressablesウィンドウから設定を選び、インスペクターで設定します。 SS-2.png
  • Addressables (Winodow) > Profiles Default > Inspect Profile Settings
    SS-3.png

カタログ

  • Player Version Overrideを記入し、Build Remote Catalogをチェックして、Remote Catalog Build/Load PathをRemote Pathに設定します。
    SS-4.png
    これで、指定したバージョンを含む名前で、Build Pathにカタログが生成されます。
  • バージョンが指定されないと、代わりにビルド日時が使われます。
    古いカタログは自動的に削除されないので、ファイルが増えていきます。
  • カタログは、実行時にリモートから読み込まれ、更新の有無が判定されます。
    カタログが作られていなかったり、正しいカタログが読み込めないと、アセットファイルが新しくなっていても更新は行われません。
  • アプリとアセットが必ず同時に更新されるプロジェクトであれば、カタログは不要だと思われます。
    対して、アセットだけ更新される場合は、カタログが必要です。

リモートパス

  • RemoteBuildPathRemoteLoadPathを記入します。
    SS-7.png
  • これらは、それぞれ、「アップロードするアセットファイルを作るフォルダ」と「アップロード先(=実行時に取得する)のURL」です。
    • [BuildTarget]が、ビルドターゲットを表す文字列に置き換えられることで、ターゲット毎に異なるアセットに切り替わります。

ラベル

  • 新しいラベル(タグ)を作ります。
    SS-5.png
    SS-6.png
    これによって、アセットを一括ロードできるようになります。

アセットの構築

グループの作成

  • Addressablesウィンドウにグループを作ります。
  • Addressables (Window) > Create New Group (Context Menu) > Packed Assets SS-8.png
  • デフォルトグループは、コンテキストメニューから切り替え可能です。

グループの設定

  • Addressablesウィンドウで作成したグループPacked Assetsを選択して、インスペクターで設定します。
  • Build PathLoad Pathをリモートに設定します。
    SS-9.png

アセットの追加

  • グループにプロジェクトウインドウからアセット(ファイルまたはフォルダ)を追加します。
  • フォルダを追加すると階層ができます。
    SS-10.png
  • Addressablesに追加されたアセットには、マークが付きます。
    SS-13.png
    • このチェックを外すと、Addressablesウィンドウからも消えます。
  • 逆に、Projectウィンドウで選んだアセットに対して、インスペクターでマークすることで、デフォルトグループに加えることも可能です。
  • アセットや階層には、ラベル(タグ)を付けられます。
    SS-11.png
  • アセットや階層の名前(Asset Address)は元のパス名から自動で付けられます。
  • これらのアドレスは任意に変更できます。アセットや階層を選んで、コンテキストメニューからSimplify Entry Namesを実行すると自動的に短くできます。
    SS-12.png
  • アセットや階層の名前は、Addressablesウィンドウでも、インスペクターでも変更可能です。
  • アセットや階層は、ドラッグ&ドロップで、あるいは、コンテキストメニューからグループ間を移動できます。

アセット(だけ)のビルド

  • Addressables (Window) > Build > Build Player Content

アセットを使う

アセットの参照

  • アセットは、string(名前、ラベル)、または、AssetReference(インスペクター経由)で特定します。
// インスペクターでアセットを指定する
[SerializeField] private AssetReference SpriteAsset = default;
  • 以降の例では、AssetReferenceは使用せず、名前とラベルを使います。

サンプルの流れ

SampleMain.cs
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AddressableAssets;

public class SampleMain : MonoBehaviour {

    private void Start () {
        StartCoroutine (loader ());
    }

    private IEnumerator loader () {
        // ロードの開始
        var textHandle = Addressables.LoadAssetAsync<GameObject> ("Prefabs/BottomText.prefab");
        var imageHandle = Addressables.LoadAssetAsync<GameObject> ("Prefabs/FullScreenImage.prefab");
        var spriteHandle = Addressables.LoadAssetsAsync<Sprite> ("Sprites", null); // ラベルを指定して一括ロード
        // 完了の待機
        yield return new WaitUntil (() => textHandle.IsDone && imageHandle.IsDone && spriteHandle.IsDone);
        // エラーがないことを確認
        if (textHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded
            && imageHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded
            && spriteHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded) {
            // プレファブからオブジェクトを生成
            var image = Instantiate (imageHandle.Result, transform).GetComponent<Image> ();
            var text = Instantiate (textHandle.Result, transform).GetComponent<Text> ();
            // スプライトを順に切り替え
            for (var i = 0; i < spriteHandle.Result.Count; i = (i + 1) % spriteHandle.Result.Count) {
                image.sprite = spriteHandle.Result [i];
                text.text = $"{spriteHandle.Result [i].name}  <size=20>© UTJ/UCL</size>";
                yield return new WaitForSeconds (3f);
            }
        }

    }
}

  • 非同期に処理する必要があるので、コルーチンを使います。
  • プレハブは個別の名前を、スプライトは一括してラベルを指定してロードを開始します。
  • 非同期ロードハンドルをチェックしてロードの完了を待ちます。
  • ロードが成功したかチェックします。
  • プレハブからオブジェクトを生成します。
  • スプライトを順に表示します。

プロジェクトの入手 (GitHub)

ダウンロード ⇒ AddressableAssetsTest.unitypackage
ソースはこちらです。

あとがき

気になったこと

  • まだ、公式ドキュメントが英語しかないようです。
  • 短期間に色々変わっているようで、ネットで調べた情報が実際と異なったりしました。
  • 設定をいじっていたら、Addressablesウインドウからアセットの一部が消えてしまって復旧できなくなる…ということが2度ありました。

今後の予定

  • 次回は「Addressablesを製品で使うとどうなるだろう」というテーマになると思います。
  • 具体的な製品プロジェクトの予定が立ったら進展すると思います。

参考にさせていただいた記事 (Qiita)

どうもありがとうございました。


UNITY-CHAN! © Unity Technologies Japan/UCL

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UnityのmetaファイルにImportLogsという謎の差分が出てしまうときの対処法

UnityプロジェクトをGitで管理していてLFSを使っているときに起きた現象です。

事象

Unityで開発してたときにgitをみるとmetaファイルに謎のdiffが出ている。
ImportLogsがうんちゃら。
類似現象 → https://forum.unity.com/threads/editor-keeps-reimporting-fbx-assets.514085/

原因

差分の出るmetaファイルの元ファイルがlfs fetchされる前のテキスト状態になってた。
なぜか git lfs fetch --all してもファイルがfetchされない。

対処

一度fetchされないファイルを削除してgitで変更を破棄する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

時を操るアセット「Chronos」の基本的な使い方

この記事について

この記事はUnityアセット真夏のアドベントカレンダー 2019 Summer!31日目の記事です。

Chronos」とは?

LIDIQ氏がAssetStoreにて製作、販売をしている、
あらゆるオブジェクトの時間を操れるアセットです。

Chronos Time Control

どのように操れるか

698F7890-57F3-4626-90AF-2676F33008DE.jpeg
時間を遅くしたり止めたり、加速させたり戻したり…
時間の調整が細かく出来ます。

時間操作の影響を受ける対象

B486C5DC-5918-4CA7-8BB3-4ECF2E8652A8.jpeg
一括で管理したり、いくつかのグループに分けて管理したり、1つずつ管理したり、範囲(エリア)内のオブジェクトのみを管理したり…
カスタマイズ性が高いのも特徴です。

どのような挙動をするかはこちらの動画をご覧下さい。

基本的な使い方

それでは、使い方に移っていきます。
まず、Chronosの時間操作を扱うためにはシーン上に「Timekeeper」というコンポーネントを持つオブジェクトが必要です。
なのでまずはそれを追加してみましょう!
(既にプロジェクトを作成し、Chronosを購入、インポートしている前提で進めていきますので、まだの方は先にインポートまで終わらせておいてください)
6CF49CC4-0323-47B6-AF2F-4FC76929BB67.png
Hierarchyビュー上で右クリックします。
A1EE4BD2-C79D-4CA0-97BA-2FB885C418E2.png
下にある「Timekeeper」をクリック
2D88F7A5-FDEE-40AA-8591-59F58B172B57.png

これで、Chronosを使う準備が出来ました。

時間操作

それでは時間を操作していきます。
時間を操作したいオブジェクトに、「Localclock」と、「Timeline」というコンポーネントを追加します。
7D91931F-7DA6-4B00-8729-C99D78BB41CA.png
Addcomponentをクリックして(今回は物理演算を適用するためRigidbodyも追加しています)
9DD3590A-DDA6-4BA4-B93E-D905180B3787.png
Localclock」を追加。
81406F63-399D-4991-8FAC-C088CDB3C07A.png
続いて「Timeline」も追加します。
これで時間操作を適用させる準備が出来ました。
時間を操作するためにスクリプトを書いていきます。
2881E4D8-1600-429B-AB6E-E5FB36B9CDB5.png
Projectビュー上で右クリックし、createからC#Scriptを押します
スクリプト名を適当に決め(私はTimeControlsしました)そのスクリプトファイルを開きます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Chronos;

public class TimeControl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        GetComponent<LocalClock>().localTimeScale = 0.01f;
    }

    // Update is called once per frame
    void Update()
    {

    }
}

このコードを書き、時間操作をしたいオブジェクトに適用することで時間を遅くする(100分の1)にすることができます。
コードの解説をしますと

GetComponent<LocalClock>()

まずオブジェクトが持つ「Localclock」を取得し

localTimeScale = 0.01f;

その時間を0.01倍速にしています。
この0.01の部分を変えれば任意の速度に変更できます。

次にこれをオブジェクト単位ではなく、一括で変更できるようにしていきましょう。
まず親にしたいオブジェクトに「GlobalClock」を追加しますが、Timekeeperに既についているので、Timekeeper以外を親にしたい場合以外は追加する必要はありません。
それでは「GlobalClock」と「LocalClock」を関連付けしていきます。
3F0CB524-D82F-4B92-B5F0-B616BAA8AB5F.png
GlobalClock」のKeyの部分の名前を覚えておきます。
3C5750D7-019C-4E89-8DCE-714CD0A5AB1E.png
そして「Timeline」のModeをLocalからGlobalに変えます。
CF0E3349-419A-45EE-BEFE-758ECDBCB20A.png
最後に「Timeline」のGlobalClockを先程のKeyの名前を選択して、完了です。
これをまとめて動かしたいオブジェクトの数だけ行ってください。

それでは先程のコードを改変して、Tキーを押した時に全体の時間を止め、もう一度Tキーを押すと時間が元に戻るコードを書いていきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Chronos;

public class TimeControl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            if (GetComponent<GlobalClock>().localTimeScale == 0)
                GetComponent<GlobalClock>().localTimeScale = 1;
            else
                GetComponent<GlobalClock>().localTimeScale = 0;
        }
    }
}

このコードを「GlobalClock」を持つオブジェクトに適用します。
そしてゲームを初めTキーを押してみると…?
一度押すと止まり、もう一度押すと動いたと思います。
最後にコードの解説をしますと

if (Input.GetKeyDown(KeyCode.T))
{
の部分で「もし、Tキーが押されたなら〜」という条件式を作り

if (GetComponent<GlobalClock>().localTimeScale == 0)
GetComponent<GlobalClock>().localTimeScale = 1
の部分で「既に時間が止まっているなら〜」という条件式をさらに作り
その下の文で時間を等倍にする処理をしています。
つまり「時間が既に止まっているな時間を等倍にする」という処理をここで行っています。

else
GetComponent<GlobalClock>().localTimeScale = 0;

この文で「時間が止まっていないなら」という先程の条件式の反対の状況になっていれば処理し時間を止めます。
ここで「時間が止まっていないなら時間を止める」という処理です。

最後に

Chronosではここで紹介した以外にもまだまだ使い方があります!
是非Chronosをマスターして時間を自在に操って見てください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity Shader における Color プロパティの色空間

概略

Unity の Shader Property は Color を持つことができる 。また [HDR] Attribute を付与することで HDR Color の指定もできる。
しかしこれらの Color Property が実際にどのような値で保存され、Inspector 上で表示され、そしてどういった値としてシェーダに渡されるのかは詳細には書かれていない。
本記事ではその点を明らかにする。

結論

表で結論を示す。

プロパティ Material に記録される値 Inspector 上の見た目 Shader に渡される値 (Linear ColorSpace)
通常の RGB チャンネル 0.5 [sRGB] 0.5 [sRGB] 0.217 [Linear]
HDR の RGB チャンネル 0.5 [Linear] 0.73 [sRGB] 0.5 [Linear]
Alpha チャンネル 0.5 [Linear] バーの半分 0.5 [Linear]

通常の RGB チャンネル

[HDR] Attribute の付いていない普通の Color Property は sRGB 空間の値を格納することを目的としている。
したがって Inspector 上で #808080 の sRGB ハーフグレイを指定すると 0.5 [sRGB] という値がそのまま記録される。
また Inspector 上における色のプレビューも、人間の直感的に中間色に近い sRGB ハーフグレイとなる。
そして Linear ColorSpace 設定のプロジェクトの場合 0.5 [sRGB] を sRGB2Linear 変換した 0.217 [Linear] の値がシェーダに渡される。

[HDR] Attribute の RGB チャンネル

[HDR] Attribute の付いた Color Property は HDR な Linear 空間の値を格納することを目的としている。
したがって Inspector 上で HSV = (0, 0, 50) を指定すると 0.5 [Linear] という値がそのまま記録される。
また Inspector 上における色のプレビューは sRGB ハーフグレイより明るめのグレイが表示される。これは 0.5 [Linear] を Linear2sRGB 変換した 0.73 [sRGB] だ。
ここで 1 点注意すべきなのは HDR Color のカラーパレットにおける #808080 は sRGB ハーフグレイではなく Linear 空間の 0.5 になるということだ。
この仕様は正直どうなのだろうかとは思う。
そして Linear ColorSpace 設定のプロジェクトの場合、値は無変換のまま 0.5 [Lienar] がシェーダに渡される。

Alpha チャンネル

アルファチャンネルは [HDR] Attribute の有無に関わらず Linear 空間の値が格納されている。
Inspector 上で 50% を指定すればそのまま 0.5 [Linear] の値が記録される。
そして Linear ColorSpace 設定のプロジェクトの場合、値は無変換のまま 0.5 [Linear] がシェーダに渡される。

さいごに

これらの仕様は Material を設定する側の人間は意識する必要はない。Shader を深く設計する必要のある人間だけが意識する必要のある挙動である。
通常は Inspector 上における色のプレビュー、そして最終的な描画結果をみて判断すると良いだろう。
ただ前述したように HDR Color のカラーパレット指定においては Web カラー指定(例 #808080 )が意図しない明るい色になってしまうということは覚えておくと便利だろう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む