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

Unityの基本操作

スクリーンショット (50).png
1:デスクトップのUnity Hubアイコンをダブルクリックして実行し、Unity Hubを開く

スクリーンショット (51).png
2:右上のアイコンをクリックする。すでに他人のIDが表示されている場合は、サインアウトを行う(36参照)。その後、「サインイン」を選択する。

スクリーンショット (53).png
3:自分のUnity IDとパスワードを入力して「サインイン」を選択する。

スクリーンショット (52).png
4:Unity IDがない場合は、「IDを作成」リンクをクリックする。

スクリーンショット (59).png
5:「Unity IDアカウントを作成」ウィンドウでメールアドレスとパスワードを入力する(自分のGoogleアカウントにすること)。その後、ユーザーネームとフルネームをローマ字で入力する。この時、半角英数字を使用すること。最後に「利用規約とプライバシーポリシー」(赤で囲んだ部分)のチェックボックスをオンにして、「Unity IDアカウントを作成」ボタンをクリックする。

スクリーンショット (60).png
6:指定したメールアドレスにUnityから確認メールが届くので、PCやスマホなどでメールの受信ボックスを開く。

スクリーンショット (63).png
7:Unityからのメールを開いて、「Link to confirm email」リンクをクリックする。

スクリーンショット (64).png
8:設定したUnity IDを入力して「サインイン」をクリックする。

スクリーンショット (65).png
9:右上のアイコンをクリックして、自分の名前が表示されているか確認しよう。

スクリーンショット (66).png
10:このIDはPCをまたいで共通で使える。どのPCのUnity Hubからでも、自分のUnity IDでログインすれば、同じサービスを受けられる(図は「開発者ダッシュボードに移動」を選択した場合)

スクリーンショット (67).png
11:同じく「マイアカウント設定」を選択した場合。ユーザーネームなどはこの画面から変更できる。

1.png
12:授業で配布されるプログラムはZip形式で圧縮されている。FserverなどからPCにコピーして、ダブルクリックしよう。

無題.png
13:ファイルをダブルクリックするとエクスプローラーが開くので、「展開」ボタンをクリックする。

無題2.png
14:続いて「すべて展開」をクリックする。

スクリーンショット (98).png
15:圧縮フォルダが展開されて、通常のフォルダが生成される。

スクリーンショット (72).png
16:Unity Hubを開き、「リストに追加」ボタンをクリックする。

スクリーンショット (74).png
17:先ほど解凍したフォルダを選択し、「フォルダーの選択」をクリックする。

無題.png
18:AseetsフォルダとProjectSettingsフォルダが表示された階層になったら、「フォルダーの選択」をクリックする。

スクリーンショット (78).png
19:フォルダがUnity Hubに登録されたら、クリックするとUnityエディタが起動する。

ワンポイントテクニック
スクリーンショット (99).png
20:Unityエディタで複数のバージョンがインストールされている場合、メニューから選択できる。授業で使うUnityは2019.4.1f1なので、間違わないようにしよう。

スクリーンショット (79).png
21:Unityエディタが表示される。プロジェクトエリアで「Tutorial」フォルダをクリックしよう。

スクリーンショット (80).png
22:Unityのシーンファイルが3個表示されるので、「Title」ファイルをクリックする。

スクリーンショット (81).png
23:再生アイコンをクリックすると、「Title」ファイルで記述された内容が実行される。

スクリーンショット (82).png
24:「Title」ファイルにはタイトル画面が記述されている。ここで「Scene1」か「Scene2」をクリックすると、それぞれのシーンファイルが読み込まれ、処理が切り替わる。

スクリーンショット (83).png
25:「Scene1」をクリックすると、「Scene1」ファイルが読み込まれ、四角形が自動で回転する。「Title]ボタンをクリックすると「Title]ファイルが読み込まれ、タイトル画面に戻る。

スクリーンショット (85).png
26:同じように「Scene2」をクリックすると、「Scene2」ファイルが読み込まれ、四角形をカーソルキーで回転させられる。「Title]ボタンをクリックすると「Title]ファイルが読み込まれ、タイトル画面に戻る。

スクリーンショット (91).png
27:Scene1とScene2をともにプレイしたら、錯視アンケートに回答しよう(URLはこちら

スクリーンショット (86).png
28:再生ボタンを再度押してプログラムを停止し、3つのシーンファイルをそれぞれ選択して、個別に再生してみよう。このようにUnityでは一つのプログラムを複数のシーンファイルに分割して作成し、必要に応じて読み込ませながら処理を進められる。通常、シーンファイルはステージやオプション画面のように、個別の処理ごとで作成される。

ワンポイントテクニック
スクリーンショット (87).png
29:Hierarchyのシーンファイル末尾に「*」が表示されている時は、エディタ上で何かを修正したまま、保存されていないことを示している。

スクリーンショット (89).png
30:「File」→「Save」で上書き保存すると、「*」が消える。何か作業をした場合は、適当なタイミングで忘れずに保存しておこう。

スクリーンショット (90).png
31:Unityを終了するには、「File」→「Exit」を選択する。

スクリーンショット (92).png
32:【14】で展開したフォルダを開くと、「Assets」「ProjectSettings」フォルダ以外に、さまざまなフォルダが作成されているのが分かる。そこで、「Assets」「ProjectSettings」フォルダ以外を削除する。

スクリーンショット (93).png
33:削除したところ。これ以外のフォルダやファイルを削除することで、保存を効率的に行える。

スクリーンショット (94).png
34:続いてファイルを右クリック→「送る」→「圧縮(Zip形式)フォルダー」を選択する。

スクリーンショット (95).png
35:圧縮フォルダができた。ここで圧縮フォルダだけをUSBメモリにコピーして、PCからまとめてを削除する。このようにフォルダを圧縮することで、より高速にUSBメモリにコピーできる。

スクリーンショット (100).png
36:最後にUnity Hubのメニューからサインアウトして終了しよう。

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

TypeLoadExceptionとの遭遇と対処

問題の概要

AdstirSDKを更新したら、TypeLoadExceptionエラーがでた。

原因(予想)

MigratePackages の実行中に動かなくなり、Unityを強制終了しちゃった。

詳細(手順)

1 : AdstirSDK の UnityPackageをimport(All Import)
2 : GoogleVersionHandler にて更新が確認されたので、全てApply
GoogleVersionHandler.png

3 : PackageManagerResolver にて更新が確認されたので GamePackageRegistry By Google を選んで AddSelectedRegistries
PackageManagerResolver.png

4 : MigratePackages にて更新が確認されたので、全てApply
MigratePackages.png
5 : 「手順4」Apply後の読み込みが2時間近く終わらなかったので、Unityを強制終了
6 : Unity再起動
7 : Unity起動時にTypeLoadException: Could not resolve type with token 01000036のエラーログが複数出るようになった。
 (Clearでエラーログは消えるが、不安)

対応

明らかに怪しいのは「詳細手順4」なので、下記のような対応を行った。
1 : 詳細手順1〜3を行う
2 : 詳細手順4が自動で表示されるので Canncel -> 現状をGitにPush
3 : MenuからAssets/ExternalDependencyManager/PackageManagerResolver/MigratePackagesを選択
4 : MigratePackages にて更新が確認されたので、全てApply
5 : 数分で処理が完了 -> TypeLoadException: Could not resolve type with token 01000036 のエラーが出る
 (おそらく、Migrateの途中でエラーが出ただけ)
6 : Unity再起動 -> 起動時にエラーが出現しなくなる

まとめ

UnityPackageのImport作業途中で落ちたり、落としたりして異常が発生した場合は
作業を区切って少しずつ進めると良いかもしれませんね。

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

Unity LineRendererでシェーダーを用いて点線を描画する

概要

以下のように丸を並べた点線をLineRendererで描画します。ついでにアニメーションもつけました。
dotted-line.gif

プロジェクトのソースはこちら
https://github.com/Arihide/unity-dotted-line

解説

LineRendererをアタッチする

まず、適当なGameObjectにLineRendererをアタッチします。
その後、下のように[Texture Mode]を[Tile]に設定します。
スクリーンショット_2020-10-12_0_03_03.png

シェーダーを書く

次に、LineRendererに設定する点線のマテリアルのためのシェーダーを書いていきます。

1.丸を並べる

まずは下図のように、丸を隙間なく敷き詰めるLineRenderer用のシェーダーを書きます。
スクリーンショット 2020-10-12 0.24.09.png

どのようなロジックでこれを実現するかというと、
先程のTextureMode:Tileの設定によって、以下のようなUV座標になるので、
dotted-line.png
以下のように0...1になるように座標を変更したあと、
dotted-line2.png
中心:(0.5, 0.5)、半径:0.5 の円を考えて、内側は不透明、外側は透明になるように描画してあげればよいです。
それを踏まえたシェーダーのコードは以下になります。

Shader "Custom/DottedLine"
{
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                half2 texcoord : TEXCOORD0;
                half4 vertex : POSITION;
                fixed4 color : COLOR0;
            };

            struct v2f
            {
                half2 uv : TEXCOORD0;
                half4 pos : SV_POSITION;
                fixed4 color : COLOR0;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                o.color = v.color;
                return o;
            }

            fixed4 frag (v2f i) : SV_TARGET
            {
                // 1の剰余をとることで、0と1の間を繰り返すようにする
                i.uv.x = i.uv.x % 1;

                fixed4 col = i.color;

                // 円の内側を不透明、外側を透明にする
                half s = length(i.uv - half2(1, 1) * 0.5);
                col.a = saturate((0.5 - s) * 100);

                return col;
            }
            ENDCG
        }
    }
}

上記のシェーダーを記述後、マテリアルを作成しLineRendererのマテリアルにアタッチすると、はじめの図のように線に沿って丸が描画されると思います。

ここで、以下のコード部分が若干複雑なので補足します。

// 円の内側を不透明、外側を透明にする
half s = length(i.uv - half2(1, 1) * 0.5);
col.a = saturate((0.5 - s) * 100);

この関数をプロットすると以下のようになります。(xy平面がそれぞれUV、z軸はアルファ値)
geogebra-export.png

図を見てもらうとわかるように、円柱ではなく円錐台になっています。
このようにすることによって、円の境界線をぼかしてきれいに描画できるようになります。

円の隙間を開ける

隙間が詰まりすぎていて気になるので、次は間隔を少し開けてみます。
スクリーンショット 2020-10-12 1.54.10.png
これは以下のように、_Spaceという変数を用意して、剰余と円の中心をずらせば実現できます。

Shader "Custom/DottedLine"
{
    Properties
    {
        _Space ("Space Between Dots", Range(1, 5)) = 1.2
    }
    SubShader
    {
        //...(中略)

            half _Space;

            fixed4 frag (v2f i) : SV_TARGET
            {
                i.uv.x = i.uv.x % _Space;

                fixed4 col = i.color;

                // 円の内側を不透明、外側を透明にする
                half s = length(i.uv - half2(_Space, 1) * 0.5);
                col.a = saturate((0.5 - s) * 100);

                return col;
            }
            ENDCG
        }
    }
}

変更後、マテリアルから[Space Between Dots]の値を調節することで隙間があくのを確認できます。

アニメーションさせる

これで完成でもよいのですが、せっかくなので冒頭のGifのように時間経過によって丸が動くようなアニメーションもつけたいと思います。これはとても簡単で、frag関数冒頭を

i.uv.x = (i.uv.x + _Time * 50) % _Space;

と置き換えることで実現できます。見ていただけばわかるように時間ごとに座標をずらしています。

まとめ

以上、LineRendererのシェーダーで点線を描画する方法について説明しました。
シェーダーを工夫すれば、円ではなく楕円などの点線にすることもできると思うので、色々試してみるのも面白いかもしれません。

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

UnityとFirebaseでストリートビューっぽいの作る

成果物

PCブラウザで実行してる動画

iPhoneのSafariから実行

この記事の趣旨

  1. Unityで簡単にWebGLアプリをビルドできる
  2. Firebase Hostingで簡単にWebGLアプリを公開できる
  3. しかも無料(※制限あり)

WebGLって何??

ブラウザ上で2Dとか3Dをグリグリいじれるスゴイやつ

JavaScriptライブラリだとthree.jsなどが有名
↓サンプル見るだけで楽しい
https://threejs.org/

Unityの3DプロジェクトなんかもWebGL(HTML5 + JavaScript)でビルドできる

※ただしモバイル端末は未サポートなので注意(サポートしてないだけで割と動く)

Unity WebGL コンテンツは現在モバイル端末ではサポートされていないことに注意してください一部の機器、特にハイエンドなものでは動く場合もありますが、現在の大抵の端末は性能不足で Unity WebGL を十分に動かすだけのメモリがありません

参考:WebGL のブラウザー間での互換性

UnityでWebGLを利用できるようにする

Unityインストール時に以下の項目をチェックする
・WebGL Build Support

既にUnityをインストールしている場合は、以下の手順でモジュールの確認・追加が可能
参考:Unityにモジュールを後から追加する方法

Unityでプロジェクトを作成

クリックで展開:point_down:

3Dプロジェクトで作業を進めます
1. 3Dビューオブジェクトの準備

まずは有志(warapuri氏)が作成した以下ファイルをダウンロードしてください
* Sphere100.fbx

参考:UnityとOculusで360度パノラマ全天周動画を見る方法【無料編】

①UnityのProjectウィンドウへドラッグ&ドロップでインポート
②それをHierarchyウィンドウへドラッグ&ドロップ
1.PNG

2. 360度写真の準備

以下のサイトなどで360度写真をダウンロードできます
360cities.net

スマホカメラでも『Googleストリートビュー』アプリなどで撮影することができるようです

今回は購入後一度だけ使用して物置きに放置されたGoPro MAXで撮影しました

3. 画像をオブジェクトにセット

①画像を「Resources/Images」フォルダへインポート
②オブジェクトに画像をセット
2.PNG
③画像のMax Sizeを変更(小さいと画像が荒くなる)
4.PNG
HierarchyウィンドウからSphere100を選択し、
④InspectorウィンドウからScaleを全て100に、
⑤ShaderをUnlit/Textureに、
⑥写真が左右反転している場合はTillngのXを-1に変更
3.PNG
⑦Shere100オブジェクトにCanvasをアタッチして、
⑧Projectウィンドウへドラッグ&ドロップでPrefab化
5.PNG
ボタンもいい感じに作ってPrefab化して、
「JumpButton」という名前でResources/Prefabsフォルダへ配置

Prefab化したオブジェクトはHierarchyから削除しておく

4. カメラ制御用のスクリプト

以下のサイトから拝借
Unity:マウスドラッグでカメラを回転して視点を操作するスクリプト

マウスホイールでズームイン/ズームアウトできるようUpdate関数に追記

CameraRotater.cs
    private float scroll;
    private float view;

    void Update()
    {
        scroll = Input.GetAxis("Mouse ScrollWheel");
        view = mainCamera.fieldOfView - scroll * 50;

        mainCamera.fieldOfView = Mathf.Clamp(value: view, min: 30f, max: 90f);

        /** 省略 **/
5. 移動時のカメラ演出用スクリプト

移動するときのビヨ~ン感を出したい
以下のサイトを参考にカメラにブラーを追加する
【Unity】【シェーダ】Radial Blur(放射状ブラー)のポストエフェクトを実装する

初期値は以下にしておく
・Sample Count : 16
・Strength : 0

外から変数を変更できるようスクリプトに以下を追記

RadialBlur.cs
    public void SetStrength(float _strength)
    {
        this._strength = _strength;
    }
}
6. 写真の位置情報を作成

写真のそれぞれのid, xy座標, 移動先のidを設定
これを元に移動ボタンを作成します
9.PNG
これをCSVファイルにしてResourcesディレクトリに配置

CSVに対応したクラスを作成

public class PhotoPosition
{
    public int id;
    public float x;
    public float y;
    public int[] jumpTo; 
}

CSVをクラスに変換してくれる無料アセットをインポート
CSV Serialize

7. メインスクリプトの作成

クリックで展開:point_down:

以下のスクリプトを作成し、適当なオブジェクトにアタッチ
CreateSphereController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;

public class CreateSphereController : MonoBehaviour
{
    // 写真の位置情報リスト
    private List<PhotoPosition> photoPositions;
    // 写真のオブジェクト一覧
    private Object[] images;

    // 3Dビューインスタンス一覧
    private List<GameObject> spheres;
    // 3Dビューのプレハブ
    private GameObject spherePrefab;
    // 移動ボタンプレハブ
    private GameObject buttonPrefab;
    // 移動時のカメラのブラースクリプト
    private RadialBlur radialBlurScript;

    // カメラのブラーの強さ
    float blurStrength;
    // カメラのブラー処理用フラグ
    bool isUpStrength;
    bool isDownStrength;

    void Start()
    {
        spheres = new List<GameObject>();
        // Resourcesフォルダのposition.csvを取得
        TextAsset csvFile = Resources.Load("position") as TextAsset;
        photoPositions = new List<PhotoPosition>();

        // CSVから写真の位置情報をオブジェクトリストに変換
        photoPositions.AddRange(CSVSerializer.Deserialize<PhotoPosition>(csvFile.text));

        // id=1の写真を初期値に設定
        PhotoPosition photoPosition = photoPositions.Find(n => n.id == 1);

        // プレハブ取得
        spherePrefab = (GameObject)Resources.Load("Prefabs/Sphere100");
        buttonPrefab = (GameObject)Resources.Load("Prefabs/JumpButton");
        // Imagesフォルダ配下をすべて取得
        images = Resources.LoadAll("Images", typeof(Texture));

        // メインカメラのブラースクリプトを取得
        GameObject mainCamera = Camera.main.gameObject;
        radialBlurScript = mainCamera.GetComponent<RadialBlur>();

        // ID=1の写真で3Dビューオブジェクト生成
        spheres.Add(CreateNextSphere(1));
    }

    // 3Dビューオブジェクトを生成
    GameObject CreateNextSphere(int nextPositionId)
    {
        // IDから写真の位置情報を取得
        PhotoPosition nextPosition = photoPositions.Find(n => n.id == nextPositionId);
        // 3Dビューのインスタンス生成
        GameObject nextSphere = Instantiate(spherePrefab, new Vector3(0.0f, 0.0f, 0.0f), Quaternion.identity);

        // 3Dビューオブジェクトのマテリアルを取得
        Material material = nextSphere.GetComponent<Renderer>().material;
        // 写真をテクスチャに設定
        material.SetTexture("_MainTex", (Texture)images[nextPosition.id - 1]);

        // 移動用ボタンを生成
        foreach (int jumpToId in nextPosition.jumpTo)
        {
            // 移動先の写真情報を取得
            PhotoPosition jumpToPosition = photoPositions.Find(n => n.id == jumpToId);
            // 移動用ボタンのインスタンスをCanvas配下に生成
            GameObject jumpButton = Instantiate(buttonPrefab, new Vector3(0.0f, -3.0f, 0.0f), new Quaternion(0.0f, 0.0f, 0.0f, 0.0f), nextSphere.transform.Find("Canvas"));
            // ボタンクリック時のイベントを追加
            jumpButton.GetComponent<Button>().onClick.AddListener(() => OnClickButton(jumpToId));

            // 次の写真のxyベクトル
            Vector2 nextVector = new Vector2(nextPosition.x, nextPosition.y);
            // 移動先の写真のxyベクトル
            Vector2 jumpToVector = new Vector2(jumpToPosition.x, jumpToPosition.y);

            // ベクトルから角度を計算
            Vector2 dt = jumpToVector - nextVector;
            float radian = Mathf.Atan2(dt.y, dt.x);
            float degree = radian * Mathf.Rad2Deg;

            // ボタンの向き、位置を設定
            jumpButton.transform.Rotate(0.0f, 0.0f, degree);
            jumpButton.transform.localPosition = new Vector2(-5 * Mathf.Cos(radian), -5 * Mathf.Sin(radian));
        }

        // 3Dビューのインスタンスを返す
        return nextSphere;
    }

    // ボタンクリック
    void OnClickButton(int id)
    {
        // 3Dビューインスタンスを追加
        spheres.Add(CreateNextSphere(id));
        // カメラのブラー処理開始
        isUpStrength = true;
    }

    // Update is called once per frame
    void Update()
    {
        // カメラのブラー処理を強める
        if (isUpStrength)
        {
            ChangeBlurStrength(true);
        }
        // カメラのブラー処理を弱める
        else if (isDownStrength)
        {
            ChangeBlurStrength(false);
        }
    }

    // カメラのブラー処理
    void ChangeBlurStrength(bool isUpFlg)
    {
        // 強める
        if (isUpFlg)
        {
            blurStrength += 0.05f;
            // 一番強まったら
            if (blurStrength >= 1)
            {
                // 強めるの終了
                isUpStrength = false;
                // 弱めるの開始
                isDownStrength = true;

                // 古い方の3Dビュー削除
                Destroy(spheres[0]);
                spheres.RemoveAt(0);
            }
        // 弱める
        } else
        {
            blurStrength -= 0.05f;
            // 弱まりきったら
            if(blurStrength <= 0)
            {
                // 弱めるの終了
                isDownStrength = false;
                // 誤差が生じるから明示的に0を指定
                blurStrength = 0;
            }
        }
        // ブラーの強さ設定
        radialBlurScript.SetStrength(blurStrength);
    }
}

WebGLアプリをビルド

Build SettingsからWebGLを選択してBuildするだけ!
7.PNG

Firebaseの設定

1. Firebaseでプロジェクト作成

FirebaseにGoogleアカウントでログイン

「プロジェクトを追加」ボタンを選択し、
プロジェクト名などを入力して作成

2. PCにFirebaseをインストール

Firebase CLIをインストール

npm install -g firebase-tools
3. Firebaseプロジェクトの初期化

まずはFirebaseへログイン

$ firebase login

Firebaseプロジェクトの初期化

$ firebase init

以下の選択肢はHostingを指定

? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confi
rm your choices.
 ( ) Database: Deploy Firebase Realtime Database Rules
 ( ) Firestore: Deploy rules and create indexes for Firestore
 ( ) Functions: Configure and deploy Cloud Functions
>(*) Hosting: Configure and deploy Firebase Hosting sites
 ( ) Storage: Deploy Cloud Storage security rules
 ( ) Emulators: Set up local emulators for Firebase features
 ( ) Remote Config: Get, deploy, and rollback configurations for Remote Config      

selectオプションは「Use an existing project」を選択

? Please select an option:
> Use an existing project
  Create a new project
  Add Firebase to an existing Google Cloud Platform project
  Don't set up a default project    

自分のプロジェクト一覧が表示されるので、先程作成したプロジェクトを選択

あとはエンター連打でOK!

4. WebGLアプリをデプロイ

作成されたpublicフォルダに、ビルドしたWebGLアプリ(以下ファイル)を配置
・index.html
・Build
・TemplateData

Firebaseへデプロイ

$ firebase deploy
5. ブラウザで表示

完了メッセージに表示されたURLへアクセスするだけ
簡単!

まとめ

WebGLアプリのビルドから公開までが簡単にできました。

せっかくUnityでアプリを作れても、AppStoreやGoogle Playに登録するのって結構大変なんですよね。

WebGLビルドを利用すれば、本記事のFirebase Hostingや、unityroomなどのサイトで簡単に公開できるのでオススメです!

ちなみに撮影した写真は、北海道の美幌峠から望む屈斜路湖でした。

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