20191024のUnityに関する記事は11件です。

KudanARUnityのサンプルをAndroidで動かす

はじめに

この記事はUnity2018.2.21f1でKudanARUnityを動作させたの備忘録です。
今回はサンプル動作までを記載します。

動作環境
Unity2018.2.21f1
KudanARUnity V1.6.0
Android Studio v3.5.1
Glaxy feel SC-04J(Android8.0.0)

環境構築

  1. Unity、Androidのインストールについては割愛します。
  2. KudanARUnity V1.6.0を以下のページの枠で囲ったリンクからUnityパッケージを取得します。
    メールアドレスでの認証が必要で、入力したメールアドレスにダウンロードリンクのURLが添付されています。

ダウンロード先
kudan_download.png
3. ダウンロードしたKudan-UnityPlugin.zipを任意の箇所に展開します。

Unity Editorでのサンプル実行

  1. UnityのProjectを作成します。
  2. Unity Editorが起動したら、前項3. で展開したフォルダのKudanARUnity.unitypackageをProjectにD&D、Importします。
  3. Assets/KudanAR/Samples/KudanSample.unityをダブルクリックし、SampleSceneを開きます。
  4. HierarchyのKudan Bundle - With UIを開き、InspectorのKudan Tracker(Script)のEditor API Keyに、
    Kudanダウンロードページ APIキータブのUnity Editor Key(黒塗り部分)を入力します。(今回は公開されている開発用ライセンスキー使用します)

UnityEditorKey.png
5. API Keyに、Kudanダウンロードページ APIキータブのKudan AR SDK(黒塗り部分)を入力します。
APIKey.png
6. 再生ボタンを押すと、サンプルが実行されます。Assets/KudanAR/Samples/Textures/lego.jpgを表示し、カメラでとらえることで、モデルが表示されます。

SampleUnity.png

Android向けのビルドと実行

1. メニューバー File>BuildSettingsを選択し、ビルド設定を出します。
2. 赤枠①で囲ったAndroidを選択し、プラットフォームをAndroidに変更する。
3. 赤枠②で囲ったAdd Open Scenesをクリックし、サンプルシーンをビルド対象に追加する。(すでにチェックが入っているScenes/SampleSceneはチェックを外す)
4. 赤枠③で囲ったplayer Settingsをクリックし、player Settingsを表示する。
ビルドセッティング.png
4. 赤枠①で囲った、player Settings/Other Settings/Rendering/Multithreaded Renderingのチェックを外します。(理由はイマイチ分かっていませんが、この記事と同じ状況を解決するためにチェックを外しています。)
5. Package NameにKudanダウンロードページ APIキータブのKudan AR SDKのBundle IDを入力します。
(開発者ハブの画像ではeu.kudan.arとなっていますが、画像が古いです)

playerSettings.png
6. BuildSettingsのSwitch Platformをクリックし、プラットフォームをAndroidへ切り替えます。
7. Edit>Preferencesを開き、External ToolsのAndroid SDK/JDKのPATHを入力する。
Preferences.png
8. BuildSettingsのBuild And Runをクリックし、ビルドとアプリファイルの転送実行を行います。
 その結果、アプリでAssets/KudanAR/Samples/Textures/lego.jpgをキャプチャするとモデルが表示されます。
Screenshot_20191024-232133_kudan4Qiita.jpg

おわりに

今回はUnity2018.2.21f1でKudanARUnityのサンプルを動作させました。
次回はオリジナルのマーカー、3Dモデルを表示させます。

参考

The Kudan Developer Hub https://www.xlsoft.com/doc/kudan/ja/home_jp/
Kudan + UnityでAndroid向けマーカーレスARを試してみる(1) https://qiita.com/doatodarkness/items/be50fb420ad6ea1c79c0
【Unity初心者向け】Kudan AR SDKを使ったARアプリの開発方法とは? https://blog.codecamp.jp/unity-kudan-ar-sdk
AR KUDANでカメラが起動して居ない https://teratail.com/questions/103107

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

TelloをUnityでC#するTelloLibを使って

UnityでC#してドローン制御したかったのでメモ

TelloのWifiにPCを接続

ノートPCなどですとWifi接続が楽ですね

TelloUnityDemoで楽をする

Gitにサンプルコードあったので、乗っかります
https://github.com/comoc/TelloForUnity

TelloLibは後入れなので、下記のものを追加します
https://github.com/comoc/TelloLib.git

映像がでないけど色々データ取れた

無題2.png

とりあえず。Windowsのファイアウォールを全部OFFにしたら表示できた。。

Windows Specific Settings
Please confirm the Windows Firewall settings of your Unity Editor. Public network access is required to receive the video stream from Tello.

って書いてあった。。
https://github.com/comoc/TelloForUnity
に。。

TelloをStationModeへ

ほんとはTelloをStationModeにすれば
他のWifiにぶら下がれるので
つぎは、このあたり設定したいです。

参考サイト

TelloForUnity
https://github.com/comoc/TelloForUnity

TelloLib
https://github.com/Kragrathea/TelloLib

TelloLib
https://github.com/comoc/TelloLib.git

UnityでUDPを送信してみる
https://qiita.com/nenjiru/items/d9c4e8a22601deb0425b

Tello EDUをNode-REDから station mode にして操作するメモ
https://www.1ft-seabass.jp/memo/2019/05/01/tello-edu-meets-nodered-setting-station-mode/

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

サーフェイスシェーダー入門編

そもそもシェーダーとは?

一言で表すと「描画方法を記述したプログラム」

実際の処理を行うのはGPUが担当する
処理は並列(GPU自体が超並列特化のため)

使用する言語

UnityのShaderLabを使う。ShaderLabは宣言型言語※1。
Cg(C for Grapchics)※2、HLSL(High Level Shading Language)※3を組み合わせたようなものになっている
ShaderLabはOpenGL向けに書き出される端末の場合、HLSL2GLSL※4でコンパイルされ、GLSL※5に書き出される仕組みになっています。

※1 宣言型言語とは、プログラムの中で使用する変数や定数などの名称や領域、属性などを、あらかじめ定める必要がある言語。
※2 Cgとは、NVIDIAが開発していたシェーディング言語。C言語ベース 意味はそのままでグラフィックスのためのC言語
※3 HLSLとは、マクロソフトによって開発されたDirectXで使われるシェーディング言語 NVIDIAと協力して開発していたのでCgと似てる
※4 HLSL2GLSLとは、HLSL言語をGLSL言語にするトランスレータ(意味や内容を変えずに変換するもの)のこと。
※5 GLSLとは、OpenGLとの親和性を持つシェーダ記述言語で、C言語ライクな独自の文法によって記述します。

使えるシェーダー

Unityのシェーダーには4種類あります。

Surface Shader

Unity 独自色の強いシェーダで、端的には簡単なシェーダ

Vertex・Fragment / Unlit Shader

Unity上ではUnlit Shaderと書かれているが、一般的なバーテックスシェーダーとフラグメントシェーダー
バーテックスシェーダーでは頂点を動かして物を変形させたりアニメーションさせる。頂点に色が打たれていたらその色にする。
フラグメントシェーダーでは光や影の影響を考慮して色を付けたり。輪郭を付けたりボカしたりする。フラグメントを操作するシェーダー

Image Effect Shader

Image Effect Shader は最終的に出力されるカメラやテクスチャ画像に適用するためのシェーダ。ポストエフェクトと呼ばれることもあります。シェーダのソースコードの構造は Vertex Fragment Shader と同じで、多くの場合に Fragment Shader を編集し実装します。
例えば画面全体の色相(色調)を変更したり、画面全体を一律にぼかしたりすることができます。 それ以外にもシーン(画面)遷移するときの効果、フェードイン・アウト、モザイク、ディストーションなどが実現できます。

Compute Shader

最も高度で複雑なシェーダ
特定のプラットフォームで GPU を使うために利用したり、 あるいはレンダリングパイプラインとは異なる目的と手段によって GPU を使った処理を実現するために使います。

Surface Shader(サーフェイスシェーダー)について

Unity専用のシェーダー
光源の影響や影の付き方、細かい色の付き方など、細かいことを考えなくても良い利点があります。 一方でそれらを細かく制御することは困難になります。

それらを考えなくてもいい理由は、頂点シェーダーを省略できて、サーフェイスシェーダー用の命令で、フラグメントシェーダーを生成してくれるため
20191003-124820.jpg
https://www.youtube.com/watch?v=wUx_Y9BgC7k

高度なシェーダーが作りたい場合はVertex・Fragment / Unlit Shaderを使います。

使える変数の型

説明
float 高精度 浮動小数点値 32bit
複雑な関数などに利用
half 中精度 16bit
-60000 ~ 60000小数点以下約3桁
方向 オブジェクト空間位置に利用
fixed 低精度 11bit
-2.0 ~ 2.0 1/256精度
色情報 単純な制御に利用

こちらに例文含めて使える変数についていろいろ書かれています。
https://qiita.com/nmxi/items/bfd10a3b3f519878e74e

実際のコード

Shader "Custom/HogeHogeShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType" = "Opaque" }
        LOD 200
        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0
        struct Input
        {
            float2 uv_MainTex;
        };

        sampler2D _MainTex;
        void surf(Input IN, inout SurfaceOutputStandard o)
        {
            half4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Shader "Custom/HogeHogeShader" {}

シェーダーの名前

Properties {}

インスペクタ上から指定したものを設定できる。
変数名("Inspector上の表示名", 変数の種類) = デフォルト値
のルールで記述します。

以下使用できるもの

//Int
name ("display name", Int) = number

//Float
name ("display name", Float) = number

//Vector
name ("display name", Vector) = (number,number,number,number)

//Float Range
//インスペクタ上でスライドバーが_min_から_max_として表示されます
name ("display name", Range (min, max)) = number

//Color
//インスペクタ上でカラーピッカーが表示されます
name ("display name", Color) = (number,number,number,number)

//Texture 2D
name ("display name", 2D) = "name" { options }

//Texture 3D
name ("display name", 3D) = "name" { options }

//Cubemap
name ("display name", Cube) = "name" { options }

シェーダープロパティアトリビュート

[HideInInspector]_Hoge ("HogeValue", int) = 0

↑のHideInInspectorのようなものをシェーダープロパティアトリビュートといいます。
HideInInspectorと設定するとインスペクタ上から表示が消えるようになります。

他にも、EnumToggleを扱えるようにすることもできます。

シェーダプロパティアトリビュートについてはこちらが詳しく書いてあります。
https://qiita.com/luckin/items/96f0ce9e1ac86f9b51fc

SubShader {}

シェーダー本体を記述するところ。一つのSubShaderに1本分のシェーダコードが入ります。
SubShader枠が複数あると、Unityがそのシェーダーが動くか上から1つ1つチェックして動くものを適用してくれます。

FallBack

全て動かなかったら最後の"FallBack"に飛びます。
"FallBack"は滑り止めみたいなもので、すべてのシェーダーが動かなかった時、ここで指定したシェーダーを使うようにしてくれます。

subshader.PNG
http://tsumikiseisaku.com/blog/shader-tutorial-lod/

Tags {}

Queue

Tags { "Queue" = "Transparent" }

レンダリング順を指定できます。

半透明のオブジェクトを最後に描画しないと、透明部分が正しく描画されないのを防止するのに使ったりします。

「Background」→「Geometry」→「AlphaTest」→「Transparent」→「Overlay」の順で描画されます。
各キューは内部で整数インデックスにより表現され,Background は 1000, Geometry は 2000, AlphaTest は 2450, Transparent は 3000,そしてOverlay は 4000です。
インデックス管理なので、以下のような定義の仕方も可能です。

//Transparentの次に描画
Tags { "Queue" = "Transparent+1" }

20161005200634.png
http://nn-hokuson.hatenablog.com/entry/2016/10/05/201022

RenderType

//キーバリュー関係
Tags { "RenderType" = "Opaque" }

カメラのDepthTexture生成で使われています。Camera.depthTextureModeでDepthTextureMode.Depthを指定するとできます。
内部ではReplacedShadersを使っているのでその時にRenderTypeタグを使います。
https://docs.unity3d.com/jp/460/Manual/SL-CameraDepthTexture.html

ReplacedShaders(置き換えシェーダー)
ReplacedShadersとは、SubShaderに定義されたタグで判定し、シェーダを置き換えて描画する仕組みです。

基本的にはそのシェーダーの用途通りのバリューを設定します。
タグは以下に列挙されています。
https://docs.unity3d.com/ja/current/Manual/SL-ShaderReplacement.html
例えば、半透明にするシェーダーを自作した場合は

Tags { "RenderType" = "Transparent" }

にすると、半透明のシェーダーを置き換える処理を実行した場合に自作のシェーダーも置き換え処理の対象になります。

置き換え処理をするときはこのようになります。

replace.cs
using UnityEngine;

public class ReplacementShaderTest : MonoBehaviour
{
    void Start ()
    {
        //置き換えるシェーダーのパスを指定する
        var replaceShader = Shader.Find ("Custom/replace");

        //第一引数:シェーダー 第二引数:入れ替え対象のキー(先ほど定義したTasgの左辺値)
        //第二引数を空文字にするとすべてのシェーダーに対して置き換え処理が走ります。
        //指定したタグが定義されていないシェーダーは置き換えに含まれなくなります。
        Camera.main.SetReplacementShader (replaceShader, "RenderType");
    }

}

こちらの例だとRenderTypeをキーにしてシェーダーを置き換えます。
置き換え前のシェーダーに定義されているタグが"RenderType" = "Transparent"だった場合
以下のシェーダーの"RenderType" = "Transparent"が設定されているシェーダーに置き換わります。

replace.shader
Shader "Custom/replace"
{
    //上から順にタグを見て置き換えれるか判定
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #include "UnityCG.cginc"
            fixed4 frag(v2f_img i) : SV_Target
            {
                return fixed4(1, 0, 0, 1);
            }
            ENDCG
        }
    }

    SubShader
    {
        //例文だとRenderTypeにTransparentが設定されているので、このシェーダーに置き換わる。結果オブジェクトは緑色になる
        Tags { "RenderType" = "Transparent" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #include "UnityCG.cginc"
            fixed4 frag(v2f_img i) : SV_Target
            {
                return fixed4(0, 1, 0, 1);
            }
            ENDCG
        }
    }
}

ちなみに置き換えれるものがなかった場合は表示されなくなります。
RenderTypeは置き換えシェーダーで使うから何をしているかを書いておこうと思っておけば大丈夫です。

置き換えシェーダーについてはこのサイトが一番わかりやすかったです。
https://www.shibuya24.info/entry/replaced_shaders

その他タグ

他は頻繁に使うことがないので、箇条書きします。
- DisableBatching バッチ可否
- ForceNoShadowCasting シャドウの投影可否
- IgnoreProjector プロジェクターが投影するかどうかフラグ
- CanUseSpriteAtlas シェーダがSpriteを使っていた場合に不具合ある場合はFalseを使用せよとのこと
- PreviewType マテリアルインスペクタのPreview画面の3D形状

補足

一度に複数のタグを設定することも可能です。
その場合はこのように記載します。

Tags { "RenderType"="Opaque" "Queue"="Geometry"}

参考
https://www.shibuya24.info/entry/shader_pass_tag

LOD

Level of Detailを略したものですが、一般的な"カメラの距離によってポリゴン数を変動させる"あのLODとは別物です。
正式名称は"シェーダーLOD"といいます。
値は高度なグラフィック機能の要求がされるものほど高い値を設定します。基準は公式のドキュメントに書かれてあります。
https://docs.unity3d.com/ja/current/Manual/SL-ShaderLOD.html

なぜこのようなことをする必要があるかというと、ハードウェア側でシェーダーがサポートされていても重かったりすることがあるからです。
その時にシェーダーLODを使って、強制的にシェーダーのレベルを下げればパフォーマンスを確保する事ができます。

LODTest.shader
Shader "Custom/LODTest"
{
    SubShader {
        LOD 500
        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0
        struct Input
        {
            float2 uv_MainTex;
        };

        void surf(Input IN, inout SurfaceOutputStandard o)
        {
            o.Albedo = fixed4(1, 0, 0, 1);
        }
        ENDCG
    }

    SubShader {
        LOD 200
        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0
        struct Input
        {
            float2 uv_MainTex;
        };

        void surf(Input IN, inout SurfaceOutputStandard o)
        {
            o.Albedo = fixed4(0, 1, 0, 1);
        }
        ENDCG
    }
    FallBack "Diffuse"
}
    [SerializeField] Renderer render;
    void Start()
    {
        //200以下のLODにしか対応しない
        render.sharedMaterial.shader.maximumLOD = 200;
    }

上の例だとmaximumLODを200にしたので、緑色になります。

LODの設定方法はrenderのマテリアルから直で編集します。
ここで設定した最大LODより大きいシェーダーは使われません。
最大LODよりも低く、できるだけ高度なシェーダーを選択します。(LOD 100と150のシェーダーがあった場合150が選択されます)
もしも使えるシェーダーがない場合はFallBackに設定されているシェーダーが適用されます。(例文でMAXを100にした場合など)

値の決め方ですが、ドキュメントを参考に自分が行った処理から決めるのがいいです。
(Diffuseぐらいしかしていないから200!みたいな感じで)

ちなみに必須のパラメータではないので、なくても動きます。

CGPROGRAM~ENDCG

CG言語の開始~終了を意味しています。
逆にこのエリア以外はCG言語じゃなく、ShaderLabで書かれています。

#pragma surface surfaceFunction lightModel [optionalparams]

サーフェースシェーダーの関数をsurfaceFunctionに知らせます。
例文だとsurfがサーフェースシェーダーの関数と書いています。
サーフェースシェーダーはsurf、バーテックスシェーダーはvert、フラグメントシェーダーはflagとしていることが多いです。

lightModel

ライティングの方法を指定できます。
ライティングの方法によって、サーフェースシェーダーの関数の構造体が変わります。

ライティング方法 説明 使う構造体
Lambert ランバート(非PBR)でライティングを計算 SurfaceOutput
BlinnPhong ブリンフォン(非PBR)でライティングを計算 SurfaceOutput
Standard UnityのStandardシェーダで使っているPBR計算 SurfaceOutputStandard
StandardSpecular スペキュラセットアップのPBR計算 SurfaceOutputStandardSpecular

詳しい構造体の中身についてはまた後程説明します。

PBR(Physically-Based Rendering)
物理ベースレンダリング(Physically-based rendering:PBR)とは物体表面における光の反射や媒質内における散乱などの物理現象,光源からシーンを経てカメラに入射する光の伝搬などを計測して数式でモデル化したものを用いてレンダリングすることです.物理ベースレンダリングに使用されるモデルは様々で,物理現象を詳細に表現したモデルほど現実と見分けがつかないほどの映像を作成することが可能ですが,計算にとても時間がかかります。
https://qiita.com/mebiusbox2/items/e7063c5dfe1424e0d01a

カスタムライティング
ライティングは自作できます。
カスタムライティングについては実際のトゥーンシェーダのソースにコメントいれて軽く説明しておきます。
詳細な説明は以下のサイト参照
http://nn-hokuson.hatenablog.com/entry/2017/03/27/204255

Toon.shader
Shader "Custom/Toon" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
         //トゥーンシェーダーで使うRampテクスチャ
        _RampTex ("Ramp", 2D) = "white"{}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        //ToonRampというカスタムライティングを使う宣言
        #pragma surface surf ToonRamp
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _RampTex;

        struct Input {
            float2 uv_MainTex;
        };

        fixed4 _Color;

        //カスタムライティングの関数名はLightingを頭につける必要あり。ここの関数名を宣言で使う
        //関数名のところ以外テンプレ。StandardSurfaceOutputは使えないのでSurfaceOutputを使用する
        fixed4 LightingToonRamp (SurfaceOutput s, fixed3 lightDir, fixed atten)
        {
            half d = dot(s.Normal, lightDir)*0.5 + 0.5;
            fixed3 ramp = tex2D(_RampTex, fixed2(d, 0.5)).rgb;
            fixed4 c;
            c.rgb = s.Albedo * _LightColor0.rgb * ramp;
            c.a = 0;
            return c;
        }

        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

optionalparams

サーフェースシェーダー設定を細かくできる
種類が多く、すべて把握していないので、わかっている範囲で説明します。

  • alpha 半透明シェーダーで使います。alphaにも種類がありますが、やりたいことに合わせて選びましょう
  • vertex:name サーフェースシェーダーでバーテックスシェーダーをいじりたいときに使います。nameと同じ関数をシェーダー内に定義する必要があります。
  • fullforwardshadows デフォルトのシェーダーについています。フォワードレンダリング時の影(ドロップシャドウ)を通常はディレクショナルライト以外は表示しませんが、このオプションがあればスポットライトやポイントライトでも影が表示されるようになる

オプション一覧
https://docs.unity3d.com/ja/current/Manual/SL-SurfaceShaders.html

#pragma target X.Y

Shader Compilation Target Levelsというものを指定しています。

こちらを見る限りだとレベルに応じてシェーダーモデルが変わります。
https://docs.unity3d.com/ja/current/Manual/SL-ShaderCompileTargets.html

シェーダーモデルによって、使えるテクスチャの数や機能が違います。単純に、高い方が色々できます。
テッセレーションなどDirectX11の機能を使いたい場合は5.0にする必要があります。
大体のモバイル端末ではShader Model 3.0までは動くようです。ダメなのは一部のOpenGL ES 2.0端末とのこと。(以下参照)
https://forum.unity.com/threads/is-it-ok-to-use-pragma-target-3-0-in-shader-for-mobile-game.448547/

struct Input{...}

Input構造体といいます。次のsurf関数の引数に何を入れ込むかを書きます。
使わなくても定義する必要があるので、適当に1つ定義だけして使わないこともあります。

書き方

型 名       名 前 説明 注意点 例文
float2 uv***** uv座標の取得 変数名を"uv"から始まる必要がある※1。
名前部分はPropertiesで指定したテクスチャ名
float2 uv_CubeTexture;
float3 worldPos ワールド座標 "worldPos"という名前にする必要がある float3 worldPos;
float4 screenPos スクリーン座標 float4の順番は(X,Y,Z,W)。
Wは"screenPos"という名前にする必要がある
float4 screenPos;
float4 color : COLOR 頂点カラー float4の順番は(R,G,B,A)。
変数名の後に":COLOR"というセマンティクス※2をつける必要あり。
float4 col : COLOR;
float3 viewDir ビュー方向 "viewDir"という名前にする必要がある float3 viewDir;
float3 worldNormal オブジェクトの法線ベクトル "worldNormal"という名前にする必要がある※3 float3 worldNormal;
float3 worldRefl 視線ベクトルがオブジェクトに反射した時のベクトル "worldRefl"という名前にする必要がある※3 float3 worldRefl;

※1 テクスチャが複数ある場合はuvが1枚目のテクスチャ、uv2が2枚目のテクスチャという意味合いになります。

※2 その変数がどういうものかを表すために使うもの。vertexシェーダーとflagmentシェーダーだとよく使います。
https://qiita.com/sune2/items/fa5d50d9ea9bd48761b2

※3 vert関数内で出力する"Normal"(法線ベクトル)に書き込みを行う場合に、それを踏まえた反射ベクトルを取得するにはInput構造体にINTERNAL_DATAを含めて、vert関数でWorldReflectionVectorを使う必要があります。
https://docs.unity3d.com/jp/460/Manual/SL-SurfaceShaderExamples.html

sampler2D _MainTex;

Propertiesで宣言したテクスチャや値を使用する場合、Propertiesで宣言した名前と同じ名前でSubShaderの中で宣言しなければいけません。
2Dテクスチャの場合はsampler2D

void surf(Input IN, inout SurfaceOutputStandard o)

サーフェイスシェーダーの実処理部分です。
1ピクセルごとにsurfメソッドが実行されます。

"SurfaceOutputStandard"部分はアウトプット構造体といい、ここは指定したlightModelによって変わります。

アウトプット構造体の種類とその中身

//[LightModel]Lambert, [LightModel]BlinnPhong
struct SurfaceOutput
{
    fixed3 Albedo; // 拡散反射光(=Diffuse)
    fixed3 Normal; // 法線ベクトル
    fixed3 Emission; // エミッション
    half Specular; // スペキュラ
    fixed Gloss; // 輝き
    fixed Alpha; // 透過度
};

//[LightModel]Standard
struct SurfaceOutputStandard
{
    fixed3 Albedo;
    fixed3 Normal;
    half3 Emission;
    half Metallic;//範囲は0~1で、1に近づけるほど金属っぽくなる
    half Smoothness;//範囲は0~1で、1に近づけるほどつるつるした表現になる
    half Occlusion;//オクルージョン(遮蔽)、デフォルトは1で0の場合は完全遮蔽
    fixed Alpha;
};

//[LightModel]StandardSpecular
struct SurfaceOutputStandardSpecular
{
    fixed3 Albedo;
    fixed3 Specular;
    fixed3 Normal;
    half3 Emission;
    half Smoothness;
    half Occlusion;
    fixed Alpha;
};

サーフェイスシェーダーでは、このアウトプット構造体の中身に値を入れることで処理を反映させます。

最初の例文の処理を見ていきます。

void surf(Input IN, inout SurfaceOutputStandard o)
{
    //tex2D関数を使って、UV座標IN.uv_MainTexから_MainTex上のピクセル色を取得します。
    half4 c = tex2D(_MainTex, IN.uv_MainTex);

    //Albedoに色を設定して適用させます。
     o.Albedo = c.rgb;

    //Alphaに透明度を設定して適用させます。
    o.Alpha = c.a;
}

このように、アウトプット構造体の中身に入れ込むだけで大丈夫です。

また、シェーダーには定義済みの値が多数存在し、その中の"_Time"というのを使えば時間が取得でき、これを使うことでアニメーションするシェーダーも書けます。

定義済みの値一覧はコチラにあります。
https://docs.unity3d.com/jp/460/Manual/SL-BuiltinValues.html

まとめ

最近サーフェイスシェーダーについて勉強したのでまとめて書きました!

勉強してみて思ったのが、サーフェイスシェーダーを書くこと自体は簡単ですが、お作法や使える関数など覚えるのが大変だなーと思いました。
覚えることが多すぎるので、理解してから書くよりやりながら覚えるほうがわかりやすかったです。
あと数学さんの出番もかなり多いので、最初は頭がいっぱいになります・・・(私も法線って何?ってレベルから始めました)

こちらのサイトを参考に1個ずつシェーダーを作っていくのが分かりやすかったです。
http://nn-hokuson.hatenablog.com/entry/2018/02/15/140037

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

【VRChat】A VRC_SceneDescriptor or VRC_Avater Descriptor is required to build VRChat SDK Content

スクリーンショット 2019-10-23 12.38.46.png

問題

A VRC_SceneDescriptor or VRC_Avater Descriptor is required to build VRChat SDK Content

日本語

VRChat SDKコンテンツをビルドするには、VRC_SceneDescriptorまたはVRC_Avater Descriptorが必要です。

自己紹介

全地球6億人のロボカッケー皆さんコンバトラー†[□ □]■━
私は王国騎士ロボットVTuberのKoshiだ??(@Koshi_VTuber
王国で騎士を勤めており、闇の組織から王国の平和を守っている!
最近はUnityゲーム王国で3Dモデル、ゲームの制作中だ。

環境

Unity 2017 4.28f

解決法

fbxにVRC_SceneDescriptorとVRC_Avater Descriptorのコンポーネントが割り当てる。

  1. VRChat SDKのパッケージをImportしておく。
  2. シーンに配置したモデルを選択し、Inspector > Add Componentをクリックし、VRC_Avatar Descriptorを選択します。
  3. もし、エラーがなければアップロード時に表示されなくなります。

以上、Unityゲーム王国騎士ロボットVTuber Koshiがお送りしました!

私のステータスだ⚔共にこの世界を救おう
Twitter⚔ twitter.com/Koshi_Vtuber
YouTube⚔ t.co/I9eMMgpS8P?amp=1
niconico⚔ nicovideo.jp/user/90553212
bilibili⚔ space.bilibili.com/476988586
公式HP⚔ koshi-4092b.firebaseapp.com

参考:
VRChatへのアバターアップロード
https://jidaraku-u.hatenablog.com/entry/2019/04/09/231834

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

Logitech G29 SteeringWheel PCでUnityできるまで

Logitech G29 SteeringWheel PCでUnityできるまで

ハンドルコントローラの動作環境とUnityでサンプル動作のメモ

たぶんドライバーインストール(Win 64bit)

ダウンロード先
https://support.logi.com/hc/ja/articles/360025298053-Logitech-Gaming-Software

対象exe
LGS_9.02.65_x64_Logicool.exe

NoName_2019-10-24_10-36-38_No-00.png

SDKダウンロード

Logitech Gaming SDK
https://assetstore.unity.com/packages/tools/integration/logitech-gaming-sdk-6630
NoName_2019-10-24_15-18-7_No-00.png

UnityでSample起動でエラー

どうやらdllが壊れているらしいかもなので
https://gaming.logicool.co.jp/ja-jp/partnerdeveloperlab/sdk-resource-list/steering-wheel-sdk.html
からダウンロードしたdllで上書きしたら動作した。

正常なdll
LogitechSteeringWheelSDK_8.75.30\Lib\GameEnginesWrapper\x64
LogitechSteeringWheelEnginesWrapper.dll

上書き対象
Assets\Logitech SDK
LogitechSteeringWheelEnginesWrapper.dll

UnityでC#でのハンドル接続

キーボードでハンドルの重さ?など変えたりできるみたいです。
オフロード設定でガタガタなりました。

NoName_2019-10-24_10-55-31_No-00.png

参考サイト

ステアリングホイールSDK
https://gaming.logicool.co.jp/ja-jp/partnerdeveloperlab/sdk-resource-list/steering-wheel-sdk.html

Logitech Gaming SDK
https://assetstore.unity.com/packages/tools/integration/logitech-gaming-sdk-6630

Logitech Gaming Software
https://support.logi.com/hc/ja/articles/360025298053-Logitech-Gaming-Software

LogicoolSDKを使ったハンドル入力
https://shin-go.hatenablog.com/entry/logitech

unityでLogicoolSDKを使ってLogitech G29 Steering Wheel(ハンコン)を取得したかった話
https://qiita.com/shi_k_7/items/8b2d2e99b4c6d9bc77d4

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

【VRChat】Not yet allowed to publish worlds / Not yet allowed to publish avatars

問題

download-1.jpg

World Creater Status: Not yet allowed to public worlds
Avatar Creater Status: Not yet allowed to public avatars

スクリーンショット 2019-10-23 9.44.13.png

結論

メールが来るまでVRChatで思いっきり遊びましょう

自己紹介

全地球6億人のロボカッケー皆さんコンバトラー†[□ □]■━
私は王国騎士ロボットVTuberのKoshiだ??(@Koshi_VTuber
王国で騎士を勤めており、闇の組織から王国の平和を守っている!
最近はUnityゲーム王国で3Dモデル、ゲームの制作中だ。

環境

macOS
Unity 2017 4.28f
VRChat & VRChat SDK

解決法

VRChatの世界を周り、友達を作ること
メールで通知が来ると、作ったアバターをアップロードすることができる。

具体的な条件は公開されていない。
重要なのは3つ、プレイ時間、友達を作る、世界を回ること。

私の場合: うる覚え
プレイ時間:約12時間?
回った世界の数: 20くらい?
友達の数: 27人

プレイ時間の7割は、無言でした。アバターを切り替えたり、世界を回りました。
残りの3割は、マイクで色々話しかけました。
話しかけてフレンドを増やしたおかげか、友達の数を増やすと、トラストランクが早く上がるかもしれません。

アップロードしたくてウズウズしている方へ(本題、おまけ、最後に)

↑そんな条件をクリアすることにこだわるより...
お前らVRChatに何しに行くんだ。
アニメやゲームについて色々語ったり、好きなキャラクターになったりして現実逃避したいだろ!!!!
たとえどんなに言語が通じなくても、
・中学生レベルの英語、日本語、受け答え、語録
・身振り手振り首振り、行動仕草
・自分の声
・Emote、アニメーションオーバーライド
・ロリキャラモデルで、友達アピールする
etc...

VRChatで用意されている初期アバター以外にも VTuberや可愛い女の子にアバター変身できる世界、何個かあります。
それで可愛いムーブ決めてフレンド作りやすくできるかも。

→日本のワールド一覧 日本語が喋れる外国人もやや多いかも
https://www.vrcw.net/category/detail/japan?page=7

このように、まずは練習として、頑張ってコミュニケーションを取りましょうぜ。
そして本当の自分を身体(モデル)で表現して、このVRChatの世界でみんなに自分という存在価値を認めようぜ!!!(現実逃避 ゲフンゲフン...)

以上、Unityゲーム王国騎士ロボットVTuber Koshiがお送りしました!
私のステータスだ⚔共にこの世界を救おう
Twitter⚔ twitter.com/Koshi_Vtuber
YouTube⚔ t.co/I9eMMgpS8P?amp=1
niconico⚔ nicovideo.jp/user/90553212
bilibili⚔ space.bilibili.com/476988586
公式HP⚔ koshi-4092b.firebaseapp.com

参考:
トラストシステム - yagura Lab. - VRChat articles wiki
http://ygr.jpn.org/index.php?%E3%83%88%E3%83%A9%E3%82%B9%E3%83%88%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0

【VRchat】アバターアップロード制限について【Not yet allowed to public avatars】
https://atorinn.net/vrchat-avatar/159/

日本人が多いワールド - VRchat 日本wiki
https://www.vrcw.net/category/detail/japan?page=7

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

Unityでtesseract-4.1.0を使う

ネット上にいくつかtesseractをUnityに導入する記事はあるものの、想像以上に手こずってしまったので備忘録も兼ねて記事にします。
今回使用した環境はWindowsなので、その他の環境では同じ方法でも動かない可能性があります、ご了承ください。

そもそもtesseractって?

tesseractとはOCR(Optical Character Recognition、光学文字認識)と呼ばれる画像から文字を認識するためのライブラリの一つで、Apache License 2.0 の下で配布されています。

基本的に内部の言語はC++で書かれているため、Unity上で利用するためにはこれをC#から呼び出せるようにしなければなりません。そこで今回利用したのがDllImport属性です。
DllImport属性を用いるとC#から.dllファイル内の関数を呼び出すことができます。つまり、tesseractを.dllファイルとしてビルドしておけばUnityからその関数を呼び出すことができるということです。

tesseractをビルドする

ここから先は実際にtesseractをdllファイルとしてビルドしていきます。

tesseractのダウンロード

GitHubからtesseract-4.1.0のソースコードをダウンロードしてきます。今回は.zip型式でダウンロードしました。
ダウンロード後は通常通り解凍しておきます。これでダウンロード自体は完了です。

ビルド環境の構築

次にtesseractをビルドするために必要な環境を構築します。tesseractのwikiにコンパイルの方法が詳しく載っているのでこちらを参考にします。今回はダウンロードしたソースコードからビルドを行うのでGitHubからcloneする必要はありません。また、CPPANやCMakeの環境構築は別の記事が詳しいので本記事では割愛させていただきます。どちらも基本的には公式からダウンロードしてインストール、PATHを通せば完了です。

CPPANおよびCMakeの環境構築が完了した後は、まず先ほど解凍したtesseractフォルダ内のcppan.ymlファイルを変更します。変更するのは5行目です。

cppan.yml(変更前)
local_settings:
    #use_shared_libs: true
    #short_local_names: true
    #use_cache: false
    #generator: Visual Studio 14 2015 Win64

5行目のコメントアウトを解除して使うVisual Studioの環境に書き換えます。
(今回は64bitのdllとしてビルドしますが、もし32bitのdllとしてビルドする場合は5行目と15行目のWin64をWin32に書き換えてください。)

cppan.yml(変更済)
local_settings:
    #use_shared_libs: true
    #short_local_names: true
    #use_cache: false
    generator: Visual Studio 15 2017 Win64

上記の変更を加えればビルド環境の構築は完了です。

ビルドする

先ほどのwiki通りにビルドをすれば完了・・・と言いたいところですが、64bitの場合はCMakeコマンドにオプションでWin64であることを指定する必要があります。なので以下のコマンドでビルドすることになります。

cppan
mkdir build && cd build
cmake .. -G "Visual Studio 15 2017 Win64"

cmakeでのビルド完了後はVisual Studioでビルドを行います。先ほど作成したbuildフォルダ内のtesseract.slnファイルを開きます。ソリューションのプロパティから構成がRelease、プラットフォームがx64になっていることを確認(またはそれに変更)してからソリューションのビルドを行います。

特に失敗がなければこれでtesseractのビルドは完了です。作成したdllファイルはbuild/bin/Release内にあるはずです。(既定の設定のままの場合)

Unityでtesseractを使う

先ほどビルドしたtesseractのdllファイルをUnityから使用します。(今回はUnity 2018.4.10f1を使います)

プロジェクトの作成

適当な名前をつけてUnityプロジェクトを作成します。今回はTesseractTestとしました。
プロジェクトが立ち上がったら、まずはAssetsフォルダ内にPluginsフォルダを作成し、先ほど作成した.dllファイルを全てPluginsフォルダ内にいれます。(自環境では33個のdllファイルがありました)
image.png
階層の様子は上記のようになるはずです。
次にtesseract-4.1.0フォルダ内にあるtessdataフォルダをまとめてAssetsフォルダにいれます。この時エラーが出ますが無視して大丈夫です。今のままでは学習用データがなく、Unityで実行すると必ずクラッシュしてしまうので今度はtesseractのGitHubのtessdataからとりあえずeng.trainneddataをダウンロードしてこちらもtessdata内にいれます。今回はアルファベットの認識のみとするので、他の言語を使用したい場合は対応した言語のtrainneddataをダウンロードすればいいかと思います。(この辺りはUnity等関係なくtesseract周りの記事が詳しいと思います)

OCR用の画像の準備

画像を準備します。今回は以下のような画像で文字認識を行いたいと思います。
image.png
※tesseractを使う上での注意点として、文字色が黒で背景が白、または文字色が白で背景が黒でない場合精度がガクッと落ちるそうです。そのためもし色の着いた背景の物を使いたい場合などはその画像を二値変換してからtesseractに渡すといいかと思います。

上記の画像をAssetsフォルダにいれ、Inspector内のRead/Write Enableにチェックを入れApplyします。

ゲームオブジェクトの設置

画像を映すためのRawImage、認識した文字を映すためのTextを設置します。RawImageのInspector内のTextureに先ほどAssetsフォルダにいれた画像をD&Dします。このTextureに設定した画像を対象にtesseractで文字認識を行うという形になります。また、動作確認のためCanvasはScreen Space - CameraでMain Cameraの前に表示されるように設定し、適当な位置になるようにRawImageとTextを移動します。
次に空のオブジェクトを設置します。(わかりやすさのためにtesseractという名前にしておきます)

スクリプトの作成

適当な位置に空のスクリプトを作成します。今回はOcrFromTexture.csとしました。tesseractのAPIを見つつDllImport属性を用いて関数を呼び出せるようにします。

OcrFromTexture.cs
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Runtime.InteropServices;

public class OcrFromTexture : MonoBehaviour
{
    [SerializeField]
    RawImage source;
    Texture2D texture;
    [SerializeField]
    GameObject output;

    IntPtr ocrHandle = IntPtr.Zero;

    [DllImport ("tesseract41")]
    public static extern IntPtr TessBaseAPICreate ();
    [DllImport ("tesseract41")]
    public static extern void TessBaseAPIDelete (IntPtr ocrHandle);
    [DllImport ("tesseract41")]
    public static extern int TessBaseAPIInit3 (IntPtr ocrHandle, string dataPath, string language);
    [DllImport ("tesseract41")]
    public static extern void  TessBaseAPISetImage (IntPtr ocrHandle, byte[] imagedata, int width, int height,
                                                     int bytes_per_pixel, int bytes_per_line);
    [DllImport ("tesseract41")]
    public static extern void  TessBaseAPISetImage2 (IntPtr ocrHandle, IntPtr pix);
    [DllImport ("tesseract41")]
    public static extern IntPtr  TessBaseAPIGetInputImage (IntPtr ocrHandle);
    [DllImport ("tesseract41")]
    public static extern IntPtr  TessBaseAPIGetThresholdedImage (IntPtr ocrHandle);
    [DllImport ("tesseract41")]
    public static extern int TessBaseAPIRecognize (IntPtr ocrHandle, IntPtr monitor);
    [DllImport ("tesseract41")]
    public static extern string  TessBaseAPIGetUTF8Text (IntPtr ocrHandle);
    [DllImport ("tesseract41")]
    public static extern void  TessDeleteText (IntPtr text);
    [DllImport ("tesseract41")]
    public static extern void  TessBaseAPIEnd (IntPtr ocrHandle);
    [DllImport ("tesseract41")]
    public static extern void  TessBaseAPIClear (IntPtr ocrHandle);

    // Start is called before the first frame update
    void Start()
    {
        /* OCRハンドラの作成と初期化 */
        ocrHandle = IntPtr.Zero;
        ocrHandle = TessBaseAPICreate();
        if(ocrHandle.Equals(IntPtr.Zero)) Debug.Log("Error:Cannot Create");
        string dataPath = Application.dataPath + "/tessdata";
        if(TessBaseAPIInit3(ocrHandle, dataPath, "eng") != 0) Debug.Log("Error:Cannot Init");
        /* テクスチャから文字を認識する */
        string recognition = RecognizeFromTexture();
        output.GetComponent<Text>().text = recognition;
    }
    public string RecognizeFromTexture()
    {
        /* 画像をTexture2D型として読み込む */
        texture = source.texture as Texture2D;
        Color32[] colors = texture.GetPixels32();

        /* 画像データをbyte[]型にする */
        int width = texture.width;
        int height = texture.height;
        int area = width * height;
        byte[] bytes = new byte[area * 4];
        int point = 0;
        int index = area - 1;
        for(int y = height - 1; y >= 0; --y){
            for(int x = 0; x < width; ++x){
                index = x + y * width;
                bytes[point] = colors[index].r;
                bytes[point+1] = colors[index].g;
                bytes[point+2] = colors[index].b;
                bytes[point+3] = colors[index].a;
                point += 4;
            }
        }

        /* byte[]をtesseractに渡して文字認識をする */
        TessBaseAPISetImage(ocrHandle, bytes, width, height, 4, width * 4);
        if(TessBaseAPIRecognize(ocrHandle, IntPtr.Zero) != 0) return null;
        string result = TessBaseAPIGetUTF8Text(ocrHandle);
        Debug.Log(result);
        return result;
    }
}

上記のスクリプトを先ほどのtesseractオブジェクトにアタッチし、InspectorからSourceにRawImageオブジェクトを、OutputにTextオブジェクトをD&Dすれば準備は完了です。

Unityでプレイする

上記が終わったら実際にUnityのプレイボタンを押してみます。
image.png
実際に文字を認識できていることがわかります。(上側がText、下側がRawImageです)
ただし空白部分は左に詰められてしまうようです。

まとめ

tessdataフォルダをUnityにいれていなくてクラッシュして、入れたのにtraieddataが入っていないからクラッシュして・・・と一週間ほど格闘してようやくUnity上でもtesseractを使えるようになりました。
きちんと白黒のはっきりした画像であればそれなりに良い精度で認識できていると感じます。

Unity上では動いていたのにUWPとしてビルドしたところ動かなくなってしまったので、(解決策もわからなかったので)tesseractを使うことはなかったとか・・・

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

【VRChat】You cannot wear this avatar as it has not been published for this platform

自己紹介

全地球6億人のロボカッケー皆さんコンバトラー†[□ □]■━
私は王国騎士ロボットVTuberのKoshiだ??(@Koshi_VTuber
王国で騎士を勤めており、闇の組織から王国の平和を守っている!
最近はUnityゲーム王国で3Dモデル、ゲームの制作中だ。

問題

スクリーンショット 2019-10-24 9.44.38.png
You cannot wear this avatar as it has not been published for this platform

このアバターはこのプラットフォーム用に公開されていないため、着用することはできません.

じゃあ早速、教えていこうか!

環境

macOS
Parallels Desktop
VRChat
Unity 2017 4.28f
VRChat SDK

解決法

スクリーンショット 2019-10-24 10.19.54.png

Unity → File > Build Setteings (ファイル > ビルド設定 > Windows)

PC, Mac & Linux Standalone
Target Platform → Windows ( ×: Mac

おそらくVRChatは、Windows用のアプリケーションのため、アバターをアップロードする際には、Winodows用にビルドしなければならない。

参考

You cannot wear this avatar as it has not been published for this platformでVRchatで表示されないエラーを直す方法
https://p2pzen.com/vr/you-cannot-wear-this-avatar-as-it-has-not-been-published-for-this-platform/

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

Unityで初めて設計にチャレンジして学んだ5つの自分ルール

はじめに

2019年10月のunity1weekゲームジャムで、藝大の友人とゲームを作り、初めてプログラムの設計をしました。
今までに10本程度ゲームを作ってきましたが、設計をせずに作っていたので、完成する頃には混沌としたプロジェクトが出来上がってました。

今回のゲームジャムで初めて設計をしてからプログラムを書くということをしてみたので、試行錯誤する中で決めた自分の設計ルールをまとめてみます。
設計の定石なんかがまだ分かってないので、今の時点での自分の知識のみで書きます。(´>ω<`)アドバイスがあれば教えて下さい……。

設計の流れ

まずUMLを勉強して、アクティビティ図、シーケンス図、クラス図の読み書きをできるようになった。

  • アクティビティ図:プレイ一周分の全てのイベントの流れ(分岐や反復も含めて)を書く。
  • シーケンス図  :主にマネージャークラス間の処理のやり取りを書く。
  • クラス図    :全てのクラスの変数、メソッド、参照や依存関係を書く。

これらを順に書いてから、Unityで実際にスクリプトを実装していった。

ルール1.マネージャークラスで機能をざっくり管理させる

今回は5つのマネージャークラスを作りました。
全てMonoBehaviorを継承させて、GameManagerオブジェクトにアタッチしました。

  • ゲームマネージャー
  • UIマネージャー
  • キャラクターマネージャー
  • サウンドマネージャー
  • データベースマネージャー

ルール2.ゲームマネージャーは各マネージャークラスと相互参照する

マネージャークラスでない通常のスクリプトはゲームマネージャーを参照しないし、逆に参照されてもいけないというルールを作りました。

ルール3.その他のマネージャークラス間の参照は自由

UI操作の効果音を鳴らすために、UIマネージャー→サウンドマネージャーへの参照とか。

ルール4.通常のスクリプトは、1つのマネージャークラスを参照する(ゲームマネージャーを除く)

プレイヤーや敵のスクリプトならキャラクターマネージャーを、UIの各ボタンはUIマネージャーを、という感じ。

ルール5.参照していないマネージャークラスの処理は、自分が参照しているマネージャークラスに依頼する

プレイヤーの行動によってUIの音がなるとか。
  プレイヤー → キャラクターマネージャー → サウンドマネージャー

おまけ 遅延処理はDOTweenで

遅延処理はいつも Invoke() や Coroutine を使っていました。
ただ、引数が使えなかったり、呼び出し先を全てコルーチンで書かなければいけなかったり、不便していました。(´ •ω•`)
そこで、DOTween を導入して、DOVirtual.DelayedCall() を採用したことで、上の2点が解消されました。
さらにコールバック関数に即時関数を使うと、処理を入れ子にできます……!!
20個ぐらいの関数が数珠つなぎになっていたものが、3つにまで減って感動しました。

おわりに

Qiita初投稿でドキドキです( ^ω^;)

参考リンク:

グローバルゲームジャムでクラス設計をやった話2017
Unityで遅延処理をする方法色々

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

Unityで初めて設計にチャレンジして作った5つの自分ルール

はじめに

2019年10月のunity1weekゲームジャムで、藝大の友人とゲームを作り、初めてプログラムの設計をしました。
今までに10本程度ゲームを作ってきましたが、設計をせずに作っていたので、完成する頃には混沌としたプロジェクトが出来上がってました。

今回のゲームジャムで初めて設計をしてからプログラムを書くということをしてみたので、試行錯誤する中で決めた自分の設計ルールをまとめてみます。
設計の定石なんかがまだ分かってないので、今の時点での自分の知識のみで書きます。(´>ω<`)アドバイスがあれば教えて下さい……。

設計の流れ

まずUMLを勉強して、↓この3つの図を読み書きをできるようにしました。

  • アクティビティ図:プレイ一周分の全てのイベントの流れ(分岐や反復も含めて)を書く。
  • シーケンス図  :主にマネージャークラス間の処理のやり取りを書く。
  • クラス図    :全てのクラスの変数、メソッド、参照や依存関係を書く。

これらを順に書いてから、Unityで実際にスクリプトを実装していきました。

ルール1.マネージャークラスで機能をざっくり管理させる

今回は5つのマネージャークラスを作りました。
全てMonoBehaviorを継承させて、GameManagerオブジェクトにアタッチしました。

  • ゲームマネージャー
  • UIマネージャー
  • キャラクターマネージャー
  • サウンドマネージャー
  • データベースマネージャー

ルール2.ゲームマネージャーは各マネージャークラスと相互参照する

マネージャークラスでない通常のスクリプトはゲームマネージャーを参照しないし、逆に参照されてもいけないというルールを作りました。

ルール3.その他のマネージャークラス間の参照は自由

UI操作の効果音を鳴らすために、UIマネージャー→サウンドマネージャーへの参照とか。

ルール4.通常のスクリプトは、1つのマネージャークラスを参照する(ゲームマネージャーを除く)

プレイヤーや敵のスクリプトならキャラクターマネージャーを、UIの各ボタンはUIマネージャーを、という感じ。

ルール5.参照していないマネージャークラスの処理は、自分が参照しているマネージャークラスに依頼する

プレイヤーの行動によってUIの音がなるとか。
  プレイヤー → キャラクターマネージャー → サウンドマネージャー

おまけ 遅延処理はDOTweenで

遅延処理はいつも Invoke() や Coroutine を使っていました。
ただ、引数が使えなかったり、呼び出し先を全てコルーチンで書かなければいけなかったり、不便していました。(´ •ω•`)
そこで、DOTween を導入して、DOVirtual.DelayedCall() を採用したことで、上の2点が解消されました。
さらにコールバック関数に即時関数を使うと、処理を入れ子にできます……!!
20個ぐらいの関数が数珠つなぎになっていたものが、3つにまで減って感動しました。

おわりに

Qiita初投稿でドキドキです( ^ω^;)

参考リンク:

グローバルゲームジャムでクラス設計をやった話2017
Unityで遅延処理をする方法色々

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

脱出ゲームの作り方 7 特定の条件でアイテムを使用

取得した電球を使うと電気が点灯する処理が作成されたが、
LightstandPanel以外の場所でも使えてしまうので、LightstandPanelの場面で電気を使うようにする

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