20200223のUnityに関する記事は8件です。

【Unity】Unityの環境構築をしてみた ~Unity プロジェクトの作成まで~

0. はじめに

最近、強化学習について勉強をはじめました。
できたらかなり面白そうですよね!
僕は、YouTuber こーじ さんにかなりハマってます。発想から実装まで全て面白いです。
ぜひチャンネル登録してみてください!

今回はこーじさんが Youtube で Unity の環境構築について動画化されてたので、僕もやってみました。

1. 概要

この動画では、
1. Unity をインストール
2. 自分のプロジェクトを作成
3. 強化学習のライブラリ(ML-Agents)をダウンロード
4. 必要なものを自分のプロジェクトに移す
5. brew をインストール
6. brew で pyenvをインストール
7. pyenv で anaconda をインストール
8. anaconda で python の仮想環境を作成
9. 仮想環境内に mlagents をインストール

の手順で紹介されています。

ちなみに、僕のPCのスペックは、

image.png

こんな感じです。
こーじさんは Mojave ですが、僕は Catalina なのでその辺でシェルとかの違いが出てきそうですね。

参考:Catalinaでデフォルトシェルが「zsh」に変わる、bashとの違いは?

2. Unity のインストール

2.1. Unity Hub のダウンロード

Unityをダウンロードから Unity Hubをダウンロードします。

ダウンロードファイルを開きます。

image.png

をAgreeします。

mac特有のアイコンを Application にドロップするやつをして、Finderとかから Unity Hub を起動します。
すると、

image.png

これが出てきます。これで Unity Hub が使えます。

2.2. Unity Hub のサインイン・ライセンス認証

右上の人のアイコンをクリックして、サインインに進みます。

image.png

サインインした後、ライセンスを認証すると、

image.png

までいけます。僕は趣味範囲での利用なので、Personal で登録しました。

【注意点!!】

ここで、アカウントのユーザーを日本語にしていると後の工程でエラーが起きるみたいです。
ローマ字(英語)に書き換えておきましょう。

2.3. Unityエディターのインストール先の指定

右上の歯車アイコンから、一般に入るとこんな画面が出てきます。

image.png

ここでインストール先を指定してあげます。

2.3. Unity のインストール

こーじさんは Unity 2019.2.21f1 を使ってますが、僕は Unity 2019.3.2f1 にします。

image.png

次へで進んで、
モジュールをインストールに加えるのところでは、
- Visual Studio for Mac
- Linux Build Support(Mono)
- Mac Build Support(IL2CPP)
- Documentation
- 日本語

にチェックを付けました。

先に進んでインストールを実行します。
これはかなり時間かかります。
まじで時間かかります。

image.png

気長に待って...

image.png

インストール完了!

3. 新しい Unity プロジェクトの作成

image.png

ここに、プロジェクト名と保存先を指定して、新しい Unity プロジェクトを作成します。
今回は3Dのプロジェクトを作成しました。

作成ボタンを押すと新しいプロジェクトができます。

プロジェクトを起動しようとしても、
「パスが存在しません」みたいに怒られた場合は、もう一度上記の2.3.のインストール先の指定が正しくできているか確認してください。

プロジェクトを起動すると、

image.png

でーん。
灰色のやつ!

続きはまた次回。

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

HDRP用のポストエフェクトを書く

HDRPでは、ポストエフェクトはPost-processing Stack v2ではなく、Volumeに統合されています。本記事ではVolumeにカスタムポストエフェクトを追加する方法をまとめます。
内容は公式ドキュメントに基づいているので、そちらもあわせてどうぞ。

1. 必要なファイルを作る

カスタムポストエフェクトを書くには、以下の二つのファイルを作成します。

  • CustomPostProcessVolumeComponentとIPostProcessComponentを継承したクラス
    • Projectウィンドウで右クリック > Create > Rendering > C# Post Process Volumeで作成
  • 実際に処理を行うシェーダー(HLSL)
    • Projectウィンドウで右クリック > Create > Shader > HDRP > Post Processで作成

2. スクリプトを書く

作成したC# スクリプトを編集します。

GrayScale.cs
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using System;

[Serializable, VolumeComponentMenu("Post-processing/Custom/GrayScale")]
public sealed class GrayScale : CustomPostProcessVolumeComponent, IPostProcessComponent
{
    [Tooltip("Controls the intensity of the effect.")]
    public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f);

    Material m_Material;

    public bool IsActive() => m_Material != null && intensity.value > 0f;

    public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;

    public override void Setup()
    {
        if (Shader.Find("Hidden/Shader/GrayScale") != null)
            m_Material = new Material(Shader.Find("Hidden/Shader/GrayScale"));
    }

    public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination)
    {
        if (m_Material == null)
            return;

        m_Material.SetFloat("_Intensity", intensity.value);
        m_Material.SetTexture("_InputTexture", source);

        HDUtils.DrawFullScreen(cmd, m_Material, destination);
    }

    public override void Cleanup() => CoreUtils.Destroy(m_Material);

}

VolumeComponentMenu

[Serializable, VolumeComponentMenu("Post-processing/Custom/GrayScale")]

VolumeComponentMenuAttributeでは、VolumeのAdd Overrideボタンを押したときの表示階層を定義します。

Volumeに露出するプロパティを定義する

    [Tooltip("Controls the intensity of the effect.")]
    public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f);

ClampedFloatParameterは、エディターではスライダーで表示されます。ほかにもFloatParameter、Vector3Parameterなどいろいろなものが用意されており、リファレンスを見ると一覧があります。

IsActive()

    public bool IsActive() => m_Material != null && intensity.value > 0f;

IsActive()がfalseを返すと、エフェクトの実行がスキップされます。パラメーターによってエフェクトの実行をスキップできる場合は、スキップして無駄な処理を省きましょう。

エフェクトの実行タイミングを定義する

    public override CustomPostProcessInjectionPoint injectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;

CustomPostProcessInjectionPointはエフェクトが実行されるタイミングを定義します。指定できるタイミングには

  • AfterOpaqueAndSky
  • BeforePostProcess
  • AfterPostProcess

があります。こことかを見るとパイプラインのどこにあたるかがわかると思います。

シェーダーの読み込み

    public override void Setup()
    {
        if (Shader.Find("Hidden/Shader/GrayScale") != null)
            m_Material = new Material(Shader.Find("Hidden/Shader/GrayScale"));
    }

エフェクトに使用するシェーダーからマテリアルを作ります。ここのシェーダー名は先ほど作成したシェーダーの名前を指定します。

Render()

    public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination)
    {
        if (m_Material == null)
            return;

        m_Material.SetFloat("_Intensity", intensity.value);
        m_Material.SetTexture("_InputTexture", source);

        HDUtils.DrawFullScreen(cmd, m_Material, destination);
    }

実際に毎フレームの描画時に呼び出されるメソッドです。ImageEffectやLegacy RPにおけるCommandBufferと同じノリで、sourceからdestinationに書き込めばいいという感じです。ただし、シェーダーの実行にはHDUtils.DrawFullScreenを使用しますが、これには入力テクスチャの指定がないため、テクスチャの入力はMaterialのSetTextureや、CommandBuffer.SetGlobalTextureから行う必要があります。

Cleanup()

    public override void Cleanup() => CoreUtils.Destroy(m_Material);

リソースの開放を行います。

3. シェーダーを書く

Shader "Hidden/Shader/GrayScale"
{

    HLSLINCLUDE

    #pragma target 4.5
    #pragma only_renderers d3d11 ps4 xboxone vulkan metal switch

    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/FXAA.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/RTUpscale.hlsl"

    struct Attributes
    {
        uint vertexID : SV_VertexID;
        UNITY_VERTEX_INPUT_INSTANCE_ID
    };

    struct Varyings
    {
        float4 positionCS : SV_POSITION;
        float2 texcoord   : TEXCOORD0;
        UNITY_VERTEX_OUTPUT_STEREO
    };

    Varyings Vert(Attributes input)
    {
        Varyings output;
        UNITY_SETUP_INSTANCE_ID(input);
        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
        output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
        output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);
        return output;
    }

    // List of properties to control your post process effect
    float _Intensity;
    TEXTURE2D_X(_InputTexture);

    float4 CustomPostProcess(Varyings input) : SV_Target
    {
        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
        uint2 positionSS = input.texcoord * _ScreenSize.xy;
        float3 outColor = LOAD_TEXTURE2D_X(_InputTexture, positionSS).xyz;
        return float4(lerp(outColor, Luminance(outColor).xxx, _Intensity), 1);
    }

    ENDHLSL

    SubShader
    {
        Pass
        {
            Name "GrayScale"
            ZWrite Off
            ZTest Always
            Blend Off
            Cull Off

            HLSLPROGRAM

                #pragma fragment CustomPostProcess
                #pragma vertex Vert

            ENDHLSL
        }
    }

    Fallback Off
}

シェーダーはHLSLで記述します。いつものCg/HLSLと言語自体の構文はほとんど同じですが、様々なプラットフォームに対応する都合上、いくつかの命令はHDRP側で定義されたマクロを使用します。

例えば、テクスチャのサンプリングひとつをとっても、

TEXTURE2D(_InputTexture)

でテクスチャを定義し、

LOAD_TEXTURE2D_X(_InputTexture, positionSS)

でピクセルを参照します。さらにこの座標系はUV ( (0,0) ~ (1,1) ) ではなく、ピクセル単位です。
このマクロが曲者で、どういうときにどういうマクロを使用するかは、ソースとにらめっこしながらなんとなく把握するしかないので、includeしているHLSLなどを片手に書いていくのがよいです。

4. エフェクトを登録する

さて、スクリプトとシェーダーの両方が準備できたら、HDRP側にエフェクトを登録してあげる必要があります。
Project Settingsを開き、HDRP Default Settingsを開きます。

下の方にCustom Post Process Ordersがあるので、スクリプトで指定したタイミングのところに、作成したエフェクトを登録します。
image.png

5. 使う

Volumeから追加して使えます。
image.png

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

初心者がUnity2Dでゲーム作ってみた記録

目次

作ったもの
ざっくり設計・機能
学び
おわりに

作ったもの

3_unity_MC_title.png

まほうのクッキング | unityroom
リンク先で遊べます。PC推奨、スマホなどでも一応動作はするようですがサポート外のためデザインが崩れます。
イラストなど諸々込で制作期間2週間、制作時間15時間ちょいくらい。完成したのは11月頃。修正してから書こうと思っていたら他が立て込んでいつのまにやら2月になってた。後回し良くない……。

ゲーム概要

子ども向け。遊びに来るお客さんのためにケーキを作ろう!というストーリー。ヒントからお客さんは誰か・使うべき食材は何か考え、調理パートで食材を選ぶ。選んだ食材によって完成するケーキが変化し、クリア分岐します。

ざっくり設計・機能

magic_cooking.png
スクリプト一覧 | Git

〆切的にイラストが間に合わなそうで諦めたけどお客さんをランダムに設定したかったところ。
主に頑張ったのはケーキ土台とトッピングを数種用意し、選んだ食材によってケーキの完成図を変化させる部分。
3_unity_MC_select.png
3_unity_MC_cake2.png

「これでつくる」ボタンに変数を用意。食材を選ぶと、インスペクターで指定した値分「これでつくる」の変数を変化させるメソッドを呼ぶ仕様。

↓一部抜き出し

「これでつくる」ボタン側スクリプト
Judge
    public int which_cake = 0;
    public int whichi_decoration = 0;

   //食材側で呼び出される、判定値を変更
    public void Pc1()
    {
        which_cake += 1;
        Debug.Log("which_cake: " + which_cake);
    }

    public void Pw1()
    {
        whichi_decoration += 1;
        Debug.Log("whichi_decoration: " + whichi_decoration);
    }
   void OnMouseDown()
    {
        if(which_cake == 7)
        {
            cake_freshcream.SetActive(true);
        }
        else if(which_cake == 17)
        {
            cake_chocolate.SetActive(true);
        }
        else
        {
            cake_failed.SetActive(true);
        }

        if (whichi_decoration == 3 && (which_cake == 7 || which_cake == 17))
        {
            banana.SetActive(true);
            strawberry.SetActive(true);
            P.SetActive(true);
        }
        else if (whichi_decoration == 1 && (which_cake == 7 || which_cake == 17))
        {
            banana.SetActive(true);
            P.SetActive(true);
        }

        else if(whichi_decoration == 2 && (which_cake == 7 || which_cake == 17))
        {
            strawberry.SetActive(true);
            C.SetActive(true);
        }
        else
        {
            B.SetActive(true);
        }
    }

食材側スクリプト
Judge
   //足す値をインスペクター上で指定
    public int plus = 1;

    void OnMouseDown()
    {
        //ループ用の変数を定義
        int p = plus;

        //+値が0になるまでJudgeで足す
        while (p != 0)
        {
            judger.GetComponent<Judge>().Pc1();
            --p;
        }

        this.gameObject.SetActive(false);
    }

ハマった問題

他オブジェクトのスクリプトから値を変化させる方法

共有する変数が記述されたクラスA
 public static int a = 0
利用側
 A.a = 0

上記のようにpublicかつstaticな変数であればクラス外からもアクセスでき、異なるシーン間でも共有することができる。またクラス外からも値を変更できます。ただしエラーのもとのためprivateにして、プロパティで操作するのが原則らしい。
今回はそもそも他オブジェクトのスクリプトから値を変化させないことで解決しました。

プロパティについては↓
プロパティ - C# プログラミング ガイド | Microsoft Docs
プロパティ?フィールド?メンバー?C#のクラス構造のおさらい

学び

  • ハマったとき、どうしてもその方法に限る場合を除いて別手段を検討する
  • その方法に限る場合早めに人に聞いてみる
  • 後々まとめることを念頭にキャプチャなどを残しておくと未来の自分が喜ぶ。

おまけ

制作前の自分用ざっくりメモ
IMG_3458.JPG

おわりに

見ていただきありがとうございました!

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

Unity オンラインゲームにMicrosoft Azure Functions C# と PlayFab はいかが?

まえがき

個人の趣味で大規模オンラインゲーム開発を進めるには、大手Webサービスを利用するほか道はないと思っています。
クラウドゲーミングサービス PlayFab を Microsoft が買収して2年、数日前に CloudScript というゲームクライアントからリクエストしてサーバーサイドで処理を実行する仕組みの実装本体に Azure Functions が一般利用できるようになりました。

ここにきて我々は C# だけでクライアント・サーバー処理を実装できるようになったわけです。
利用言語の統一は個人開発において開発効率の向上やモチベーションの継続に大きく寄与します。

本記事は他の多くの個人開発者の方にも参考にしていただければと思い、いつもは個人ブログに書いている内容をここ Qiita に残すことにしました。

前提

Azure のサービスを使うので Microsoft Azure にお支払いできる「従量課金」サブスクリプションが必要
Visual Studio 2019 を上記と紐づく Microsoft Account で利用している(ボタン押すだけで作業完了するので楽だよ)

Visual Studio 経由で Azure Functions を発行

公式でとても十分な手順書があるのでなぞります
https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-create-your-first-function-visual-studio

ポイントだけ記録すると、新規プロジェクト作成で Azure Functions テンプレート C# を選択して適当な場所に適当なプロジェクト名で作成
image.png

最新の v3 環境と Http trigger でリクエストをさばくようにし Authorization level を Function から Anonymous に落とします(一応 Function のままでもいけるけど、関数ごとに code クエリパラメータに関数のキー指定が必要になる。今は入門記事だからセキュリティは後から上げることにしました)
image.png

実装はテンプレート自動生成のままで進めます。

ソリューション エクスプローラーで、プロジェクトを右クリックし、 [発行] を選択
Azure Functions の従量課金プランの新規作成、パッケージファイルから実行(推奨)にチェックを入れてプロファイル作成に進みます

PlayFab の実行環境が US West (オレゴン州)なので Azure のリソースグループや Azure Storage の場所指定は West US (カリフォルニア州) or West US 2 (ワシントン州)で進めていきます。アメリカではそれぞれオレゴン州と隣接する州なので近い方がいいと思います。

数分後、Azure の Function App 一覧に West US ロケーションで Azure Function が作られていることを確認できました。(速度比較のため Japan East にも同じの作りました)
image.png

Function 一覧を確認して、まだ発行ボタンを押していないので一つも関数がない状態でした。
ここから Visual Studio 上で公開→発行ボタンを押すと Function1 が有効化された状態で確認できるようになりました。

image.png

現在の実装はテンプレートから自動生成されたもの 以下の通りです。

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace CubeWalkAzureFunctions
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
        }
    }
}

Azure Function の疎通確認

コンソールで関数について確認していけば「Get function URL」ボタンがあるので、ここから関数を HTTP リクエストで実行するための url を取得します。
image.png

上記実装では name クエリを必須としているので、これを付けて GET してみましょう。
image.png

Hello, simplestar が返ってきました。
これが確認できれば Azure Functions の作成、発行については問題ありませんね。

Unity から PlayFab Azure Function を呼び出そう

前提

Unity で Cloud Script を実行できること

初心者で何もわからない方は先に以下の記事をなぞりましょう。

@ume67026265 さんが PlayFab のアカウントの作り方と、Unity へ SDK を導入する記事を書かれています。

PlayFab始めました ※アカウントの作り方
PlayFabでUnityを動かしてみる -その1下準備編 - ※Unity へ PlayFab SDK を導入する手順
PlayFabでUnityを動かしてみる -その2 APIコールを作ってみる- ※ユーザーを PlayFab へログインさせるための手順

PlayFab にて関数名とurlを登録

自分の PlayFab スタジオ・タイトルの Automation → Cloud Script → Functions(Preview) で Register Cloud Script Function する
具体的には、関数の url を関数名とともに登録して紐づけを行います。
image.png

Unity 側の実装

Unity で PlayFab にログインして API 呼べるなら、次の実装が行えるはずです。

using PlayFab.CloudScriptModels;
using PlayFab;
using System.Collections.Generic;
using UnityEngine.Events;

~省略~

        private void CallCSharpExecuteFunction(UnityAction<string> onSuccess)
        {
            PlayFabCloudScriptAPI.ExecuteFunction(new ExecuteFunctionRequest()
            {
                FunctionName = "Function1", //This should be the name of your Azure Function that you created.
                FunctionParameter = new Dictionary<string, object>() { { "inputValue", "CubeWalk" } },
                GeneratePlayStreamEvent = false
            }, (ExecuteFunctionResult result) =>
            {
                if (true == result.FunctionResultTooLarge)
                {
                    Debug.Log("This can happen if you exceed the limit that can be returned from an Azure Function, See PlayFab Limits Page for details.");
                    return;
                }
                onSuccess?.Invoke(result.FunctionResult.ToString());
                Debug.Log($"The {result.FunctionName} function took {result.ExecutionTimeMilliseconds} to complete");
                Debug.Log($"Result: {result.FunctionResult.ToString()}");
            }, (PlayFabError error) =>
            {
                Debug.Log($"Opps Something went wrong: {error.GenerateErrorReport()}");
            });
        }

実行結果は次の通り

The Function1 function took 191 to complete
Result: Hello, simplestar

PlayFab の SDK を Azure Function で利用

やっと下地が整いましたね。ここから PlayFab と Azure Function 連携のうまみをトッピングしていこうと思います。

PlayFab SDK Package インストール

次のパッケージを Visual Studio プロジェクトにインストールします。
PlayFabAllSDK : https://www.nuget.org/packages/PlayFabAllSDK/
PlayFabCloudScriptPlugin : https://www.nuget.org/packages/PlayFabCloudScriptPlugin/

PlayFab SDK の利用

テンプレート自動生成された Azure Function C# に次のクラスを追加します。
※PlayFab 側で TitleInternalData に TestKey で TestValue を詰めておいてください。以下のコードで取得できているかチェックしてます。
またタイトルIDとサーバー関数実行のためのシークレットキーをどこかのタイミングで渡しておきます。(今回は実行直前に設定…)
シークレットキーは PlayFab のタイトル管理画面の Secret Key 項目から作れます。
詳しい手順はAzure PlayFab をサーバーサイド(ASP.NET Core Web API)から利用するから確認できます。

using System.Net.Http;
using PlayFab.Plugins.CloudScript;
using System.Collections.Generic;
using PlayFab.ServerModels;
using PlayFab;

    public static class HelloWorld
    {
        [FunctionName("HelloWorld")]
        public static async Task<dynamic> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestMessage req,
            ILogger log)
        {
            /* Create the function execution's context through the request */
            var context = await FunctionContext<dynamic>.Create(req);
            var args = context.FunctionArgument;

            // コンテキストからプレイヤーIDを確認
            var message = $"CurrentPlayerId: {context.CurrentPlayerId}!";
            log.LogInformation(message);

            // POSTボディ入力パラメータを確認
            dynamic inputValue = null;
            if (args != null && args["inputValue"] != null)
            {
                inputValue = args["inputValue"];
            }
            message += $"  args: {new { input = inputValue } }";

            // サーバーAPIの呼び出し
            var internalData = await GetTitleInternalDataAsync();
            message += $"  internalData[TestKey] = {internalData["TestKey"]}";

            return new { messageValue = message };
        }

        [HttpGet]
        private static async Task<Dictionary<string, string>> GetTitleInternalDataAsync()
        {
            PlayFabSettings.staticSettings.TitleId = "ここに Playfab タイトルIDを指定";
            PlayFabSettings.staticSettings.DeveloperSecretKey = "ここに PlayFab タイトルのシークレットキーを指定";

            var request = new GetTitleDataRequest();
            var titleInternalData = await PlayFabServerAPI.GetTitleInternalDataAsync(request);

            return titleInternalData.Result.Data;
        }
    }

再発行→関数を登録→関数名で実行

加えたのは Azure Functions の実装だけですから、再発行→関数を登録→関数名で実行をしてみます。
問題なく PlayFab SDK が利用できていました。

結果(XXXXXXXX には有効な ID が入ります)

The HelloWorld function took 268 to complete
Result: {"messageValue":"CurrentPlayerId: XXXXXXXXXXXXXX! args: { input = CubeWalk } internalData[TestKey] = TestValue"}

速度の確認

West US と Japan East それぞれに同じ Azure Function を作ってみました。
それぞれの関数 url を利用する CloudScript を登録して、Unityにて関数実行からレスポンスが返るまでの時間を計測
結果が次の通り
※ 10 回ほど 2秒間隔で関数を Unity から実行

ロケーション Japan East West US
所要最大[ms] 1061 492
所要最小[ms] 765 241

やっぱり Azure Functions も日本じゃなくてアメリカ西海岸に置くのがいいのかな
(全部日本に来ないかな…)

まとめ

オンラインゲームにはいくつか形態があります。リアルタイム通信格闘だったり、ステータスをクエストで上げていくRPGだったり
今回のは後者のソーシャルRPGを支える PlayFab というクラウドゲーミングサービスのオンライン実装の話です

その Unity のオンライン機能実装が C# で、しかも Visual Studio 環境のインテリセンスを効かせてできるようになりました!
Azure Functions は F5 キーで実行するとサーバーとして機能しブラウザから HTTP リクエストすればブレークポイントはってデバッグもできます!
image.png
こんなにうれしいことはない!!

昨今の Unity 個人開発で大規模オンライン要素の追加を考えている人は
Microsoft Azure Functions と PlayFab の組み合わせを候補にあげてみてはいかがでしょう?

以上です。

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

Unity Accelerator + Prometheus + GrafanaをDockerでサービス化する

はじめに

Unity2019.3からAsset Pipeline v2が追加されてUnity Acceleratorを組み合わせるとインポートしたアセットをキャッシュおよび共有することができます。

それまでのUnityにもAsset Pipeline v1とキャッシュサーバーでキャッシュできていましたが、Unity Acceleratorには以下の違いがあります。

  • キャッシュサーバーと同居できる
  • Collaborateのキャッシュに対応
  • 不要なキャッシュを定期的にクリーンアップ
  • 転送されたバイト数や接続されたエディターなどの情報をPrometheusから利用できるメトリクスで公開

フォーラムの以下のスレッドによるとDockerHubで公開する予定があるようですが、まだないのでUnity AcceleratorとPrometheusとダッシュボードのGrafanaをDockerでサービス化しました。

Dockerでサービス化

Dockerfileおよびdocker-composeは以下にUnity Acceleratorのみのv2とキャッシュサーバーも同時にインストールするv1_v2を用意してます。

https://github.com/shiena/docker-unity-accelerator

Unity Acceleratorのみ

# イメージをビルド
docker-compose -f dokcer-compose.yml -f v2.yml -p v2 build

# サービスを実行
docker-compose -f dokcer-compose.yml -f v2.yml -p v2 up -d

# Unity Accelerator単体で実行
docker-compose -f v2.yml -p v2 up -d

# バージョン確認
docker run --rm unity-accelerator:v2 /opt/Unity/accelerator/unity-accelerator --version

Unity Acceleratorとキャッシュサーバー

# イメージをビルド
docker-compose -f dokcer-compose.yml -f v1_2.yml -p v1_v2 build

# サービスを実行
docker-compose -f dokcer-compose.yml -f v1_2.yml -p v1_v2 up -d

# Unity Acceleratorとキャッシュサーバーのみで実行
docker-compose -f v1_v2.yml -p v1_v2 up -d

# バージョン確認
docker run --rm unity-accelerator:v1_v2 /opt/Unity/accelerator/unity-accelerator --version

サービスを起動するとそれぞれ以下からアクセスできます。

GrafanaではUnity - Manual: Unity Acceleratorの一覧にあるメトリクスを扱えます。

Docker化で工夫したこと

  • Unity AcceleratorをダウンロードするURLからバージョンが分からないのでバージョンを確認する方法を用意しています。
  • キャッシュサーバー追加でインストーラーを非対話モードで実行するとnpmのパスが展開されないバグがあるので対話モードprintfで強引にインストールしています。(バグ報告済み)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityでスプライトシートを使ってアニメーションさせる方法

はじめに

キャプチャ.PNG
一枚の画像でアニメーションする方法を紹介します。
経緯としては普段のゲーム開発環境では一枚一枚をプログラムで読み込む作業があったのですが、
なんとunityでは簡単な設定でできるらいしいので試してみます。

設定

  • 画像を用意

    • 画像をproject>assets>imageに投下
    • キャプチャ1.PNG
  • 画像の設定方法

  • Pixels Per Unityを設定

    • 今回は一つの画像が300*300なので(300)に設定しました。300ピクセルを1ユニットに設定
  • Filter Modeの設定

    • 画像もドット絵なのでPoint(no Filter)に設定
  • Compressionの設定

    • Noneに設定
  • Sprite Modeの設定

    • スプライトエディターで画像を編集したいのでMultipleに設定
  • 今までの設定は以下

    • キャプチャ2.PNG

編集開始!

  • Sliceを押下
    キャプチャ33.PNG

  • あと適当に設定する

    • 自分の場合
    • TypeをGrid By Cell Sizeに設定
    • 一枚の画像サイズを設定する(300*300)
  • エディットでサイズが任意のものになっているか確認し「Apply」を押下する。

  • あとは画像を実行画面にドロップしてアニメーションファイルを保存する。

    実行して確認してみる

  • gifで出力する方法がわからないので、

  • いまいちなのですが、何とかアニメーションすることができました。
    キャプチffffャ.PNG

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

Unityでスクリプトがアタッチできない!

発生したエラー

タイトルの通り、スクリプトをアタッチしようとすると、
Can't add script behaviour 〇〇. The script needs to derive from MonoBehaviour!
とエラーが出ます。
調べてみるとファイル名とクラス名が不一致の場合に起こるエラーのようですが、もちろん一致していますし、再インポートしても治りません...。
絶望的な気分でしたが、なんとか解決したので共有します。

ちなみにUnityのバージョンは "2018.4.17f1" です。

解決

気が付かなかったのですが、アタッチ時にコンソールにて詳細なエラーメッセージが表示されていたようでした笑
みんなもコンソールはちゃんと確認しよう(戒め

コンソールのメッセージによると、今回使用していたUnityちゃんのアセットパッケージに含まれていたスクリプトにエラーが発生していたようでした。
Unity AssetStore / "Unity-Chan!" Model

どうやら一つでもスクリプトに不備があると他のスクリプトもアタッチできなくなってしまうようですね。(間違ってたら申し訳ない)

エラーを起こしているスクリプトを修正すると、無事ほかのスクリプトもアタッチすることができるようになります。

さいごに

今回はコンソールの確認不足という恥ずかしいオチでしたが、参考になれば幸いです。
抜けている情報や誤りがあれば改善しますのでコメントにてお願いします。

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

【中級者向けUnity講座】RPG編 part1 『キャラを歩かせる.その1』

はじめに

皆様こんにちは。
個人でゲーム制作をしております、kenと申します。
この講座では、実際にゲームを作りながら「こういう事をするなら、こういう風にすると良いと思うよ。詳しくは自分で調べてね。」という感じで、ゲームの作り方、Unityの機能やアセット等を軽く紹介して行きます。

今回は、Unityでキャラクターを歩かせる方法をいくつか紹介します。
私は、キャラが動いているのを見るとテンション上がるので、大体ここから作り始めます。

キャラを歩かせよう!

1口にキャラを歩かせるといっても、いろんなことをしなければいけません。だいたい以下の手順が必要です。

1.キャラクターをシーンに配置してセットアップする
2.プレイヤーからの入力を受け取る
3.キャラクターを移動させる
4.キャラクターの移動に合わせてアニメーションを再生する
5.カメラも動かす

今回は3のキャラクターを移動させる方法を3つ紹介します。

Character Controller

これが1番シンプルで扱いやすいです。登れない角度の設定や登れる段差の設定が出来ます。スクリプトから移動させる方法にSimpleMoveとMoveという関数があり、SimpleMoveは重力が自動で付きますが、ジャンプが出来ません。Moveは重力が無いので独自に実装する必要が有りますが、ジャンプの実装が可能です。

Character Controllerの欠点は、物理演算の影響を受けない事と設置判定の精度が甘い事などが有ります。それらの問題を解決したい場合は、後述するPhysicsを使いましょう。

Character Controllerについて詳しく知りたい方には以下の記事がオススメです。
Unityの便利機能を使いこなそう #2 CharacterControllerでプレイヤーの移動とジャンプを実装しよう【マリオ風、バイオハザード風、フォートナイト風】
キャラクターコントローラーを使う人型3Dモデルをジャンプさせる(その1:重力を加える)

【Unity】CharacterControllerで当たり判定ができないときの対処法

【Unity】CharacterController使用時に地形の傾斜に応じてキャラクターを滑らせる方法
Character Controllerの罠

Physics + Collider

物理演算を使いたい場合は、これを使いましょう。1番自由度が高いですが、自由度が高いという事はバグも生み出し易いという事です。ちょっと凝ったことをしたい場合は、バグとの戦いになる事を覚悟して使いましょう。

Physics + Colliderについて詳しく知りたい方には以下の記事がオススメです。
【Unity】 Rigidbodyの移動方法
【Unity】Rigidbody や Collider の設定により変化する、当たり判定の性質 前編
【Unity】Rigidbody や Collider の設定により変化する、当たり判定の性質 後編

NavMesh

NavMeshを使うと経路探索AIが簡単に実装出来ます。経路探索のためのシステムですが、Move関数があるので他の2つと同じような使い方もできます。
欠点は宙に浮くことが考慮されていない為、ジャンプの実装が難しいことです。が、OffMeshLinkという機能を使えばそれっぽい感じには出来ます。

NavMeshについて詳しく知りたい方には以下の記事がオススメです。
NavMeshを使ってみる その1
NavMeshを使ってみる その2
UnityのNavMeshComponentsアセットの使い方とゲーム中にNavMeshのベイクをする
NavMeshAgentでよい感じにキャラクターを歩かせる
Unityのナビゲーション機能でOffMeshLinkを使って移動
【Unity】NavMeshとRigidbodyを連携して動かす

まとめ

物理演算を使いたければPhysics + Collider、経路探索を使いたければNavMesh、簡単な動きだけならCharacter Controllerを使うのがよさそうです。
また、どれか一つに絞る必要はなく、自キャラの移動はCharacter Controllerで敵キャラはNavMeshを使うなど、複数のいいとこどりをすることも可能です。とりあえず全部触ってみてそれぞれの特性を知っておくのがいいと思います。

私は今回はNavMeshを使って自キャラが自動で障害物をよけて進むようなシステムにしようと思っています。具体的な実装はまた今度記事にします。

次回は、2のプレイヤーからの入力を受け取るをやっていこうと思います。
次回→2/29(日)投稿予定

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