20200927のUnityに関する記事は5件です。

Unity LearnのCreate with Codeの出来が良い

前書き

一応、エンジニア的には業務系のシステムを主にやってきたのですが、スキルの幅を広げるためにUnityに手を出してみました。
学習用コンテンツというのは、各サービスで力を入れているとは思いますが、アカウント登録のみの無料で利用できる内容としては非常によくできていると思ったので、簡単にご紹介です。
内容について詳細な解説はしていませんので、悪しからず。

参照先

Unity Learn
Unity Learn - Create with Code
Unity

概要

Unity Editer上でのゲーム作成を通してプログラミングの基本を学べる内容。
全体を通して行うと36.5時間と非常に長いのですが、主に解説動画の視聴なので作業としての時間はそんなに長くありません。

おススメな点

  • プログラム未経験者でも独学で進めれられる内容。
    • 難易度としてさほど高くなく(おそらくターゲットとしては小中学生)、コードを記述する量も多くない。
    • 数分~10分程度の動画視聴後、すぐに説明内容を実装する⇒動作確認する、という流れが良くモチベーションを保ちやすい。
  • 理解できなくてもそのまま書けば動くものができる。
    • もちろん、理解できた上で動かせているのが理想ですが、ひとまずは動くものを作って、いろいろ動かしているうちに理解する、という方法も「あり」だと思うので。
  • 3Dで動くものができる。
    • 往年のBASICプログラマーとしてはLOCATEとPRINTでCUIでゴリゴリ書いた時代が懐かしいのですが、簡単なベクトルで立体が動くと楽しいです。
    • 説明動画内で使っていないアセット(要するにゲームを構成する部品)も用意されているので、ちょっとした変更でオリジナル感がだせる。
    • 使用するアセットは低ポリゴンのものがほとんどなので、低スペックPCでもある程度いけそう。
    • 低ポリゴンでもちゃんとモーションが付いている。

少し残念な点

  • 基本的に英語の内容のみ。
    • とはいえブラウザの翻訳機能を使えば大筋は理解可能と思います。
    • 説明動画はほとんど英語のキャプションが付いているのですが、キャプションがデフォルトでONになっている動画となっていない動画がある。
    • 動画内でかなり具体的に説明しているので、動画の内容が理解できていないと難易度が上がる。
  • 総量が多い。
    • 一通りの事を盛り込むとある程度の量になってしまうのは仕方がないですが。
    • 単純計算で、毎週末1日使って約1カ月かけてじっくりやる、程度の気構えがあった方が良い。
    • 内容のうち「Prototype」と「Quiz」だけに絞ればだいぶサクサク進められますが、習熟度を高めるために「Challenge」はやったほうが良い。
    • 「Lab」の位置付けが微妙。コンセプトデザインから入るので、デザインをどう実装していくか(プロトタイピング)というお手本にはなる。ので知って損はないのですが、初心者向けとしてはなくてもいいと思える内容。

気づいた点

  • Visual Studio Community よりVisual Studio Codeを使う方が動作が軽くなるので良い。

    • Unityバージョン2020.1ではメニューから「編集」⇒「環境設定」⇒「外部ツール」から「外部のスクリプトエディター」に「Visual Studio Code」を選択すればO.K. unity_preferences.png
    • Visual Studio Code側に「C#」拡張機能を追加しておくと入力候補もある程度きちんと出るので便利。 vscode_CSharp.png
  • 推奨Unityバージョンが2018.4(LTS)系と少し古いのですが、2020.1系でもアセットはそのままインポートできる。

    • アセットをプロジェクトにインポート後は Unity_PackageManager_MyAsset.png
    • コンソールにエラーがたくさん出ますが、 Unity_Console_1.png
    • パッケージマネージャーで「In Project」に入っているパッケージを全部最新化して(パッケージ名の右側に上矢印があるものは新しいバージョンがある)から、 Unity_PackageManager_InProject.png
    • Unity Editerを一旦閉じて、開きなおしてから一度実行すると、大体エラーはなくなる。 Unity_Console_NoError.png
    • 実行不可となるエラーが残るようなら、エラーメッセージを元に対処。エラーメッセージを元にGoogleで検索して対処します。

後書き

出回ってるツールの公式コンテンツってのは、お勧め機能や最新機能に寄ったものが多いと感じていたのですが、こういった初心者向けのコンテンツもあるんだな、というのはいい発見でした。
公式コンテンツがこれだけのクオリティだと、外部からやれることも減るんじゃないかという気もしますが、いいコンテンツが増えると独学でできることも増えるので、個人的にはどんどんやってほしいですね。

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

GitHub Desktopでのローカルリポジトリの作成でエラー

【GitHub Desktopでのローカルリポジトリの作成でエラー】

①GitHub Desktopを起動

②Git管理したいフォルダをGitHub Desktopに追加。フォルダ をGitHub Desktopへドラッグ&ドロップ。

③Add Local repositoryウィンドウが表示されるので、Create a repositoryをクリック。
クリックミスで、下の青いボタンのAdd repositoryを押してしまった。

【解決方法】
①ローカルリポジトリが対象よりもかなり広い範囲をリポジトリとしてしまっていたので、一度リポジトリの設定を消して作り直した方がよい。
.android というフォルダの一つ上のフォルダを突き止めて、そこから .git という隠しフォルダを削除することでリポジトリの設定を消す。

②.android というフォルダを探すためには、左のファイル一覧から適当なファイルを右クリックして "Show in Explorer" を選べばその場所が Explorer で開かれるので、そこからたどる。

④.android というフォルダの一つ上のフォルダに .git という隠しフォルダがある。隠しフォルダを見えるようにするにはこちら https://www.google.com/search?q=windows+%E9%9A%A0%E3%81%97%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80+%E8%A1%A8%E7%A4%BA を参照する。

⑤.git という隠しフォルダを見つけたら、それを削除するとファイルに影響を与えずにリポジトリの設定を消せる。これでもうリポジトリではなくなる。
あとは、正しいフォルダをもう一度ドラッグアンドドロップして Create a repository すればできる。

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

Update your C# in Unity ~ ローカル関数 ~

Unityにおいて古いC#しか使えない時代もありました。しかし、それは過去のことです。本稿執筆時の最新LTSであるUnity 2019.4ではC# 7.3がサポートされています。また、本稿執筆時の最新Beta版であるUnity 2020.2ではC# 8.0がサポート予定です。

長らくUnityで古いC#しか使えなかったことで、「C#にこんな機能あるのか?知らなかった!」となることがある方も多いのではないでしょうか?この「Update your C# in Unity」シリーズでは、「C#の比較的新しい機能をUnityでこんな風に使えるよ!」という紹介を行います。


言語機能名: ローカル関数
追加バージョン: C# 7.0でローカル関数、C# 8.0で静的ローカル関数
説明: 関数を他の関数の中に入れ子にし、定義できる


ローカル関数を使うことで、関数の中に入れ子で関数を定義することができます。

private関数はその型のメンバーからは呼び出すことができます。一方でローカル関数は、その関数の中でしか呼び出せない、より狭いスコープの関数です。スコープを非常に狭めたく、かつ処理に名前をつけたい場合、ローカル関数を検討してください。


ローカル関数の利用例はLINQライクな関数の実装です。

次のコードはLINQライクなMapメソッドの実装の、よくない例です。仮引数であるsourceやpredicateがnullの場合、関数呼び出しのタイミングでArgumentNullExceptionが投げられることを期待したいところです。しかし、この実装だと返り値の要素を、最初に列挙するタイミングまでArgumentNullException投げられません。これにより、実行時の思わぬ不具合の原因になってしまうことがあります。

public static class MyEnumerable
{
        public static IEnumerable<TResult> Map<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource,TResult> selector)
        {
            if (source == null)
                throw new ArgumentNullException ("source");
            if (selector == null)
                throw new ArgumentNullException ("predicate");

            foreach (TSource element in source) {
                yield return selector (element);
            }
        }
    }
}

関数呼び出しのタイミングでArgumentNullExceptionが投げられることするためには、次のように二つの関数に分割する必要があります。

public static IEnumerable<TResult> Map<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource,TResult> selector)
{
    if (source == null)
        throw new ArgumentNullException ("source");
    if (selector == null)
        throw new ArgumentNullException ("selector");

    return source.Map_ (selector);
}

private static IEnumerable<TResult> Map_<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource,TResult> selector)
{
    foreach (TSource element in source) {
        yield return selector (element);
    }
}

これで期待通り関数呼び出しのタイミングでArgumentNullExceptionが投げられます。しかし、Mapからしか呼ばないMap_ができてしまいました。
これはローカル関数を利用することで、次にように改善することができます。

public static IEnumerable<TResult> Map<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource,TResult> selector)
{
    if (source == null)
        throw new ArgumentNullException ("source");
    if (selector == null)
        throw new ArgumentNullException ("selector");

    return Impl (source, selector);

    IEnumerable<TResult> Impl(IEnumerable<TSource> source_, Func<TSource,TResult> selector_)
    {
        foreach (TSource element in source_) {
            yield return selector_ (element);
        }
    }
}

次のように、ローカル関数から外側の関数の変数をキャプチャすることもできます。

public static IEnumerable<TResult> Map<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource,TResult> selector)
{
    if (source == null)
        throw new ArgumentNullException ("source");
    if (selector == null)
        throw new ArgumentNullException ("selector");

    return Impl ();

    // 外側の関数の引数や変数をキャプチャできる
    IEnumerable<TResult> Impl ()
    {
        foreach (TSource element in source) {
            yield return selector (element);
        }
    }
}

ローカル関数から外側の関数の変数をキャプチャすることが必要な場合や便利な場合もあります。
しかし、うっかり意図と違うキャプチャをしてしまい不具合の原因になることがあります。

これを解決するために、C# 8.0から静的ローカル関数が加わりました。
静的なローカル関数では、外側の関数の変数をキャプチャするとコンパイルエラーになります。
これにより、意図しない外側の関数の変数のキャプチャを防ぐことができます。
static修飾子をローカル関数につけることで静的なローカル関数になります。

public static IEnumerable<TResult> Map<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource,TResult> selector)
{
    if (source == null)
        throw new ArgumentNullException ("source");
    if (selector == null)
        throw new ArgumentNullException ("selector");

    return Impl (source, selector);

    // C# 8.0から使える
    // staticがついていると静的ローカル関数
    // 外側の関数の引数や変数のキャプチャを許さない
    static IEnumerable<TResult> Impl(IEnumerable<TSource> source_, Func<TSource,TResult> selector_)
    {
        foreach (TSource element in source_) {
            yield return selector_ (element);
        }
    }
}

Unityでの利用例をあげます。

次のように、IEumeratorを返すLaunchImpl関数と、それを内部で呼び出しCoroutineを返すLaunch関数を定義していたとします。IEnumeratorを返すLaunchImpl関数は、Coroutineを返すLaunch関数からしか利用していません。StartCoroutineの仕様上、このように二つの関数を分離する必要があります。

using System.Collections;
using UnityEngine;

public class Launcher : MonoBehaviour
{
    public Coroutine Launch()
    {
        return StartCoroutine(LaunchImpl());
    }

    private IEnumerator LaunchImpl()
    {
        // 略
        yield break;
    }
}

これはローカル関数を使い次のように定義することもできます。

public class Launcher : MonoBehaviour
{
    public Coroutine Launch()
    {
        return StartCoroutine(LaunchImpl());

        static IEnumerator LaunchImpl()
        {
            // 略
            yield break;
        }
    }
}

ローカル関数を使うことで、関数のスコープと可視性を関数内のスコープだけに制限することができます。
private関数より狭いスコープで定義することができます。
スコープを非常に狭めたく、かつ処理に名前をつかたい場合、ローカル関数を検討してください。

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

Unityでステータスバーとナビゲーションバーを表示する

環境

  • Unity 2019.4.1f1
  • AQUOS sense3

UIのPanelとTextを張り付けただけのシーン。Textは-90度回転させており、「a~z」と「0~1」までの文字を並べてビューの上から下まで表示。コンテンツがどのような影響を受けるか確認した。(ナビゲーションバーの調査から、位置を左に変更しているが気にしないでください)

ステータスバーを表示する

参考記事:UnityでAndroidのステータスバーを表示するコードのAndorid10対応版

  • コンテンツに重なるようにステータスバーが表示される
  • ステータスバーは透明
  • ナビゲーションバーは表示されておらず、下からスワイプすると表示される(この画像で表示されているのは、スクリーンショットを撮ったときに自動表示されたため)

ナビゲーションバーを表示する

実行開始時に次のようなスクリプトを実行する。上記のステータスバー表示も同時にスクリプトに組み込んでいる。

void Start()
{
    // ナビゲーションバー表示
    Screen.fullScreen = false;
    // ステータスバー表示
    StatusBarController.Show();
}
  • この方法だと、ステータスバーが半透明にならない
  • 上部のコンテンツが見切れている(ステータスバーの高さ分、コンテンツが上にずれた感じ?)

  • ステータスバーを表示するロジックを外すとステータスバーが表示されなくなる

ナビゲーションバーを表示させたまま、ステータスバーを半透明

参考記事:【Unity】Unity 5.3以降でAndroidのStatus Barを表示する方法
ステータスバー表示のロジック(最初の記事にあったもの)を次のように変更

    public static int FLAG_FORCE_NOT_FULLSCREEN = 2048;
    public static int FLAG_LAYOUT_IN_SCREEN = 256;
    private static int WINDOW_FLAG_TRANSLUCENT_STATUS = 0x04000000;

    public static void Show()
    {
#if !UNITY_EDITOR && UNITY_ANDROID
        //ChangeFlags(FLAG_FULLSCREEN,FLAG_FORCE_NOT_FULLSCREEN);
        ChangeFlags(FLAG_FULLSCREEN,FLAG_FORCE_NOT_FULLSCREEN | FLAG_LAYOUT_IN_SCREEN | WINDOW_FLAG_TRANSLUCENT_STATUS);
#endif
    }

ナビゲーションバーを表示させたまま、ステータスバーを透明にする

  • 参考:setStatusBarColor
  • 上記の半透明のやり方(WINDOW_FLAG_TRANSLUCENT_STATUS)ではなく、setStatusBarColor関数を利用すると、透明や色をつけられる
  • WINDOW_FLAG_TRANSLUCENT_STATUSと一緒に使えないので、ステータスバーの処理は元に戻す
   public static void Show()
    {
#if !UNITY_EDITOR && UNITY_ANDROID
        ChangeFlags(FLAG_FULLSCREEN,FLAG_FORCE_NOT_FULLSCREEN);
#endif
    }
  • setStatusBarColorを利用する
  • COLOR値は、透明度(00~FF)、赤(00~FF)、緑(00~FF)、青(00~FF)だと思われる
  • 以下は完全透明
    private const uint DEFAULT_BACKGROUND_COLOR = 0x00000000;

    private static void RunOnUiThread()
    {
        using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                using (var window = activity.Call<AndroidJavaObject>("getWindow"))
                {
                    window.Call("clearFlags", clearStatusBarFlag);
                    window.Call("addFlags", addStatusBarFlag);
                    window.Call("setStatusBarColor", unchecked((int)_statusBarColor));
                }
            }
        }
    }

  • ちなみに0xFF000000にしたところ、黒でステータスバーが表示された
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NrealSDK1.3.0のInput-Interactionシーンを観察してみる(Inputシーン編2/3)

はじめに

NrealSDK 1.3.0にあるInput-Interactionシーンを観察していきます。

Inputのサンプルシーンは3つあるので、本記事は(2/3)としています
もし間違いがあれば、指摘いただければ幸いです。

【別のInputシーン編記事はこちら】
NrealSDK1.3.0のInput-ControllerInfoシーンを観察してみる(Inputシーン編1/3)

Input-Interactionシーンについて

Nrealのコントローラーのクリック、ポインターのRay判定などのサンプル
「Active True」「Active False」でCubeの表示非表示を行い、
ポインターをCubeのコライダーに当てると、Cubeが緑色になる。外すと、白色になる。

下記画像はUnityEditorで実行時のスクリーンショット

シーン構成

Left align
NRCameraRig
NRInput
Cube
Canvas
SimpleControllerVibration
Directional Light

NRCameraRig、NRInput

Nrealに対応したカメラ、入力システム
別のサンプルシーンで観察してます。
NrealSDK1.3.0のHelloMRシーンを観察してみる

Cube

スクリプト名 役割
CubeInteractiveTest MonoBehaviourを継承、IPointerClickHandler, IPointerEnterHandler, IPointerExitHandlerの計3種類インターフェースを実装し、Cubeにポインターが「触れた」、「離れた」、「クリックした」際の処理を記述している

Canvas

ActiveTrue,Falseボタン、InputFieldをもつCanvas
RenderModeはWorldSpaceになっており、カメラからZ:3に配置されている。
カメラに追従しない系Canvas。
(カメラに追従する系Canvasは、NRCameraRig>CenterCamera直下にWorldSpaceで配置すればできる)
実装するなら、HololensのUIのように一定距離離れるとじんわり付いてくるCanvasを作りたいですね。

スクリプト名 役割
CanvasRaycastTarget Canvasの子UIにRayを当てるためのもの。アタッチされていないと、RayでUIを触れることができない

ignoreReversedGraphics
レイキャスターから反対方向を向いている場合も考慮するかどうか。

SimpleControllerVibration

スクリプト名 役割
SimpleControllerVibration コントローラーのボタン押下時、コントローラーを振動させるものだと思われる。

Nreal Developer Kitで確認した時は、振動がなかった気がする。 
Nreal公式の製品仕様を見た限り、振動するものはないが、Android端末は振動するのか??(スマホは未確認)

vibrationTime
振動時間。デフォルトは0.06。

Directional Light

Unity標準のライト。

まとめ

オブジェクト、UIへの入力方法も理解できました。
やはり目の前のオブジェクトの色が変化したりするのは見ていて楽しいです。
(ちなみにInputFieldの役割は不明です、、)

さいごに

Androidにすれば、振動や入力用キーボード表示などできたりするのでしょうかね。
開発するにしてもテスト等々DeveloperDeveloper Kitがメインになると思うので、
出来ることをはっきりしていきたいです。
これからもNrealに関する記事を投稿していきたいと思います。

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