altebute.hatenablog.com

犬も歩けば規格にあたる

Unity 5 日記 3 deltaTime の適用

なんだか 前回 まで大真面目に記事を書いてたせいで新しく記事を書くのが億劫になってきてしまっていたので, 今回からもっと雑に書いていくことにする.

UnityEngine.MonoBehaviour を継承したクラスのメンバ関数 Update は毎フレーム呼ばれるが, 毎フレーム呼ばれるということはフレームレートの高い環境ではそのままではゲームの動作まで早くなってしまう. そこで, Time.deltaTime を乗算する事でこの問題を解決する.

void Update()
{
    var x_axis = Input.GetAxis("Horizontal");
    var y_axis = Input.GetAxis("Vertical");
    var vx     = x_axis * 60 * Time.deltaTime;
    var vy     = y_axis * 60 * Time.deltaTime;
    var v      = new Vector3(vx, vy, 0);
    this.transform.position += v;
}

Time.deltaTime には前回のフレームから今回のフレームまでに経過した時間が秒単位で保持されている. 型は float である.

FPS が 60 の環境である事を前提にフレームカウンタを回して任意の動作を実行するようなアルゴリズムを実行した場合は, Time.time の差分を取るか, Time.deltaTime を毎フレーム加算して, 大小の比較演算によって実行する必用がああるだろう. 浮動小数点であるから, 同値比較を行うと危険である事に注意.

Unity 5 日記 2 スクリプトの作成

前回は GameObject の追加とギズモを使った操作までを行った。 Unity入門 (全26回) - プログラミングならドットインストール ではこの後 Transform 、 Material の操作、 Rigitbody 、 Directional Light 、 GameObject の階層化、 Prefab が紹介されているが、それらを全てすっ飛ばして Script の追加に入っていく。 Visual Studio がインストールされている前提で話を進める。

プログラマ諸氏におかれては、さっさとプログラムに入って一先ず入力を受け取ってオブジェクトを動かしたくて仕方ないと思われるので、まずは Hierarchy ペインの Create ボタン 3D Object -> Cube で適当に GameObject を追加する。

次に、作成した GameObject を Hierarchy ペインから選択し、 Inspector ペインの最下部の Add Component をクリックしてコンポーネントを追加する。上部メニューの Component から追加してもよい。今回は New Script を選択し、名前を設定、 C Sharpスクリプトを追加する。

スクリプトを追加すると Project ペインの Assets の中にファイルが追加される。ファイルをダブルクリックすると自動的に Visual Studio が立ち上がり、プロジェクトが生成され、ファイルが開かれる。自動生成したクラスは MonoBehaviour を継承しており、メンバ関数 StartUpdate 関数が最初から定義されている。

不思議な事に、ファイル名とクラス名は一致していなければ Unity 側でうまく動かない一方で、クラスを名前空間に入れる分には特に問題なく動く。謎である。関数 Start はオブジェクトの生成時に一度だけ呼ばれる。一方 Update は毎フレーム呼ばれる関数である。

この時、すでに存在するクラス名を指定しようとすると、新しくファイルを追加出来ない場合がある。 Assets 内を適当に右クリックして新規ファイルを作成し、ドラッグ & ドロップで GameObject に Attach した方が良いのかも知れない。 そもそも名前空間で区切りながら同じ名前の複数のクラスを作成したいと考えていないが出来ないらしい。無念。

以下のように記述する事で、入力に応じてオブジェクトを移動する事が出来る。

public class NewBehaviourScript : MonoBehaviour
{
    // Use this for initialization
    void Start() {}

    // Update is called once per frame
    void Update()
    {
        var x_axis = Input.GetAxis("Horizontal");
        var y_axis = Input.GetAxis("Vertical");
        var velocity = new Vector3(x_axis, y_axis, 0);
        this.transform.position += velocity;
    }
}

InputUnityEngine.Input クラスである。このクラスは静的メンバ関数 GetAxis を持っており、引数 axisName によって識別される Unity 側で仮想的に定義された軸の入力値を取得する事が出来る。

取得した値をベクトルに変換し、 MonoBehaviour クラスのデータメンバである transform を操作して実際の移動を行う。丁度、このデータメンバは Inspector ペインに表示される Transform の内容そのものである。

あとは画面上部の再生ボタンを押せば、ゲームが動作を開始する。ちなみに Visual Studio 側から Unity にアタッチすれば、簡単にデバッガも動いてしまう。

これで晴れて C# を使用して、スクリプトによるオブジェクトの操作が出来た事になる。カメラやライトの制御をきちんとしないと Game 内での実際の見え方は奇妙になるが、そこは適宜調整してやればよいだろう。あとは、オブジェクト間で互いに情報を取得するための手段と、オブジェクトの生成と破棄を行う仕組みがあれば最低限のゲームを作成する事が出来る。

Unity 5 日記 1 インストール - GameObject の操作

はじめに

超々久しぶりに Unity に触った。もうどの位久しぶりかというと、起動しようとしたら別ドライブに僅かに残骸だけが残っていてUnity自体がインストールされていなかった。

折角なので、自分自身の備忘録兼足跡として、日記をつけていく事にする。プログラムは書けるが Unity は初めてで右も左も分からない、という人の一助になれば幸いだ。

インストール

前回まで使っていたのが 4 系だったので 公式ウェブサイト から Personal 版をダウンロードしてインストール。インストーラ ( Unity Download Assistant ) に同時にインストールコンポーネントをどうするか聞かれるが、ざっと見た感じデフォルトで OK 。強いて言えば、 マニュアル に色々書かれていて参考になるかも。 Visual Studio 2015 との連携はあって損は無さそうだった。

新規プロジェクトの作成

新規プロジェクトの作成の際に、プロジェクトを 2D にするか 3D にするかを聞かれるが、 マニュアル によればゲームにより向き不向きがあるが、あとで切り替えられるらしいのでこのマニュアルを読みながら適当に決めれば良い。

f:id:agate_pris:20161203211230p:plain

真っさらな状態になった。うーんこの何もない荒野にほっぽり出された感。 UI が英語だし、そもそもどこからどう手を付けていいか分からない。もちろん 1 マス左に移動すると見えない村があるなどという事もない。

画面のレイアウト

#03 画面の見方を覚えよう | Unity入門 - プログラミングならドットインストール を見ながら色々と確認。

ウィンドウ内の各種タブはドラッグ & ドロップで移動する事が出来る。ウィンドウ外にドラッグ & ドロップする事で別ウィンドウに切り離す事も可能だ。また、レイアウトには各種プリセットが用意されており、右上のボタンから選ぶことが出来る。

f:id:agate_pris:20161203215700p:plain

動画でも Tall がオススメされていたので自分も Tall を選び、 Scene と Game が縦に並ぶようにした。

基本的に Scene の中に各種 GameObject を配置していく事になる。 Scene 内に配置された GameObject は Hierarchy タブ内に表示される。 Hierarchy 内の各種オブジェクトを選択すると、 Inspector タブにその GameObject の内容が表示される。 GameObject に Component を付加していく事で、オブジェクトに対する肉付けを行っていく。

操作モードとシーンビューの操作

Unity - マニュアル: シーンビューの操作

ウィンドウ左上に並んでいる各種アイコンが操作モードを決定する各種ツールだ。手のアイコン、十字アイコン、その他諸々のツールはパン、移動、回転、拡大/縮小、 Rect Tool に対応する。パンはハンドツールとも呼ばれる。尚、各種操作モードにはデフォルトで Q W E R T キーが対応している。

ハンドツールを選択しる時、左クリックでドラッグする事で視点を移動する事が出来る。移動を選択している場合は GameObject を移動させる事が出来る。

ただ、ハンドツールを選択していてもミドルクリック ( ホイールクリック ) でドラッグすればどちらのモードでも視点の移動が出来るので、そちらが使える人はそれでいいかもしれない。

右ドラッグで視点をその場で回転させる事が出来る。また、 Alt+左ドラッグでクリックした地点を中心に視点を回転、 Alt+右ドラッグで視点の拡大縮小を行う。その他詳細はマニュアルを参照。

また Scene 右上に表示されているアイコン ( ギズモ ) の操作でも視点の操作が出来る。

#05 GameObjectの操作をしてみよう | Unity入門 - プログラミングならドットインストール

GameObject の操作

GameObject を選択すると、中央にギズモが表示される。このギズモを操作する事で、操作モードに応じてオブジェクトの各種操作を行う事が出来る。

Asset

File -> Save Scenes Ctrl+S で Scene を保存すると、 Assets に保存したシーンが表示される。 Asset の概念はまだ理解出来ていないが、たぶん Project に紐付いたファイル全般を Asset と呼ぶのだと思う。 Scene も Asset 、その他色々な物も Asset なのだろう、たぶん。

参考文献

Windows の解像度に思うこと

画素の密度

AppleiPhone 4 向けに Retina ディスプレイを発表して以降、スマートフォン向けのディスプレイは高密度化し続け、その傾向はラップトップ PC やテレビにおいても同様である。しかし macOS のスケーリングは比較的綺麗に見える一方 Windows では従来のアプリケーションは UI がガタついたり、表示がボケボケになってしまう。

最新の MacBook Pro がフルサイズの USB ポートを廃止した事からも分かるように Apple は古い物を切り捨てる事に躊躇が無い。一方で Microsoft は ( サティア・ナデラの就任以降その傾向は変わりつつ有るものの ) 比較的後方互換性を重視する傾向にある。そのため、新しい高解像度環境において Windows では古いアプリケーションの表示に問題が発生してしまうのである。勿論、新しい開発環境で作成されたアプリケーションではスケーリングがほぼ上手く行われる。 Windows 10 では 25% 刻み 4 の倍数単位でスケーリングが行われるため Windows アプリ UX デザイン ガイドライン においても 4x4 のピクセルグリッドにデザインをスナップするようにと書かれている。

Windows でのアプリケーション側での対応については以下の記事に詳しい。

しかしながら、結局の所 Windows では従来型の古いアプリケーションに有用な物が多く、その多くはバグフィックス等のメンテナンスは行われているものの UI を完全に刷新する程の対応が行われている物は殆ど無い。そのため、従来型のアプリケーションをピクセルパーフェクトにスケーリングするため 200% 表示に最適化されたディスプレイを搭載する事のアドバンテージが極めて大きい。

Microsoft もその問題を認識しているのか Surface Pro 4Surface Book の解像度は 200% スケーリングに最適な解像度になっている。

機種 size x y DPI
Surface Pro 4 12.3 2736 1824 267
Surface Book with Performance Base 13.5 3000 2000 267
MacBook Pro (2016) 15.4 2880 1800 220
EV2116W-A 21.5 1920 1080 102
EV2451 23.8 1920 1080 92

古式ゆかしいコンピュータ用ディスプレイにおいては 72DPI または 96DPI がデファクトスタンダードとされてきた 。これはデスクトップ環境での利用を想定した数値であるから、より目に近い距離で使用されるラップトップ PC やタブレットにおいてはより高密度が好適である。現行の Surfaceバイスの DPI は 267 であるから、 200% スケーリング環境では実質的なコンテンツの表示領域は 133.5DPI 相当となる。 Surfaceバイスはラップトップ PC とタブレットを兼ねる 2-in-1 デバイスとしてのセグメントに属するので、その DPI もラップトップ PC とタブレットの中間であると考えられる。

現行のデスクトップ環境向けのディスプレイの解像度は 96DPI 前後が主流である事から、以下のようなディスプレイが望ましいと考える。

セグメント DPI
デスクトップ 192
ラップトップ 240
タブレット 288

アスペクト比

PC のディスプレイのアスペクト比は時代と共に 4:3 、 5:4 、16:10 、 16:9 とそのメインストリームの軸足を移してきた。一方で Surface シリーズはアスペクト比 3:2 を採用している。

x y アスペクト比
640 480 4:3
800 600 4:3
1024 768 4:3
1280 1024 5:4
1280 720 16:9
1366 768 約16:9
2736 1824 3:2
3000 2000 3:2

PC 向けのディスプレイにおいて 16:9 が一期に普及した背景には、動画コンテンツの多くが視界全体の大きさを意識してそのサイズを採用した事にある。そのため PC で画面一杯に動画コンテンツを表示出来るようにするため、 PC においてワイドディスプレイが普及してきた初期に多かった 16:10 のアスペクト比が一気に駆逐されていった、という歴史的経緯がある。

一方で、縦に長いコンテンツを消費する事の多い PC においては縦の解像度のアドバンテージを支持する声も多く、 Surface シリーズのアスペクト比が 3:2 である事は、それらの揺り戻しであるとも言える。

デスクトップ PC においては、非常にワイドなコンテンツを表示したり、あるいはコンテンツを並べて表示する事に適した 21:9 の解像度を推す声もある。

私は、 3:2 の解像度は好ましいと考えるし、より小さなアスペクト比を採用し、また縦の値を共通化するという意味で、デスクトップ環境において 5:2 のアスペクト比もありなのではないか、と思う。

以下の表の x 及び y は既存の解像度と比較しやすくするため、半分の値にしている。

x y DPI size アスペクト比
1260 840 240 12.6 3:2
1260 840 264 11.4 3:2
1260 840 288 10.5 3:2
1344 896 240 13.5 3:2
1344 896 264 12.2 3:2
1344 896 288 11.2 3:2
1440 960 240 14.4 3:2
1440 960 264 13.1 3:2
1440 960 288 12.0 3:2
1536 1024 240 15.4 3:2
1536 1024 264 14.0 3:2
1536 1024 288 12.8 3:2
x y DPI size アスペクト比
2560 1024 192 28.7 5:2
2560 1024 216 25.5 5:2
2560 1024 240 23.0 5:2
1920 1280 192 24.0 3:2
1920 1280 216 21.4 3:2
1920 1280 240 19.2 3:2
3200 1280 192 35.9 5:2
3200 1280 216 31.9 5:2
3200 1280 240 28.7 5:2
2160 1440 192 27.0 3:2
2160 1440 216 24.0 3:2
2160 1440 240 21.6 3:2
3600 1440 192 40.4 5:2
3600 1440 216 35.9 5:2
3600 1440 240 32.3 5:2

5:2 のアスペクト比は昔の 5:4 のディスプレイを 2 枚並べた比率に相当する。意外とありなのではなかろうか?

iPhone 7 と次期 Nexus ( Pixel ) の狭間で

iPhone 7 が発売され、次期 Nexus ( Pixel ) に関するリーク情報も出揃ってきたので、このタイミングで所感をまとめる。

性能がずば抜けている

Android が登場してしばらくは、 AndroidiPhone に対してパフォーマンス面で明らかに劣っていた。スクロールの追従性一つとってもそれは明らかであるし、ましてWEB回覧は言わずもがなであった。

Android 側のパフォーマンス面、それによって提供されるユーザエクスペリエンスがある程度対等になったと言えるのは Android 4.0 Ice Cream Sandwich 以降の事だ。この頃の iPhone は 4S 、 Android では Galaxy Nexus である。勿論体感的な話をしているのであるからその所感は人それぞれだろうが、 iPhone はシングルタスク、 Androidマルチタスクに注力している分、一長一短なのだ、と思える程度には収まっていたと思う。

これ以降の両陣営は基本的なユーザビリティの向上にその労力の多くを注力してきたように思う。個々の技術や機能を見ればそれなりに革新的と言える物も少なくはないだろうが、どちらかが強烈、あるいは一方的な優位性を持つ事は無く、私自身のスマートフォンに対する熱も徐々に冷めていった。

が、今回の iPhone 7 は久しぶりに強烈なインパクトを受けた。

iPhone は世代交代のサイクルの関係上、全世代と考えて数十パーセント、場合によっては倍近く性能が向上する事もあるが、それは iPhone 内での事だ。その発売タイミングでの各々のフラッグシップ端末との間で単純性能でこれ程の差がついたのは久しぶりであるように感じる。 A10 Fusion プロセッサの威力は大きい。 Qualcomm には対抗製品の開発を頑張って欲しい所だ。

高い防塵、防水性能

iPhone 7 が防塵、防水に対応し、その等級が IP67 である、というのはかなり大きなアドバンテージであるように思う。

次期 Nexus ( Pixel ) について防塵、防滴性能があるというリーク情報があるが、あくまで IP53 であり、防水ではなく防滴である。

高機能なカメラ

残念ながら iPhone 7 Plus にしか搭載されていないものの、デュアルレンズのカメラの衝撃は大きい。広角レンズと望遠レンズをソフトウェアで合成する事で絵作りを行う、という方向性は非情に興味深い。

今までにもスマートフォンのカメラは HTC EVO 3D の3Dカメラや HTC One M8 のデュアルカメラ、 ZenFone Zoom の光学3倍ズーム等枚挙に暇がないが、 iPhone 7 Plus のカメラの方向性はバランスが良いアプローチだと感じる。

FeliCa 対応

最近になって、おサイフケータイもいいなぁ、等と思えるようになってきた。 iPhoneおサイフケータイ対応については、今まで何度も噂されてきたので眉唾であったし、 iPhone が日本のローカルな事情のためだけにハードウェアに特別対応をする事は無いだろうと思っていたので、非情に驚かされた。

持ち物が減るというのは良いことだ。可能であればスマートフォンに財布を統合するだけでなく、鍵も統合出来てしまえば良いのに、とすら思ってしまう。

ただ、それによって国際版と国内版とで様々な物事が分断されてしまうのは残念だ。 FeliCaNFC を初めとする近距離無線通信の規格の中で、その応答性において高い優位性を持っているのであればこそ、 Secure Element 等の問題を解消し NFC-F が国際的に普及している規格の序列に NFC-A 、 NFC-B に続く形で加わって欲しいものだ。

Visual Studioと同時に立ち上がるVsHub.exeの挙動

作業中である事を明示するために Steam のマイライブラリに Visual Studio を登録した時、バックグラウンドで VsHub.exe というプロセスが動いているために Visual Studio を閉じても継続状態になっている事に気がついた。

この VsHub.exe は通常 C:\Program Files (x86)\Common Files\Microsoft Shared\VsHub\1.0.0.0 にある。 *1

VsHub.exeVisual Studio を閉じてもしばらくプロセスを残し続けるが、しばらく時間が経つと自動的に終了するようだ。ちなみに自動的に終了する直前に複数の子プロセスを立ち上げ一時的に CPU 負荷が高い状態になった。

*1: OS が 64 ビットの場合

VC++2013 で using 宣言を使うだけでコンパイラが強制終了するコード

以下のプログラムは VC++2013 で正しく動作する。

template< typename Head, typename... Tail >
struct s;

template< typename Last >
struct s< Last >
{
    void f( Last ) {}
};

template< typename First, typename Second, typename... Tail >
struct s< First, Second, Tail... >
: s< Second, Tail... >
{
    using s< Second, Tail... >::f;
    void f( First ) {}
};

int main() {}

template の再帰を用いた典型的な記法である。 *1

派生クラスで宣言、定義した関数 f によって、基底クラスの関数 f が隠蔽されてしまうため、 using 宣言によって名前をスコープに持ち込む。

ところが、以下のように書き換えるだけで VC++2013 ではコンパイラが動作を停止してしまう。

致命的なエラー C1001

template< typename First, typename Second, typename... Tail >
struct s< First, Second, Tail... >
: s< Second, Tail... >
{
    void f( First ) {}
    using s< Second, Tail... >::f;
};

関数 f と using 宣言の順番を入れ替えただけでコンパイラが動作停止。とても残念。 VC++2015 では動くのかもしれないが未検証。 *2 当然だが gcc と clang では動作した。

また、以下のコードも NG 。

template< typename Arg >
struct impl
{
    void f( Arg ) {}
};

template< typename Head, typename... Tail >
struct s;

template< typename Last >
struct s< Last >
: impl< Last >
{};

template< typename First, typename Second, typename... Tail >
struct s< First, Second, Tail... >
: s< First >
, s< Second, Tail... >
{
    using  s< First >::f;
    using  s< Second, Tail... >::f;
};

int main() {}

これが出来ないので、再帰テンプレートによる構造部分と、関数を宣言する構造部分を分離することが出来ない。

辛い。

*1:テンプレート型引数が2個以上である場合の特殊化を明示しているのは、古い VC++ では明示的に書かないと曖昧と判断されてしまうため

*2:2016.07.22 VC++2015 では正常に動作した。