キノコの自省録

日々適当クリエイト

Krita(G'MIC)で雲模様

木目や岩など、自然物のテクスチャによく使われるPhotoshopの雲模様ですが、KritaでもG’MICを使って描くことが出来るようになりました。

G'MICのダウンロードと設定

雲模様の描画には、G'MICのver2.8.3以降が必要です。

Kritaには元々G'MICが同梱されていますが、この記事を書いている2020年2月8日現在のKrita(ver4.2.8)に同梱されているG'MICはver2.7.1ですので、最新バージョンを別途手に入れる必要があります。 もしお使いのG'MICが2.8.3以降なら、この章は読み飛ばしてください。

ダウンロードはこちらから。

G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing

G'MIC plug-in for Kritaから、zip archiveをダウンロードして解凍してください。

解凍したフォルダのパスを、Kritaに設定します。設定->Kritaの設定を変更を選択してダイアログを表示して、一番下の項目G'MIC Qt統合に、先ほど解凍したG'MICのパスを設定します。

f:id:kinokorori:20200207231443p:plain
Kritaの設定を変更

間違っても、KritaのbinフォルダにG'MICをコピーしてはいけません。Kritaごと起動しなくなります。

※私はやってしまいました。

雲模様を描く

まずはサンプル。256×256の画像を用意して、灰色(0x808080)に塗りつぶしておきます。そのレイヤーに対して、フィルタ -> G'MIC-Qtを開始を実行します。

次に、G'MICが起動したら、Degradationsから、Noise[Perlin]を選択します。

ノイズのパラメータを次のように設定します。

  • Random Seedはなんでもよい
  • 1st AmplitudeとScaleを32に
  • 2nd AmplitudeとScaleを16に
  • 3rd AmplitudeとScaleを8に
  • 4th AmplitudeとScaleを4に
  • ChannelsをYCbCr[Luminance]に

f:id:kinokorori:20200207233350p:plain
Perlin Noise Parameter

これでフィルタを適用すると、こんな感じの雲模様が生成されます。

f:id:kinokorori:20200207234314p:plain
G'MIC製 雲模様

大体Photoshopに近い雲模様が作れたのではないかと思います。

Perlin Noise

要するに、雲模様というのはPerlin Noiseで出来ています。Perlin Noiseはその名の通りノイズなのですが、単純なランダムノイズではなく、複数のノイズ波の合成で出来ています。 今回のように、サイズと周期の大きい波を基準(今回は32)として、その半分(16)、そのまた半分(8)、さらにまた半分(4)のノイズ波を合成すると、Photoshopのような雲模様になります。

フォトショ使いの人は、火や波を作ったりと色々な応用をしたのではないかと思いますが、実際Perlin Noiseは自然物の表現(特に3D)によく用いられます。自分も昔、連続作成したPerlin Noiseを火の画像に対してDisplacement Mapを取ることで、火の揺らぎを表現したことがあります。

G'MICの場合、パラメータを自分で設定しなければならない手間はありますが、逆に色んなことが出来ます。

例えば、木目なんかは無理やり拡縮しなくても、最初からアスペクト比を調整すれば、すぐに作れてしまいます。

f:id:kinokorori:20200208151754p:plain:w256
G'MIC製木目テクスチャ

色も2値ではなく、様々な色の雲模様が生成できます。例えば、ChannelsをYCbCr Luminanceのような輝度ではなく、RGBAに指定すると、マーブルのような雲模様が生成できます。これで生成した雲模様を使って水中の青を表現すると、ちょっとリッチ感が出せます。

f:id:kinokorori:20200208152345p:plain
シンプルなブルーバック

f:id:kinokorori:20200208152505p:plain
マーブル雲模様のリニアライト合成

グラボの換装と支え棒の自作

思うところがあって、グラフィックボードRTX2060SUPERを買いました。Amazonで45000円くらいでした。実はこんな高性能なグラボを買うのは生まれて初めてです。

それにしてもグラボって物理的に重いんですね。接点の板がバキっといきそうなくらい。適当に針金で引っ張ろうかと思ったのですが、針金を通せそうな穴が全く空いてません。

調べると、グラボ支え棒みたいなものが専用品で売ってるとか……。

その辺に売ってそうにないけど届くの待ってる暇はないし、ちょっと高い、ということで、東急ハンズで代替になりそうなものを探しました。

アジャスター

天井の突っ張り棒や、机の脚に使うねじ巻き式の部材がありますが、あれアジャスターと言います。アジャスターを使って、天井の突っ張り棒の要領で、地面からグラボを支える道具を作りました。

まあ正直作りましたというレベルではありません。部品を2個買っただけです。

f:id:kinokorori:20200203012310j:plain
アジャスターとベース

アジャスターは277円、ベースは400円でした。ハンズ価格ということで少々割高なので、別のところで買えばもっと安く手に入るはずです。買ったアジャスターは頭にフェルトがついているので、グラボを傷つけずに済みます。

アジャスターベースは正直適当な木を買ってドリルで穴開けでも良かったのですが、垂直に穴あけが必要なことと、部屋汚れるから嫌ということで、最初からねじ穴の合うベースを買いました。まあそんなに高くないですし。

取り付けた写真はこんな感じになります。

f:id:kinokorori:20200202180545j:plain

このグラボは玄人志向のGALAKUROモデルですが、ファンとファンの間が意外と空いているため、ちょうどフェルトアジャスターが取り付けられます。写真では、グラボがやや傾いているように見えますが、実際は真っ直ぐになっています。

ベースを接着固定するのであれば、ベースの裏に磁石のシートを貼る、両面テープを貼る、マジックテープを貼る、適当なテープで止める辺りが良いかと思います。ちなみに、上の写真は特にベースを接着していないのですが、この状態で横にしてもズレません。(今は養生テープで止めています。)

Amazonで買うなら

アジャスターですが、フェルトアジャスタ―で検索すると良いです。買ったのは下のと同等品です。この商品のねじはM10ですが、M6やM8のものもありますので、お好みで。


フェルトアジャスター 【プラパート】 A400-32M10 M10×Φ32×L31.5 ベージュ

座金はアジャスターベースで検索すると良いです。


LAMP ステンレスアジャスターベースM10用(200-140-502)

198 + 239 = 437円ですね。

と、ここまで紹介しておいてなんですが、実際にホームセンターに行って調べてきた方が早いです。(送料もかかりますし……)

特に、必要な高さがマシンによって異なりますので、必要な部材も当然変わってきます。今回、自分のPCは大体高さ4cmほどでしたので、この組み合わせになりました。 ちなみに耐荷重はスペック表に書いてある通り、140kgです。グラボが重いといっても、家具レベルの部品から見れば屁みたいなものです。

多少グラボのケースが傷ついてもいいなら、ボルトが一番種類があります。ボルトを使うにしても、座金はちゃんとしたものを使用した方が良いと思います。グラボファンが回転振動しているため、不安定だとズレることが想定されます。

※冒頭で紹介した感じの支え棒なら、ジョイント金具とアングルの組み合わせか、マルチブラケット使ったらできそうな気がします。

プレーヤーに向かってくる弾を撃つ、照準に向かって撃つ

中高生向けのゲームプログラミング用数学の内容です。

敵が真っ直ぐ自分の方向に向かって弾を発射したり、自機が照準に向かって弾を発射したりといった実装をしたいことは多々あると思います。 これ自分が中学生だか高校生くらいの時、実装方法がわからなかったんですよね(なんとなーくそれっぽく動く実装していました)。 昔できなかった自分を思い出して、ちょっとTips書いてみました。

図解と物凄く簡単な実装

超シンプルな実装

f:id:kinokorori:20200106232329p:plain
弾発射

自機が(0, 0)の位置に、敵が(15, 15)の位置にいます。敵が自機に向かって弾を発射したいと思います。弾の速度はどう設定すれば良いでしょうか?

f:id:kinokorori:20200106232752p:plain
-15,-15で動く

弾の速度(velocity)を(-15, -15)に設定すればプレーヤーの方向に飛びます。1フレームで(-15, -15)の場合、絶対に直撃します。

超シンプルな実装2

f:id:kinokorori:20200106233305p:plain
場所移動

では、ちょっと移動して、自機が(1, 6)、敵が(12, 15)の位置にいた場合、どうすれば真っ直ぐ飛ぶでしょう?

要するに、x=12から1へ, y= 15から6へ移動させれば良いので、vx=1 - 12=-11, y=6-15=-9となり、弾の速度を(-11, -9)に設定すればプレーヤー方向へ真っ直ぐ飛びます。

弾の速度を調整する

しかしこれだと、弾速がまちまちになります。簡単に言えば、敵が遠く、例えば(50, 100)にいるときは、(-50, -100)の猛スピードで飛んできますが、敵が近く、例えば(1, 2)にいるときは、(-1, -2)のゆったりスピードで飛んできます。これでは困ります。

要するに、距離に応じて速度が変わるのが困るので、距離で割って距離の影響を取り除いてあげれば良いのです。(-50, -100)の場合の距離は、

 \sqrt{(-50)\times(-50)+(-100)\times(-100)} = \sqrt{12500} (≒ 111.8)

なので、弾の速度を (-\frac{50}{\sqrt{12500}}, -\frac{100}{\sqrt{12500}})とすると、距離の影響が排除できます。

(-1, -2)の場合の距離は、

 \sqrt{(-1)\times(-1)+(-2)\times(-2)} = \sqrt{5}

なので、弾の速度を (-\frac{1}{\sqrt{5}}, -\frac{2}{\sqrt{5}})とすると、距離の影響が排除できます。

これで、 (-\frac{50}{\sqrt{12500}}, -\frac{100}{\sqrt{12500}}) (-\frac{1}{\sqrt{5}}, -\frac{2}{\sqrt{5}})は、進行方向は違えど、速度は同じになりました。

ちなみに弾の速度(-50, -100)や(-1, -2)は、純粋な大きさだけでなく向きを持っていますね。これをベクトルと言います。このベクトルの向きをそのままに、大きさだけを1にしたものを単位ベクトルと言います。 (-1, -2)を単位ベクトルに変換したものが (-\frac{1}{\sqrt{5}}, -\frac{2}{\sqrt{5}})ということです。数学の授業で習います。

単位ベクトルに対して所定値を乗算することで、スピードが調整できます。例えば、 (-\frac{1}{\sqrt{5}}, -\frac{2}{\sqrt{5}})が遅すぎるので速度10倍にしたいなーという場合は、

 (-\frac{10}{\sqrt{5}}, -\frac{20}{\sqrt{5}})

とすれば良いということです。

3次元の場合は?

3次元でも4次元でも同じです。例えば、(2, 4, 5)の方向に弾を撃つ場合、(2, 4, 5)の距離は(\sqrt{2^ 2 + 4^ 2 + 5^ 2}) = \sqrt{45} なので、

単位ベクトルは(\frac{2}{\sqrt{45}}, \frac{4}{\sqrt{45}}, \frac{5}{\sqrt{45}})です。この単位ベクトルに任意の数値を掛けると、速度調整ができます。

MoveTowards

ちなみにUnityの場合は、MoveTowards()という便利なメソッドが用意されています。

Fungusのメッセージダイアログを任意のボタンで送る方法

大変便利なFungusのSayDialogですが、ちょっとキー設定で困ってしまいました。

f:id:kinokorori:20190511021103p:plain
FungusのSayDialog

FungusのSayDialogは、デフォルト設定の場合、キーボードだとSpaceやEnterでしか送ることができません。要するに割と良くアクションキーとしてアサインされるZキーなどでは次へ進ませることができませんが、特にその辺りを変更できそうな箇所も見当たりません。

そもそもどこでボタンが定義されているのか

全然情報が見つからなくて、コードから追っかけました。結局こんなところにありました。

f:id:kinokorori:20200106221916p:plain:w300
SayDialogのインスペクタ

これはSayDialogを作成した時にデフォルトで設定されるインスペクタです。この中にあるDialogInputが入力処理を司っています。

DialogInput.csのUpdateメソッドの中に、該当コードがあります。めでたしめでたし。

if (writer != null && writer.IsWriting)
{
    if (Input.GetButtonDown(currentStandaloneInputModule.submitButton) ||
          (cancelEnabled && Input.GetButton(currentStandaloneInputModule.cancelButton)))
    {
           SetNextLineFlag();
    }
}

※上に書いた通り、全然情報なかったんですが、常識なんでしょうか……?

StandaloneInputModule

上記コードは何かというと、currentStandaloneInputModule.submitButtonが押されたときか、currentStandaloneInputModule.cancelButtonが押されたときに、次に進むというコードが書かれています。

このcurrentStandaloneInputModuleなるメンバ変数は、UnityEngine.EventSystems.StandaloneInputModuleインスタンスです。要はUnityの機能です。submitやらcancelやらはどこで設定されているのかというと、ここです。

f:id:kinokorori:20200106223029p:plain
キーアサイン変更

InputManagerですね。ノットユーザーフレンドリーで有名な。

ゲーム中にキーコンフィグを作りたい場合はどうすれば?

起動時にわけのわからないタブで設定を強いるというのは、そもそもUIとして大問題で、ゲームの品質を下げてしまいます。なので、普通はキーコンフィグ画面をゲーム内に設けると思います。

ただ、デフォルトのSayDialogがStandaloneInputModuleのSubmitとCancelを参照している以上、ゲーム内でキーコンフィグを作った場合、FungusのSayDialogに関しては、次のどちらかの対応を取る必要があります。

  1. ゲーム内でInputManagerを再生成する
  2. DialogInputを継承したクラスがUpdate処理をオーバーライドする

1は大変辛いです。2は大変楽です。なので、2でいきましょう。DialogInputを継承したMyDialogInputは、具体的にはこんな感じになります。

public class MyDialogInput : Fungus.DialogInput {
    protected override void Update() {
        base.Update();
        if (EventSystem.current == null) {
            return;
        }

        if (writer != null && writer.IsWriting) {
            if (Input.GetKeyDown("Z")) {  //ここを好きなキーに設定する
                SetNextLineFlag();
            }
        }
    }
}

base.Update()でDialogInputのUpdate()を呼び出してますが、base.Update()が呼び出されると、SubmitやCancelでも送れてしまうので、不都合がある場合はDialogInput.Updateの処理をべた書き(コピペ)して、DialogInput.Update()を呼び出さずに隠ぺいしてしまうと良いでしょう。

実装が終わったら、MyDialogInputをSayDialogのインスペクタに追加します。

f:id:kinokorori:20200106225427p:plain
MyDialogInputを追加

これで、Zキーを押してダイアログを送ることができるようになると思います。

ライセンス

f:id:kinokorori:20190508004005p:plain

この作品はユニティちゃんライセンス条項の元に提供されています。

なお、FungusはMITライセンスです。

ブロックチェーンの分かりにくいであろう部分を説明してみる

ブロックチェーンによる革命が起こるまでにあと10年かかる理由 - ZDNet Japan

ブロックチェーンの普及まであと10年かかる、という記事が出ていますが、なんというか、そもそもブロックチェーンって理解が及んでない気がします。 私もよく「ブロックチェーンって結局何?」って聞かれます。ビットコインブロックチェーンの1実施形態なのですが、ビットコインブロックチェーンと混同する人が非常に多く、 それがまたわかりにくさに拍車をかけている気がします。

大抵の場合、いくつかのキーワードは点でわかるんですけど、これが線にならないんですよね。例えば、だいぶキーワードとして浸透した感のある「マイニング」ですが、物凄い計算量がいることはみんな知っています。でも、なぜこれが必要なのかわからない。実はこの作業はビットコインだとマストなのであって、別の実施形態では必要がないということも知られてません。分散台帳もそうです。P2Pで、各ノードが台帳を持っているということはみんな知ってますが、実際に台帳がどうなっているのかあまり知られてません。

そんなわけで、個人的にわかりにくいんじゃないかなーと思った知識を線で繋いでみます。

キーワード

大体みんな知ってるブロックチェーン、というかビットコインの中身はこんなところではないでしょうか?

「通常サーバクライアントで実装するアプリケーションやサービスを、P2Pで行う。」

「 取引ログは分散台帳に残っており、全てのP2Pノードが分散台帳を保持している。」

「分散台帳はブロックに分かれており、ブロック同士はハッシュチェーンで連結されている。」

ビットコインは発掘者(マイナー)にたくさん計算させるマイニングを行わせることで、P2Pでの合意形成を可能にしている。」

「マイニングに成功すると多額の報酬が支払われる」

なんかわかるようなわからないような、ですよね。とりあえずこれらの分散した知識を、ビットコインの実装を例に鎖でつないでみます。

サーバクライアントとP2P

サーバクライアントではなくP2Pで処理を行うことについては説明するまでもないと思いますが、ブロックチェーンを活用するメリットもここに集約されています。メリットについては後程説明します。

分散台帳

台帳ファイルはノードそれぞれが持っていますが、基本的に「全員同じ台帳」になるように更新します。 たまに、「それぞれのノードが各々の台帳を持っていて、全部足すと1つの台帳が出来上がる」と思っている人がいますが、誤りです。

分散台帳には取引(トランザクション)を記録します。台帳のページ毎に、複数の取引が一度に記載されます。このページをブロックと言います。トランザクションとは、例えば「AさんがBさんに100円送金」みたいなものと考えておけばよいです。これが1トランザクションです。ビットコインの場合は2500トランザクションくらい一度にブロックに書くことができます。

未使用のブロックにトランザクションを詰め込み、それを承認して分散台帳に正式に登録します。要するにハンコを押します。このハンコを押されたブロックをハッシュで繋いでいくのでブロックチェーンと言われます。このハンコ押しはどのノードでも行えますが、そのためにはちょっとした作業が必要です。それがProof of Workです。

f:id:kinokorori:20191016232322p:plain
ノード、(分散)台帳、ブロック(チェーン)

コンセンサス

普通、ハンコは責任者が押します。みんながみんなハンコを簡単に押せるようにすると、取引Aはあっちでもこっちでも承認されたとか、取引Bと取引Cが同時に成立して、残高がマイナスになったという、状態の不整合が発生します。これをビザンチン障害と言います。

ビットコインではノード全てがハンコを押す資格を持っていますので、ビザンチン障害が発生する環境にあります。その対応策として、ビットコインではProof of Work(PoW)という計算作業を承認者に行わせて、微妙な時間的ズレを作り出しています。

PoWは何をするかと言うと、ブロックのハッシュ計算に利用するNonce(ナンス)という32ビットの数値を、条件が合うまで延々と探し続けさせます。具体的にはブロックのハッシュ値の先頭16桁が全部0になるNonceを探せ、といった具合です。これがいわゆるマイニングです。最初に見つけ出した人には報酬が支払われます。2019年10月現在では12.5btcです。ちなみに、マイニングは平均10分かかるようにアルゴリズムで自動的に調節されます。

承認されたブロックはP2Pネットワークを通じて拡散されます。新しい台帳を受け取ったノードは、自分の台帳と比較よりもブロックチェーンが長い場合、新しい台帳を採択して更新します。

平均で10分ということは、5分で見つかることもあれば、15分でも見つからない可能性があります。つまり、ある人がNonceを見つけた時、同時に別の人がNonceを見つける確率はかなり低くなります。この平均で10分かかる計算作業による物理的時間のズレの創出と、長いブロックチェーンの採択によって、P2Pネットワークでも合意形成が保たれるという寸法です。この合意形成アルゴリズムをナカモト・コンセンサスと言います。

f:id:kinokorori:20191016232801p:plain
長いものに巻かれよ

ファイナリティ

ほぼ同時に承認が発生すると、ブロックが分岐(フォーク)してしまいます。しかしこれも、時間が解決します。そのうちチェーンの長さに差が生じてきて、片一方はなかったことにされます。

つまり、1回承認されたトランザクションであっても、覆されてしまう可能性があるということです。一般的には6承認、つまり、後ろに6つブロックが繋がれば、承認が覆されることはないとされています。何回後ろに承認が続けば事実上OKとするかをファイナリティと言います。

ちなみに、平均10分承認にかかるということは、6承認には1時間かかるということです。長いですよね。

スケーラビリティ

トランザクションの承認に平均10分、一度に承認できる数が2500くらい、ということは、1分250取引、1秒60取引程度しか捌けないということです。その処理以上のトランザクションが追加されると、処理しきれず溜まっていく一方となります。

スケールアップもスケールアウトも容易ではないので、ブロックチェーンにとってスケーラビリティの確保が最も困難な課題となっています。スケールアップの場合、トランザクションの承認数を増やすことになります。要するに、平均10分かけさせていたPoWを1分にするとかですね。1分に短縮すれば、当然10倍承認が可能になりますが、ファイナリティの方で問題が出ます。スケールアウトの場合、ノードをなんらかのエリアにわけることになりますが、エリア間での取引や整合性が課題になります。

最近では、ライトニングネットワークという取引アルゴリズムが、この問題の解決のカギになるとして注目されています。

取引所とかはなんなんだ

ビットコインはノードを立ち上げれば誰でも取引ができますが、上述したように、1取引に60分はかかります。見やすいUIが付いているわけでもありません。 また、ファイナリティに60分ということは、例えばビットコインをタクシーの支払いに使うとなった場合、承認されるまで60分かかるので、その間降車できません。

ということでビットコインP2Pネットワークだけでは使い勝手が悪いため、外部サービスが構築されています。このサービスは通常のサーバクライアントシステムで実装されているというのが一般的です。

ブロックチェーンのメリット

メリットはサーバクライアントからP2Pに変更した部分にある、と前述しました。具体的には、

  • シェアリングが用意
  • 改ざんが極めて困難
  • ダウンタイム・ゼロ
  • 安価
  • 管理者不在

などのメリットがあると言われています。どの部分を最も魅力と感じるかは人に寄りけりかと思いますが、特にシェアリングと管理者不在が大きいかと思っています。管理者不在と言うことは、CtoCビジネスの拡大が今後期待できるということです。

EthereumとHyperledger

以上がビットコインの話ですが、ビットコインは基本的にお金のやり取りしか扱えません。しかし、ブロックチェーンの有用性に目を付けた人たちが、ビットコイン以外のブロックチェーン基盤を開発しました。有名なのはEthereum(イーサリアム)とHyperledger(ハイパーレッジャー)です。

イーサリアム

イーサリアムはETH(イーサ)という独自通貨を持っています。イーサリアムの特徴は、なんといってもスマートコントラクトだと思います。スマートコントラクトは、取引にスクリプトコードを実行させるという機能で、これにより、通貨の移動だけでなく、「物件のステータスの変更」や、「絵画の所有者の変更」といったことが可能になります。スマートコントラクトを利用したアプリケーションをDAppsと言います。

DAppsで最も人気なのがゲームです。普通のゲームの場合、アカウント売買(ようはRMT)は禁止で、ゲーム内のアイテムの売買はそもそも出来ないことが多いですが、DAppsの場合は、ETH使って取引できるように実装されています。割と有名なのがCryptoKittiesで、このゲーム内で作成された猫が1300万円だかで取引されたとか。

https://www.cryptokitties.co/

DAppsの問題(?)は、記録をブロックチェーン内のDBに行う都合上、これがトランザクションとして発行されます。トランザクションはいくらかの手数料がかかりますので、チマチマとお金が出ていくことになります。ちなみにDAppsではこれをガス代と呼んでいます。

なお、イーサリアムもコンセンサスアルゴリズムにPoWを使用していますが、平均15秒でNonceの探索が終わるようになっているため、ビットコインより圧倒的に速いです。その分分岐も増えてしまいますが、その分岐数をうまく生かして、「最も長いチェーン」を採択するのではなく、「最も計算量の多いチェーン」を採択する、GHOSTプロトコルを採用しています。最近では、この15秒でも遅すぎるということで、PoSという別のアルゴリズムに切り替えることを検討しているようです。

Hyperledger

HyperledgerはLinux Foundationが管理する、ビジネス用途特化型のブロックチェーンです。デファクトスタンダードIBMのHyperledger Fabricだと思います。

Hyperledgerもイーサリアム同様、取引にスクリプトコード(Hyperledgerの場合はChainCodeと言う名前)が実行できます。大きな違いはノードの構成で、ビットコインのように誰でも参加できるのではなく、許可制のコンソーシアム型、もしくは完全クローズドなプライベート型という形態をとります。また、Hyperledgerは独自の通貨を持ちません。取引に支払いを含める場合は、外部から調達する必要があります。

使用用途としては、例えば医療情報の共有や輸出入関係書類の共有と言ったものがあります。輸出入関係書類の共有については、農林水産省がHyperledgerを導入して検討を進めていたことがあります。(今どうなったのかわかりませんが)

Hyperledgerは、ノードが全て同じ機能というわけではなく、役割が異なっています。Hyperledger Fabricの場合、合意形成にEndorsement-Order-Validation(EOV)というアルゴリズムを取っています。このEOVは、ノードごとに役割が異なるため、全員同じノードのビットコイン系とはだいぶ雰囲気が違います。ちなみに合意形成は非常に高速です。

図書

推薦図書。ブロックチェーン理解の助けになったのは、まずこの本。話がやや技術に寄っています。


ブロックチェーン システム設計

企画系ならこちらをお勧めしておきます。技術部分も非常にコンパクトにまとまっています。


新事業企画・起業のための 実践ブロックチェーン・ビジネス

Unity FungusのInvokeMethodとCallMethodは何が違うのか

Fungusを使ったメソッド呼び出しには、InvokeMethodとCallMethodの2種類があります。何が違うのでしょうか?

CallMethodはGameObject.SendMessage()

ヘルプにも書いてありますが、CallMethodは、実際にはGameObject.SendMessage()を呼び出しています。 即ち、Hogeと言うメソッドを呼び出すように設定した場合、 targetObject.SendMessage("Hoge", xxx); が実行されると言うことです。

InvokeMethodはリフレクションを使う

こちらもヘルプに書いてありますが、InvokeMethodは、Fungus内部で直接C#のReflection機能を使用して、メソッドを呼び出します。 Reflectionを実行するメソッドがInvoke()なため、InvokeMethodという名前がついているものと思います。

Recflectionとは?

Reflection(リフレクション)とは、「文字列から、同名のメソッドを見つけて呼び出せるようにする」というハッキングまがいの手法です。 Androidの非公開メソッドを無理やりコールする時なんかにも使います。

コード上でもGameObject.Find();とか直接メソッド名書いてるじゃん!と思うかもしれませんが、これはビルド時には呼び出しアドレスに変換してしまっていますので、実行時には文字列とは言い難いモノになっています。

そうではなく、例えば、

  • 実行時に外部から読み込んだテキストファイル
  • ネットワーク越しに受け取った文字列
  • なんか入力された文字列

などを実行時に解析して、その解析文字列だけで実行できるようにする手法がリフレクションです。

f:id:kinokorori:20190823214904p:plain:w400
リフレクション(反射)

で、何が違うの?

簡単に言うと、CallMethodはUnityの用意したメソッド呼び出し方法を使い、InvokeMethodはFungus自体が用意したメソッド呼び出しを使います。 そして、CallMethodの先にあるSendMessageの実装がどうなっているのか不明なものの、実際にはReflectionを使用しているようです。要するに結局どちらもReflectionということです。

じゃあ大体同じじゃないの?と言われると、ええ、まあ、たぶん……という感じです。ただ、InvokeMethodの方が、

  • 呼び出し引数を細かく設定出来る
  • 戻り値をFungus引数で受け取れる

というメリットがあります。また、SendMessageの内部がブラックボックス過ぎて気にくわないという人にも安心です。個人的にはInvokeMethod使っておけばいいんじゃないの?というところ。

ちなみに、SendMessageの注意として、「Activeでないオブジェクトからは呼び出せない」という制約がありますが、これはInvokeMethodでも同じです。

Kritaで不透明度アニメーション補間

久々のエントリー。ここしばらくイラストばかり描いてました。

今回は、Krtiaのアニメーション補間機能について紹介。いや、そもそもKritaのアニメーション機能って何が出来るの?という方はこちらをどうぞ。

kinokorori.hatenablog.com

Kritaのアニメーション補間機能

Krita4.2.5現在、アニメーション補間機能は透明度の変化(アルファブレンド)しか実装されてません。正直、移動補間くらいは欲しいなーというところですが……。 とりあえず、自分で作ったサンプルの紹介から。このアニメーションでは、光の明滅をアルファブレンド補間機能を使って描きだしています。

f:id:kinokorori:20190819005414g:plain
がたんごとん

設定の仕方

アルファアニメーションはレイヤー単位で行うことができます。

  1. まず、タイムラインパネルで、明滅させたいレイヤーを選択します。下の例ではlightレイヤーを選択しています。
    f:id:kinokorori:20190819010034p:plain
    タイムラインパネルのlightレイヤーを選択中
  2. 次に、不透明度を変化させたいフレームにカーソルを合わせ、アニメーションパネルから「不透明度キーフレームを挿入」を選択します。
    f:id:kinokorori:20190819010836p:plain
    アニメーションパネル/不透明度キーフレームを挿入
  3. 不透明度キーフレームを挿入すると、ひし形(◆)のキーフレームが挿入されます。下の図では、1Frameと13Frameに設定しています。
    f:id:kinokorori:20190819011410p:plain
    不透明度キーフレーム(1, 13)
  4. それぞれのキーフレームで、レイヤーパネルから不透明度を設定します。下の図では、1フレーム目を58%に、13フレーム目を17%に設定しています。
    f:id:kinokorori:20190819011919p:plain
    不透明度58%
    f:id:kinokorori:20190819012010p:plain
    不透明度17%
  5. 最後に、補間アルゴリズムを選択します。「アニメーショングラフ」パネルを表示して、直線補間ボタンを押します。
    f:id:kinokorori:20190819012635p:plain
    補間

下の図は4フレーム目の不透明度です。45%ということで、58% - 17%の間で自動的に補間されていることがわかります。

f:id:kinokorori:20190819013128p:plain
4フレーム目

アニメーショングラフ

手順5のアニメーショングラフ上で、不透明度をマウスで変更したり、補間アルゴリズムを変更したりすることができます。

下の図のようにすると、いわゆるイーズアウト(最初速く、後半ゆっくり)になります。 (ちょっと下にグラフが振れているので、行き過ぎて戻ってくるかもしれません。)

f:id:kinokorori:20190819013708p:plain
アニメーショングラフ

この辺は触って確かめた方が早いと思います。公式も、ここの部分に関しては詳しく載っています。

Animation Curves Docker — Krita Manual version 4.2.0

おまけ - 電車アニメーションについて

上の電車アニメーションですが、前景にこんな感じの車内画像、

f:id:kinokorori:20190819014414p:plain:w400
車内

車窓用の画像として、適当に描いたシームレスな背景を用意して、その画像をちょっとずつずらしながら出力しています。

f:id:kinokorori:20190819014518p:plain:w400
シームレスな背景

移動補間がないので、手動でキーフレームを配置して移動させています。面倒くさい。あと、定期的に車内画像を上に10pxくらい動くフレームを用意して、電車の揺れを表現しています。動くのは車内だけなので、背景は動かしません。

さらにこの2つの画像の上に、lightフレームを配置して、太陽光を表現しています。

キャラクターの動きは全部手書きです。Live2Dライクな動きを手でやってる感じです。なので、めっちゃレイヤー多いです。 動きがちょっとぎこちないので枚数もう少し増やせばよかったんですが、こちらも面倒くさいのでこれでいいやと言う感じ。でも、寝落ちする部分のアニメーションは結構綺麗に描けた気がします。