【Unityシェーダ】ZWrite Onなのに描画順が崩れる場合の対応

問題

サーフェスシェーダで、半透明なシェーダを作っている際に描画順が崩れた。  

元コード↓

Shader "hoge/hoge"
{
    Properties
    { 
    }
    
    SubShader
    {
        ZWrite On

        Tags {
            "Queue" = "Transparent"
            "RenderType" = "Transparent"
        }
        
        CGPROGRAM
        
        #pragma surface surf Lambert alpha
        
        struct Input
        {
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
        }
        
        ENDCG
    }
    
    Fallback "Diffuse"
}

解決手段

下記のようにZWrite Onを記述していたところを、Passで囲って下記のようにする。

Pass {
    ZWrite On
    ColorMask 0
}

コード全体

Shader "hoge/hoge"
{
    Properties
    { 
    }
    
    SubShader
    {
        Pass {
            ZWrite On
            ColorMask 0
        }

        Tags {
            "Queue" = "Transparent"
            "RenderType" = "Transparent"
        }
        
        CGPROGRAM
        
        #pragma surface surf Lambert alpha
        
        struct Input
        {
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
        }
        
        ENDCG
    }
    
    Fallback "Diffuse"
}

ffmpegで動画のアスペクト比を変更する

下記のように利用する.

$ ffmpeg -i input.mp4 -vf scale=1920:1080,setsar=1 output.mp4

画像等の場合はsetsar=1が不要だが,動画では必要となる.

1920x1080(iPhone 8+)の動画を,2688x1242(iPhone 11 Pro Max)にリサイズした結果は以下.

f:id:tmls:20210412213313p:plain
1920 x 1080

f:id:tmls:20210412213724p:plain
2688 x 1242

uGUIのTextにルビをつける【Unity】

ルビ振り問題

uGUIで漢字にルビをつけたいとき,Unityでは結構面倒です.
普通にやると,新しくTextオブジェクトを作成して,漢字の上に位置を合わせるしかありません.
これを全部の漢字にやっていては,あまりに時間がかかる上に,変更に耐えられません.
そこで,ルビふりをもっと楽にする方法を紹介します.

使い方

[漢字]<かんじ>という形式で書くことで,ルビを設定できます.

f:id:tmls:20210411134456p:plain

f:id:tmls:20210411134545p:plain

導入方法

  1. Unityに後述のスクリプトをインポートもしくは,コピペする
  2. uGUIのTextがついたプレファブを作成する(ルビ用のTextとして利用)
    • TextのAlignmentは縦横どちらも中央寄せに
    • Textのフォントサイズは小さめに
  3. ルビをふりたいTextに,1のスクリプトをつけ,2のプレファブを設定する
// BEGIN MIT LICENSE BLOCK //
//
// Copyright (c) 2017 dskjal
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
//
// END MIT LICENSE BLOCK   //
/*
 * *注意*
 * 改行の処理はしてない.ルビを必要とする部分が途中で改行されないよう処理する必要がある.
 * http://dskjal.com/unity/detect-unity-ugui-break-pos.html を参照.
 */
/*
 * 設定方法
 * uGUI の Text にこのスクリプトをつける.
 * テキストのセンタリング設定をした uGUI の Text のプレハブを作り TextPrefab にセット
 * プレハブのフォントサイズをテキストのフォントサイズの 1/2 ぐらいにする
 */
using UnityEngine;
using UnityEngine.UI;
using System.Text.RegularExpressions;
using System;
using System.Collections.Generic;

[RequireComponent(typeof(Text), typeof(RectTransform))]
public class RubyText : MonoBehaviour {

    Text text;
    RectTransform rt;
    public GameObject TextPrefab;  // テキストはセンタリングしておくこと
    private const float rubyHeight = 0.7f;

    class RubyPos {
        public int start;   // ルビの開始インデックス
        public int end;     // ルビの終了インデックス
        public string ruby; // ルビ
        public RubyPos(int start, int end, string ruby) {
            this.start = start;
            this.end = end;
            this.ruby = ruby;
        }
    }
    void Start() {
        text = GetComponent<Text>();
        rt = GetComponent<RectTransform>();

        var rubyPos = new List<RubyPos>();
        var matches = Regex.Matches(text.text, @"\[(.*?)\]<(.*?)>");
        // removed text count
        var rmtxt = 0;
        foreach(Match match in matches){
            var match1 = match.Groups[1];
            var match2 = match.Groups[2];
            // remove markdown texts and insert match1
            text.text = text.text.Remove(match.Index - rmtxt, match.Length);
            text.text = text.text.Insert(match.Index - rmtxt, match1.Value);
            // remove text count 1([)
            rmtxt += 1;
            rubyPos.Add(new RubyPos(match1.Index - rmtxt, match1.Index - rmtxt + match1.Length - 1, match2.Value));
            // removed text count is 2(]) + 2(<>) + (ruby count)
            rmtxt += 1 + 2 + match2.Length;
        }

        var generator = new TextGenerator();
        // テキストのレンダリング位置の計算
        var settings = text.GetGenerationSettings(rt.sizeDelta);
        settings.scaleFactor = 1;
        generator.Populate(text.text, settings);

        // 各文字のレンダリング位置を記録した文字配列の取得
        var charArray = generator.GetCharactersArray();
        foreach (var ruby in rubyPos) {
            var start = charArray[ruby.start].cursorPos;
            var end = charArray[ruby.end].cursorPos;
            end.x += charArray[ruby.end].charWidth;

            PlaceRuby(start.x + (end.x - start.x) / 2f, start.y + charArray[ruby.start].charWidth / 2 * rubyHeight, ruby.ruby);
        }
    }

    // TextPrefab をインスタンス化して配置する
    void PlaceRuby(float x, float y, string text) {
        var o = GameObject.Instantiate(TextPrefab);
        o.name = text;
        o.transform.SetParent(this.transform);
        var prt = o.GetComponent<RectTransform>();
        prt.localPosition = new Vector3(x, y, 0f);
        prt.localScale = new Vector3(1, 1, 1);

        o.GetComponent<Text>().text = text;
    }
}

このスクリプトは,↓の方が公開しているものをもとに,改良を加えています.

dskjal.com

最終的に↓のように設定されていればOKです.

f:id:tmls:20210411134411p:plain
最終的なコンポーネント設定例
f:id:tmls:20210411140554p:plain
ルビとなるプレファブ(手順2)の設定例

UnityのビルドをSteamにアップロードする方法

公式サイトからSDKをダウンロード

↓のサイトから最新のSteamworks SDKをダウロードします. zipを解凍後,toolsフォルダにあるSteamPipeGUI.zipも解凍して,SteamPipeGUI.exeを起動します. sdk > tools > ContentBuilder > content 内にUnityのビルドで出力されたファイルを入れておきましょう.

https://partner.steamgames.com/dashboard

f:id:tmls:20210321201552p:plain

f:id:tmls:20210321201601p:plain

App IDを入力します.
これはSteamworksで,ゲームタイトル名(App ID)という表記で確認できます.

App Descriptionには好きな言葉を書きます.

Add Depotを押して,Build Pathの横のBrowseを押し,先ほどビルドファイルを入れたcontentフォルダを指定します.
Steamworks SDK Content Builder PathにContentBuilderフォルダを指定します.
SteamworksのアカウントIDとパスワードを入力します.

中央右あたりにあるUploadボタンを押します.
SteamGuardコードを聞かれたら,メールに届いてる文字を入力しましょう.

f:id:tmls:20210321235359p:plain

アップロードの確認

f:id:tmls:20210321210511p:plain

Steamworksに移動し,SteamPipe > ビルドを選択します.
うまくいっていれば,ここにビルドが表示されるはずです.

「アプリブランチを選択」を押し,defaultに変更して,変更をプレビューをクリック.
「今すぐビルドをライブに変更」を押すことで,ビルドを有効化できます.

起動オプションの設定

Steamworksにて,インストール > インストール全般 に移動します.
起動オプションの欄で,「新しい起動オプションを追加」を選択します.
実行可能ファイルの項目に,Windows desktop 64-bit.exeのようにゲームの実行ファイルを指定します.

テスト

公開タブに移動し,「公開の準備」→「Steamに公開」→「本当に公開する」と押していきます. これはビルドが公開されるだけなので,まだリリース前であれば自分のアカウント限定で公開されます.

βテスト

Steamworksのアカウント管理者以外の人がプレイするためには,インストール用のキーを発行します.
これはSteamworksの「キーの管理」から行います.
説明に従っていけば問題なく作れると思います.
キーの発行は申請をだしてから2~3日かかると書いてありますが,実際には6時間後くらいに承認,発行されました.

あとは,発行されたキーをSteamで入力すればインストールできます.

公式ドキュメント

partner.steamgames.com

Windowsの個人用ファイルを保持した初期化の挙動

消えるもの

  • インストールしていたものはアンインストールされた
  • アカウント情報も初期化された
  • WSLは消えた
  • Windows Terminalも消えた

消えないもの

  • ドキュメントフォルダはもちろん,ダウンロードフォルダやC直下のファイルも全て残っていた
  • Windows Insider Programも入ったまま

Ubuntuから始めるunixporn

私のデスクトップがこちらです。

f:id:tmls:20201203001046p:plain

ちょっとカッコいいですよね。
こんな感じで、デスクトップを自分好みにカスタマイズするのを巷ではunixpornと呼んでいます。
カスタムの幅が広いので大抵の場合はLinuxを使うことが多いです。

今回はとりあえずgruvbox darkというテーマで整えてみます。
テーマを統一するのは大事。

Ubuntu

今回は初めてということもあり、最も扱いやすいUbuntuを使いたいと思います。
慣れている人は、Linux Mint やArch Linuxを使った方がもっと本格的な感じになります!

i3 (Regolith)

タイル型ウィンドウマネージャーというものを導入します。
これは、各ウィンドウが重ならないようにタイル状に並べてくれます。

有名なのは、i3やAwesomeで、今回はi3を使うことにします。

でもi3の導入は結構大変で、初期設定も複雑です。
そこでUbuntu用に簡単に始めれるようにしてくれた、Regolithというものがあります。

基本的には下記でインストール完了します。

$ sudo add-apt-repository -y ppa://kgilmer/regolith-stable
$ sudo apt update
$ sudo apt install regolith-desktop

詳しくはこちら。

malkalech.com

Ubuntu Theme

Ubuntuのテーマを導入しましょう。
Tweaksという設定ツールを使うと簡単に設定が変えられます。

sudo apt install gnome-tweaks

gruvboxのテーマはこちらが良さそうです。

github.com

↓のコマンドでインストールできます!

git clone https://github.com/jmattheis/gruvbox-dark-gtk ~/.themes/gruvbox-dark-gtk

f:id:tmls:20201203140321p:plain

fish

ターミナルの見た目をかっこよく出来るfishを使ってみましょう。
fisherでgruvboxのテーマをインストールできます。

fisherのインストール

curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
fisher install Jomik/fish-gruvbox

さらに、

theme_gruvbox dark

を実行するとテーマが適用されます。

~/.config/fish/config.fishtheme_gruvbox darkを記述しておけば、ターミナルの起動時に初期設定でテーマを変えてくれる。

www.virment.com

デスクトップ背景

背景は自由に設定して良いですが、ダーク系なら暗めのものを用意すると良いかもしれません。
minimalist wallpaperあたりで検索すると私好みのものがたくさん出てきます。

Chrome Theme

よく使うブラウザがChromeならChrome Themeを入れましょう。
今回はgruvbox themeを入れました。

chrome.google.com

Chrome Dark Mode

ダークモードが好きなら、Chrome拡張でブラウザを黒くしてくれる機能を導入しましょう。
Dark Readerがおすすめです。
gruvboxなら、セピアの割合を大きくするといい感じになるかもしれません。

chrome.google.com

Neofetch

ターミナルでUbuntuロゴマークを表示してくれるやつです。
f:id:tmls:20201203141127p:plain

www.omgubuntu.co.uk

tty-clock

ターミナルで時計を表示してくれます。

f:id:tmls:20201203141425p:plain

zoomadmin.com

cava

ターミナルでPCの音をカッコよく表示してくれます。

f:id:tmls:20201203141550p:plain

github.com

ytop

ターミナルでPCの使用状況をカッコよく表示してくれます。

github.com

mebee.info

f:id:tmls:20201203142608p:plain

次のステップ

いかがでしたか。 デスクトップはカッコよくなりましたか?
デスクトップがカッコいいだけで、ちょっとテンション上がりますよね。

今回紹介したのは、ほんの一例にすぎません。
この世界にはもっともっとカッコいいデスクトップがあるでしょう。

気になったら、unixpornで検索してみてください。
Redditでは多くの投稿があり、その人が使っているツールがコメントで残されています。

www.reddit.com

良さそうなものを見つけたら、使ってみましょう。
自分好みのデスクトップにアレンジしてみてください!

Ubuntuで固定ip

/etc/netplan/99-netcfg.yamlというファイルを作成し,下記の内容を記述する.

network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp4s0:
      addresses: [192.168.3.11/24]
      gateway4: 192.168.3.1
      nameservers:
        addresses: [8.8.4.4]

その後,下記コマンドを実行すると反映される.

$ netplan apply

参考