騒音のない世界 BLOG

コンピュータの話と、音楽の話

LANDRで楽曲をApple Musicに配信して困ったこと

ひとりインストバンド「騒音のない世界」のbecoです。YouTubeSoundCloudに毎月新曲をリリースしています。 noiselessworld.net

最近リスナーの方からちらほら要望があったので、毎月リリースしている曲をApple MusicやSpotifyなどにも配信しようと考えました。そこで、ディストリビューションサービス(楽曲の配信サイトへ一斉配信してくれるサービス)を色々と比較した所、LANDRというサービスが良さそうだったので使ってみました。今回はLANDRを選んだ理由と、実際に使ってみて困った点について書きます。

以下は2019年7月時点での情報となりますのでご注意ください。

LANDRを選んだ理由

LANDRは楽曲のディストリビューションサービスです。実店舗でCDを販売するのではなく、iTunes Storeなどのネット配信に特化しています。競合サービスとしては TuneCore、CD Baby 、Big Up! などがあります。最近はSoundCloudからもApple Musicなどに配信できますね。

他サービスと比べて良かったのは、月額定額制でリリースし放題のプランがあった点です(現在400円/月)。他サービスはリリースごとに年額で課金されるものが多かったので、毎月1曲ずつリリースするやり方だと高額になってしまい、向いていませんでした。

その代わり、現在は他サービスと比べると日本国内のサービスへの配信先があまり充実していません。LINE MUSICやAWAへの配信には対応していますが、例えばTuneCoreだとそれに加えてmoraやレコチョク、うたパスなど遥かに多くの国内サービスに対応しています。

TuneCore Japan

ただ、YouTubeTwitterで頂いたコメントだとApple Music、Spotify、LINE MUSICあたりの利用者が多いイメージがあり、そのあたりに対応できてれば良いと判断し、LANDRに決めました。

ちなみに、SoundCloudも有料プランに入れば定額でリリースし放題のようなのですが、配信先がまだ少なく、日本のサービスには対応していませんでした。LINE MUSICは外せないと思っていたのでSoundCloudは見送りました。

配信してみて困った点

配信してみて困った点を紹介します。これから配信する人の助けになればと思います。ただし、僕は複数サービスを使い比べてはいないので、必ずしもLANDR特有の点というわけではないと思います。他のサービスでも同様かもしれないのでよく確認してください。

言語と時差の壁があった

LANDRはサービスページが日本語化されているのですが、日本支社は現状無いみたいです。サポートも基本的に英語です。僕は仕事で英語を読み書きすることも多いですし、特に苦手という程でもないのですがやはり日本語よりもコストは高いです。

日本語に自動翻訳されることもあるのですが、若干カタコト翻訳なのと、たまに別な言語に翻訳されます(英語、日本語、中国語で送られてきてカオス)。ただ、意味がわからないときは申請すると手翻訳の自然な文章を送ってくれる機能もあります。これは感動しました。

僕は英語で問い合わせしていますが、普通に日本語ローカライズされているサービスなので日本語のやりとりにも対応してくれそうではあります。ただ対応を後回しにされそうな気がして… 検証していません。

あと言語とは別なのですが、本社がおそらくカナダのモントリオールにあるようで、日本との時差が結構すごいです(日本マイナス13時間。LAとベルリンにもオフィスがあるみたいなのでどこの人がサポートしているかは謎だけど何にせよ時差がある。)。また、土日はサポートが休みなので土曜リリースとかして問題があると月曜まで返事が帰ってこないので注意が必要です。

ジャケット画像の必須サイズが大きい

ジャケット画像の最低必須サイズは3000x3000です。僕は写真素材をそのままジャケット画像にすることが多いのですが、3000x3000に満たないものも多く、かといって引き伸ばすと汚くなるのでちょっと困りました。

最近は超解像といって画像を拡大したときにガビらないようにうまく補完してくれるような技術があり、Webサービスで利用できたりするのでそれを使ってできるだけ綺麗に引き伸ばしたりしています。

こういうのとか。

Bigjpg - AI Super-Resolution Image lossless enlarging / upscaling tool using waifu2x Deep Convolutional Neural Networks

あと、Photoshopの最近のバージョンだと機能として備わっていたりします。(「ディテールを保持 2.0」という、知ってないと絶対わからない謎の名前ですが…)

Photoshop CC 2018がついに禁断の機能を搭載で最強に - じゃじゃむねっと

英語と日本語が混在できない

これは結構致命的だったのですが、Appleの最近のスタイルガイドの変更でアーティスト名や曲名、アルバム名などのメタデータは日本語(ひらがな、カタカナ、漢字)と英語(ローマ字)を混在できなくなったみたいです。

僕の場合は「騒音のない世界」というアーティスト名を英語表記にするわけにはいかないので、曲名やアルバム名を日本語表記で統一する必要がありました。曲は日本語名が多いので大体は問題なかったのですが、古い曲の一部をカタカナ表記にする必要があったのと、ちょうどリリースを予定していたアルバムのタイトルをリリース直前で日本語に変更することになってしまいました。

定額制の配信サービスのみには出せなかった

楽曲によっては販売のみ、定額配信のみ、と分けたかったのですが、片方だけという設定はありませんでした。例えばiTunes Storeに出すとApple Musicにかならず出るし、Amazon Musicに出すと販売も定額配信もどちらも出るようです。

この辺はストアの仕様のような感じがします。買い切りの販売よりも定額配信に寄せていきたいのかな?と。

YouTube Musicの仕様が合わなかった

配信先は全て月額課金の有料の定額制聴き放題サービスと思っていたのですが、YouTube Musicは広告を見れば無料でフル視聴できるモデルのようでした。さらに、YouTube Musicに配信した曲はYouTubeにも自動的に転載されてしまうようでした。「アートトラック」というようなのですが、有料限定で出そうとした楽曲が無料でYouTubeにも出てフルで聴ける状態になってしまいました。

アートトラックとは - YouTube ヘルプ

また、YouTubeに出ているアートトラックは一見すると無断転載にも見え、複数名のリスナーの方々から問い合わせもありました。

一度リリースすると個別に公開先を変更できなかった

上記の理由から、YouTube Musicへの配信を止めたかったので問い合わせたのですが、「個別に公開先を変更することはできない」と言われてしまいました。「配信先を変更したければいったん配信を全て停止し、新規のリリースを作って配信してください」とのことでした。

このへんはシステム的に不可能なわけはないので、ストアとの契約の問題なのか、サポートでどこまでやるかの線引きとして「やらない」判断になっているのか、ちょっと謎です。

ストアによって公開/停止の反映までの時間が違った

LANDRでリリースを申請してから審査が入って各ストアに配信されるのですが、実際にストアに公開されるまでの間に遅延があります(一瞬でリリースして一瞬で止められると良いのですが…)。どのくらい遅延するかもストアによって結構差があって、例えばLANDRのヘルプだとApple Musicへの公開は平均で24時間と書いてあるのですが、最近は1週間ぐらいかかっており、一番遅いです。逆にYouTube Musicは公開も停止もかなり速かったです。

このヘルプページの数字、ぜんぜん当てになりません…

リリースを提出してからどれくらいでお店で販売されますか? – 私たちがお助けします!

そのような事情があり、公開先の変更のための再リリースにも1.5週間程度かかってしまいました。(余裕を持って1.5週後に公開予約した後、公開停止は余裕を見て1週間前に行いました)

ストアのデフォルト価格から変更できなかった

現状は申請時も公開後も価格の設定ができません。ストアごとにそれぞれの基準でデフォルトの価格があり、そちらで決まるようです。1曲の値段はどのストアも一律200円でしたが、iTunes Storeのみアルバムが半額でリリースされてしまいました(1200円 → 600円)。

これについては問い合わせたら「現在は変更できないが、将来対応予定」とのことでした。現状は価格はすべてストア任せになってしまうようです。競合サービスだとできるっぽいのでこの辺はLANDRに頑張って欲しいところです。

おわりに

まだまだ不便な点もありますが、月額400円でリリースし放題プランは最高なので今後もLANDR使っていきます。こういったサービスのおかげで個人アーティストがマネタイズしやすい世の中になってきてるなあと感じます。仕様やポリシーの異なるストアを一つにまとめるのは大変なところもあると思いますが、頑張って欲しいです。

最後に宣伝になりますが、よければ楽曲聴いてください〜。

Apple MusicやSpotify、LINE MUSICは「騒音のない世界」で検索すると出てきます。

noiselessworld.net

どうやって曲を作ってるか

Twitterで「どうやって曲つくってるか」っていう質問を頂きました。以前もメールなどで同じ質問を頂いたので、どんな感じで作ってるかを書いてみようと思います。

機材やソフトなどの技術面の話と、作曲するプロセスの話に分けて書きます。

機材とソフト

使っている主な機材とソフトを紹介します。ここでは作曲ソフトの使い方や録音技術などの話は割愛します。

機材

機材ですが、現状はギターとコーラスの声のみ録音しており、それ以外の音は打ち込みかオーディオ素材です。「新生活」ぐらいまではベースも録音してましたが、ノイズが結構のって処理が大変なのと、良いベース音源(後述します)を手に入れたので最近は打ち込みで作っています。

ギター

ギターはGodinというメーカーのストラトっぽいやつ使ってます。見た目と持った感じが好きで買ったやつです。Godinはカナダのメーカーで、もともとガットギターで有名らしいですね。

GODIN GUITAR ( ゴダンギター ) >Session Blackburst SG Rose | サウンドハウス

オーディオIF

ギターの音をPCに入れるためのオーディオIFはRolandのOctaCaptureを使っています。ドラム録音とかもしようとおもってチャンネル多いやつ買ったんですが現状1chでもいいぐらいなのでかなり持て余してます。

ROLAND ( ローランド ) >OCTA-CAPTURE UA-1010 | サウンドハウス

ヘッドホン

モニターヘッドホンはいくつかありますがSONYのMDR-V6をメインで使っています。これで調整して書き出したあとでiPhoneのスピーカーとか付属のイヤホンみたいな粗悪な環境で聴いて破綻してないかどうかとかチェックしたりします。

SONY ( ソニー ) >MDR-V6 | サウンドハウス

マイク

マイクはあまり使わないのでベリンガーの安いやつ使ってます。メインボーカルに使うにはちょっと心もとないですがコーラス重ねるぐらいならいいかなと思ってます。とはいえもうちょっといいやつ欲しいなという気もしています。

BEHRINGER ( ベリンガー ) >Ultravoice XM8500 | サウンドハウス

使ってる主な機材はこんな感じです。

ソフト

よく使ってるやつだけ紹介します。

作曲ソフト

作曲ソフトはLogicを使っています。あまり理由はないですがmacを使っているのと、AppleLoopsというオーディオ素材が付属していて便利なので。

ドラム音源

ドラム音源はAddictiveDrumsというのを使っています。いまは2がでてますね。お金出せばもっとリアルな音源もありますが、コスパ良くて動作も重くないので気に入ってます。

Addictive Drums 2 - XLN Audio

ベース音源

前述したベース音源はMODO BASSを使ってます。良い音です。

IK Multimedia | MODO BASS — The first physically modeled electric bass

ギターアンプシミュレータ

ギターアンプシミュレータはWavesのGTR3を使ってます。

Guitar Plugins - GTR3 | Bundles | Waves

音色はClean, Warm,Edgy, Creamあたりの歪みが少ないやつをよく使ってます。

その他

EQ、リバーブ、ディレイなどなどその他のエフェクトはLogic組み込みのやつを使うことが多いです。コンプとかリミッターだけはWavesのやつ使います。

作曲プロセス

プロセスって言うほどカッチリしたものでもないんですが、だいたいどんな感じで作ってるかとか、どんなことを考えながら作っているかという話です。

構成

まずどこから手つけるかなんですが、適当にギター弾いたりそのへん歩いたりしてるときに思いついたフレーズをボイスレコーダーに片っ端から入れてます。ボイスレコーダーにはエレキギターの生音とか、口笛とかで入れてます。あとから思い出せれば良いので。それから「これ」っていうフレーズができたらそれを中心にして他のフレーズとつなげたり、コードをつなげていったりして、全体の構成を決めていきます。

どんな感じでフレーズを思いつくかはなんとも言えないんですが、ギターを適当に弾いてるときや歩いてるときにふと浮かぶことが多いです。タイトルやイメージを先に思いついて、しっくり来るコード進行やフレーズを模索していくこともあります。

最近は浮かんできたイメージの真ん中に主人公がいるかどうかを大事にしてます。主人公がイメージできるということはそこにストーリーがあるということのような感じがしていて、タイトルを見て、曲を聴いたら物語が想像されて心動かされるようなものになるように試行錯誤しています。

なんとなくキレイな風景が浮かぶような曲はよく思いつくんですが、なんとなくキレイなんだけど深みがないような感じがしていて、動きや展開が欲しいなって思います。

録音・打ち込み

大体決まったら音源の作成に手つけていきます。とりあえずドラムの打ち込みから始めることが多いです。その後ベースを入れるか、ギターを録るかしていきます。ディテールはこの時点では決まっていないので録りながら決めていきます。

ドラムとか鍵盤の打ち込みはリアルにしたいのでダイナミクスをしっかりつける感じが多くて、ベースはダイナミクスをあまりつけずにいい感じの休符をつけていくのを意識することが多いです(曲にもよるとは思います)。

ミキシング・マスタリング

各トラックを音量調整して、EQかけたりリバーブかけたりリミッターかけたりしていい感じにして書き出していきます。書き出してから気になって何度も調整したりもします。

おわりに

どんな感じで曲を作っているか書いてみました。書いてみて思ったんですが、結局作曲っていうプロセス自体は自分の内側にあるグッとくるイメージを具体化していく作業とでもいうのか、感覚的で直感的なものなのかなあと思っていて、文章に落とすのは難しいところがあります。でも最近は段々と絵を描くように作れるようになってきて面白いです。常に新しいものを模索して、期待を超え続けていきたいですね。

楽曲をダウンロードする方法について

楽曲をダウンロードする方法がわからないと伺ったので解説します。

今回は「騒音のない世界のサイトの埋め込みプレイヤーからダウンロードする方法」と、SoundCloudのページから直接ダウンロードする方法」の2つをご紹介します。

なお、どちらもPC環境を想定しており、スマホタブレット等はOSや端末によって仕様や操作方法が多岐にわたるため想定しておりません。ご了承ください。また、スクリーンショットは2017年6月現在のものですので変更される可能性があります。

騒音のない世界のサイトから

騒音のない世界noiselessworld.net

サイトの埋め込みプレイヤーからダウンロードする場合です。 まずプレイヤーで曲を選択してください。 曲名の横に下矢印⬇のボタンが出てくると思います。

f:id:a_beco:20170618163524p:plain

このボタンからダウンロードできます。ボタンが出てこない場合、 僕の方の設定の問題の可能性があるのでTwitterなどで知らせて頂けるとありがたいです。

SoundCloudページから

beco | Free Listening on SoundCloudsoundcloud.com

SoundCloudのページからダウンロードする場合です。トップページと個別の楽曲ページの2箇所からダウンロードできます。

トップページから

プレイリストからは直接ダウンロードできないようなので、1曲ごとになっている方からダウンロードしてください。 下図のように「More」ボタンをクリックしてでくるメニューからダウンロードできます。

f:id:a_beco:20170618164531p:plain

個別の楽曲ページから

楽曲タイトルをクリックすると個別の楽曲ページに移動します。こちらもトップページからダウンロードするときと同様に 「More」ボタンをクリックしてでてくるメニューからダウンロードできます。

f:id:a_beco:20170618165048p:plain

おわりに

いかがでしたでしょうか。不明点などありましたらお気軽にメッセージください。

iOSエンジニアがUnity使って1ヶ月でアプリ作った話

先日、Unity製のカジュアル2DゲームをiOS/Androidでリリースしました。

iOS開発やcocos2d-xでのゲーム開発の経験はあったのですが、Unityはまったく初めてでした。というわけで、Unity使う中で感じたことをまとめたいと思います。これからUnity入門する方やUnityに興味ある方の参考になれば幸いです。

学習

最初にとりあえずUnityの学習期間を設けました。勉強だけしてたのはだいたい2、3日ぐらいだったと思います。インストールして動かすまではすんなりいけました。

勉強方法

最初に驚いたのが公式サイトが日本語に対応していたことです。全てではありませんがドキュメントの類までかなり対応されていました。少し前にAndroid開発のチュートリアルか何かを読んだ時は最初の数ページだけ日本語で後半ほとんど英語だったのですが、そんなこともなくしっかり対応されていました。すばらしい。

Unity - マニュアル: Unity マニュアル

公式のチュートリアルも充実してます。コースは動画になっており、実際にゲームを作りながら基本的な要素を学んでいく形のものになっています。こちらは日本語字幕があるものとないものがありますが、おそらくネイティブスピーカー以外の人が聞くことも想定しており比較的平易な英語ではっきりと発音してくれているので聞き取りやすいです。僕は英語のリスニングはそこまで得意ではないですが、英語字幕もあるので簡単に進められました。

Unity - Learn - Modules

今回作るゲームは2Dだったので2Dの初級と中級をやりつつ色々試したりしてました。それだけであとは調べながら作れそうという状態になれたので、実際のプロジェクトを進めていくことに。

本も読んでいたのですがそちらはあとから知識の穴を埋めるイメージで隙間時間に読んだりしてました。3Dだったら地形とかマテリアル、ライティング周りなども勉強しないと厳しいかもですね。

大変だったこと

Unity開発の中でハマったこと・手間取ったことなどをざーっと書いてみます。最初からこの辺気をつけられるともっと開発効率上がったかなと思います。

エディタを覚える

まず、縦画面にする方法がわかりませんでした。プロジェクトの初期状態は横画面で、チュートリアルも横画面だったので。「いやこんなもんすぐできる」と思ってあれこれやってたんですが結局自力では見つけられませんでした。まあ調べろって話なんですが、「簡単そうなことでも自力で見つけられない」っていう洗礼をいきない浴びた感じでしたね。当たり前かもですが、調べながら覚えていく感じだな〜と。

よく使う処理のショートカットとかも覚えると便利になりますね。公式チュートリアルでは出てきませんが、Q, W, E, Rで移動とか回転とかのツールを切り替えられるのは最初に知っておくと良いです。

複数の座標系が混在する

ゲームによって違うかと思いますが、複数の座標系について考える必要があり少し混乱しました。説明が難しいのでちょっとわかりにくい話になります。もっと良い方法もあるかもです。

ゲーム内のオブジェクトは基本的にワールド座標系で設定します。これは3次元の座標系ですが、2Dゲームでも同じ座標系を用います。ワールド座標系の1単位の長さは例えばカメラに写っている領域の高さを10とする、みたいな感じで自由に決められます。

さらにUnityにはGUIを作るuGUIという仕組みがあって、こちらはスクリーン座標系っていうんですかね、2次元の座標系で設定します。これはワールド座標系とは別の座標系です。デザインをiPhone5サイズでお願いしていたので、今回は横幅が640になるように設定しました(デバイスの横幅/640が1単位になる)。

さらに広告やWebviewなどのネイティブUIを出す必要がありました。例えば画面下部に出す広告の高さは50dipで固定です。dip密度非依存ピクセルというやつで、Androidなどのネイティブアプリでよく使われる単位です。Unityからデバイスのサイズを取るとピクセル値で取れるので、dipにcontent-scaleを掛けた座標系についても考える必要があります。(content-scaleはUnityからは直接取れなさそう?だったので、DPIから計算しました。)

要は色んな長さの「1」があってどれがどれなんだっけとなるっていう話なんですが、結局どうしたかというとそれぞれの座標系を相互に変換するような関数を作りました。それでデザインで指定された座標をワールド座標に変換して配置、とか、画面下から50dip空けて30ワールド座標の位置に配置、みたいなことやってました。

dip座標系 <-> デバイス座標系 <-> スクリーン座標系 <-> ワールド座標系

という感じです。

画面のレイアウトはめちゃくちゃやらないといけないので、最初に仕組みを作るのに時間をかけて細かい計算は隠蔽し、できるだけシンプルに考えられるようにしました。

ついでにですが、マルチ解像度対応は横方向は横幅に合わせて拡縮、そのスケールで縦方向は画面いっぱいに伸ばすという感じにしました。小さめの画面を基準にしているので基本引き伸ばされて多少ガビっちゃいますが、大きめの端末で見ても問題なさそうだったので許容としてます。

transform.positionとtransform.localPosition

Unityエディタ上でGameObjectに設定したpositionとかrotateみたいなプロパティは、スクリプトから動的にいじれたりします。それで、なんとなくエディタ上の名前とプロパティ名って必ず一致してると思ってました。実際だいたい一致してるんですが、transform.position = new Vector2(x, y)みたいにすると全然思った場所にレイアウトされなくてなんでや!ってなりました。

調べたところ、エディタからだと親GameObject基点の相対positionを指定するんですが、スクリプトのpositionは画面中心基点のグローバルなポジションになってしまうみたいです。なのでしばらく親GameObjectのpositionに足しあわせる感じで相対ポジションを書いてて、めんどくさいなーと思ってました。

しばらくしてドキュメント眺めてて気づいたんですが、transformにはlocalPosiitonというプロパティがあって、エディタ上のpositionはスクリプトではlocalPositionと対応しているみたいです。エディタだと表記がpositionなので結構長いこと勘違いしてました。基本スクリプトでセットする時はlocalPosition使うことが多くなるんじゃないでしょうか。

タッチイベントの取得

オブジェクトをタッチして云々ということがやりたいとき、uGUIを用いる場合はButtonコンポーネントを使えばタッチは簡単にとれますが、そうでない場合は自分で当たり判定を書く必要があります。毎回書くと結構大変なので、使いまわせるようなコンポーネントを作るなど考えたほうが良さそうです。

ArrayListとList (C#)

C#も初めてだったので少し戸惑ったことなのですが、「ListのほうがArrayListより新しい」って名前から初見で気づけなくないですか。。なんとなくJavaに近い感覚で書いてたので最初は名前的にArrayList使ってましたが、型情報が失われるのでキャストが多くなってなんか嫌だなと思っていました。あとからListの存在を知って、Listみたいに型指定できるって知ったのでこれだ。。と。普通の配列への変換もこっちのほうがやりやすいですね。

ビルド設定

Unityはビルド周りの機能が結構弱い印象です。普通のネイティブアプリだとdebug, releaseで分けたりとか、繋ぐサーバの環境ごとにビルド設定を分け、サーバの接続先を変えたり、別アプリにしたり、マクロで処理を分岐したりとかできると思いますが、Unityだと難しいです。

一応developmentビルドというものはありますが、bundle-idやアプリ名を切り替えるなど細やかな設定を簡単に実現する方法は標準では用意されてないという感じでした。(今回は、幸い社内ツールでPlayer設定を保存して切り替えられるようなものがありそちらを利用させてもらってだいたいなんとかなりました。)

ビルド工程についてはスクリプトを書いてある程度自動化することはできるようになっていて、今回で言うと広告のUnity SDKを入れるときにキーをinfo.plistに設定してあれこれみたいな手順があったのですが、毎回やってたらヤバイ量だったのでスクリプトを書いて自動化しました。

リソースの管理

色や文字列などもリソースとして一元管理したかったのですが、いまいちベストな方法を確立できませんでした。

最初はスクリプトで定数として管理し、必ずスクリプトからセットするルールにしていたのですが、Unityはエディタが強力で、エディタで完結させたほうがはるかに速く作れるので「必ずスクリプトからセットする」というルールはスピード感がなく諦めました。エディタでの見え方と実行時の見え方が変わるとややこしかったというのもあります。

結局エディタで直接指定するようにしたので一元管理はできていません。なのでUIの色をいっぺんに変えたりとかはできないです。ローカライズとかも大変なのでは。。ちょろっと調べたんですけど簡単にやるデファクトな方法って無さそう?ですかね。

プラグインの管理

Unityプラグインは普通に入れるとプロジェクトの色んなフォルダにガッとインポートされてファイルが散在してしまうこともあり、どれがどのパッケージなのかわからなくなったりします。

外すためのプラグインとしてPackage Uninstallerというのがサードパーティ製で一応ありましたが、パッケージに含まれるファイル全部消してしまいそうな感じだったので、複数のパッケージが同じファイルに依存していたりすると死ぬんじゃないかな。

https://www.assetstore.unity3d.com/jp/#!/content/35439

実際そういうのがあって、複数のプラグインが全く同じGoogleのなにかのライブラリに依存してました。(プラグインに含まれているバージョンが違っていて、古い方で上書きしちゃうとビルドできなくなるという問題もありました。)

あとプラグイン間でAndroidのActivity奪い合っちゃう問題というのもありました。Activityのライフサイクルきっかけで処理したくてActivityを独自のものに置き換えるプラグインがあるんですけど、Activityのイスって1つしか無いので2つ以上そういうプラグインを入れると動かなくなるんですよね。手動でActivityをマージして置き換えないといけないという。

いろいろ書きましたが、プラグインの管理は特にプロジェクト規模が大きくなっていくと結構たいへんになりそうだなーという印象でした。今回はそこまで問題になりませんでしたが、プラグインごとにフォルダがあって独立に管理できるようにしておくと良さそうという感じ。

設計について

ゲームの設計って前々から悩んでますが、難しいですね。

ゲーム内容にもよりますが、ゲームロジックとビューが密接に絡むことが多いので、そこを完全に分離するのは難しいと思うんですよね。見た目に依存するロジック層と見た目に依存しないロジック層で分けるとかなんですかね?MVVM的なアーキテクチャは可能かもしれませんね。VMには見た目に絡んだロジックを書くイメージ。

あとUnityはComponent-Based Architectureというやつだと思うので、それにメンタルモデルを切り替えて乗っかる必要があるなという感じがしています。たまたま昔書いていた記事を貼っておきます。

ゲーム設計: Component-Based Architecture - Qiita

スクリプトを書く時には小さいコンポーネントに分ける意識で、コンポーネントの再利用性をいかに上げられるかを考えるって感じですかね。

あとグローバルにデータを持つのってバッドノウハウなイメージあったのですがゲームだと結構普通にやるのかなって感じがしてます。Scene間のデータ受け渡しをやろうとするとどうしてもそうなりますし。そもそもUnityのGameObjectってFindとかするとどこからでも到達できてしまうし。。

ツール系よりもゲームのほうが変更の振れ幅が大きくて、堅牢性よりフレキシビリティを重視するんですかね。動かせる状態になってからの調整とか多そうですし。その中で保守性や可読性を担保していくのはなかなか骨が折れそうですね。

おわりに

ちょっとダラダラ書いてしまいましたが今回は以上です。何か参考になれば幸いです。

Null安全がすごい

先日社内で事業部のエンジニア全体向けに発表する機会があり、テーマが割と何でもありだったのでNull安全について話しました。発表の中で話せなかったことなども踏まえてブログにもまとめてみようと思います。

まずこのテーマを選んだ理由ですが、背景として

  • 自分がちょうどSwiftでiOSアプリを開発しており、Null安全な言語を利用していた
  • 事業部でNull安全な言語を使っているプロジェクトが他になかった
  • 比較的近年になって広がりを見せている新しい概念である
  • 自分がSwiftを書き始めて一番感動した部分だった
  • 将来的に言語選定の際の判断軸になるなど、具体的なアクションにつながりそう

といったところがあり、共有する価値があるのではと考えました。そういうわけなのでできるだけ特定の言語に依存せず、まったく知らない人にその概念を理解してもらい、良さを伝えるということを念頭に置いています。

Null安全とは

Null安全とは、一言で言うと「Nullチェックをコンパイラが強制する仕組み」のことです。Nullチェックをしないとコンパイルが通らない状態にすることで、実行時にNullへの不正なアクセスを防ぐ、ということをゴールとしています。

概念の説明としてはこれだけなのですが、Null安全が導入された背景を理解するため、NullとNull安全を取り巻く歴史を紐解きつつ、さらに深掘りしていこうと思います。

Nullの発祥

Nullという概念は1965年にTony HoareがALGOL Wという言語に導入したのが始まりとされています。その後様々な言語でNullが導入されていますが、2009年のカンファレンス(QCon)でTony Hoare自身が「Nullは10億ドルに相当する誤りだった」という旨の発言をしています。さらに、当時からコンパイラが参照の安全性をチェックするという発想はありながらも、実装の簡易さから単にNullを導入するという選択をしてしまい、多くのクラッシュにつながってしまった、とも話しています。

気をつけてNullチェックをする、みたいなことは当たり前のようになってしまいがちですが、人間が気をつけないとバグにつながるようなことはできるだけ機械に任せたほうが良いでしょう。考案者本人が認めているように、Nullチェックも本来はもっと仕組みで自動化されるべき存在だということではないでしょうか。コンパイラによって自動化するというのはその1つのアプローチといえます。

Null安全の歴史

Null安全という言葉は2005年のカンファレンス(ECOOP)でBertrand Meyerによって「Void Safety」という名前で紹介されたのが最初のようです。その後本人が開発するプログラミング言語Eiffelに導入されています。実装レベルではそれ以前にも似たような仕組みを実験的に導入している言語はいくつかあったみたいです。

それなりにメジャーな言語に普及していったのはここ数年のことで、だいたい2010年ごろからです。2010年に登場したRustをはじめ、Kotlin(2011~), Swift(2014~), TypeScript 2.0(2016~)など様々な言語に導入されました。

コンピュータやプログラミング言語の歴史から考えれば比較的近年になって広まってきた考え方であるといえるでしょう。

Null安全の仕組み

もう少し具体的な仕組みに踏み込んで見たいと思います。Null安全は実際にどういった形で実装されているのでしょうか。いろいろなバリエーションはあるかと思いますが、個人的に一番慣れ親しんでいるSwiftを例に取りつつ説明していきます。

Null安全はその性質上、言語機能として実装されることが多いです。やや雑な説明かもしれませんが、以下の2つの条件が満たせればNull安全な言語であるといえるでしょう。

  1. Optional型が存在すること
  2. Optionalでない型にはNullを代入できないこと

Optionalという言い方は言語によって異なるかと思いますが、わりとよく使われている用語のようです。概念としては「値もしくはNullを代入できるが、その中身には直接アクセスできない」ような型だと考えていただければよいかと思います。Optional型は明示的にNullチェックをすることによって中身の値にアクセスできるようになります。この型を使っていれば、Nullへの不正なアクセスは起こり得ません。

また、Optionalでない型にNullを代入できてしまうと結局そちらでNullへの不正なアクセスが起きうるため、2つめの条件も保証されている必要があります。

コード例を見る

Swiftでのコード例を見てみましょう。Swift未経験の方でもわかるようにコメントを含めていますのでなんとなく理解してもらえればと思います。まずOptional型です。

var opt: String? // StringのOptional型を定義する
opt = nil // Optionalなのでnilを代入できる
opt.lowercased() // Error! NullチェックをしていないのでStringのメソッドは呼べない

if let non_opt = opt { // Nullチェック
  non_opt.lowercased() // NullチェックをしたのでStringのメソッドを呼べる
}

Swiftの場合、型名の後ろに?を付けることでOptionalにすることができます。また、nilがいわゆるNullです。Optionalにはnilを代入でき、チェックなしには値にアクセスしたりメソッドを読んだりすることはできません。

次に、Optionalでない型です。

var non_opt: String = "TEST"
non_opt = nil // Error! Optionalでないのでnilは代入できない
non_opt.lowercased() // Stringのメソッドを呼べる

Optionalでない型にはnilは代入できません。つまりnilにはなりえないのでチェックなしにメソッドを呼ぶことができます。Non-null typeと呼ぶこともあります。

Javaなど従来の多くの言語では参照型のみNull代入可能であることが多いですが、Swiftでは値型か参照型か、ということとNull代入できるかどうかということは関係ありません。IntやDoubleといった値型でもOptionalならNull代入できますし、クラスなどの参照型でもOptionalでなければNullは代入できません。

これによって、型が値型か参照型かは意識せず、「存在しない」という状態をNullで表せるようになります。

Null安全のメリット

Null安全についてイメージが深まってきたでしょうか。次にNull安全のメリットについて見ていこうと思います。メリットとしては以下の様なものがあると思います。

うっかりNullチェックを忘れてしまうことがなくなる

コンパイラがNullチェックを強制するためです。Nullチェックをするか否かの判断軸も明確になるため、全体的にNullについての悩みが減ります。

生産性が高まる

開発のイテレーションにおいてNullチェック忘れというありがちなミスを早い段階で見つけられるようになるため、実装, コンパイル, 実行, デバッグ, というイテレーションを早めることができ、生産性が高まることが期待できます。

関数のインタフェースが表現豊かになる

これは直感的には理解しづらいかもしれませんが、例えば関数が失敗した場合の簡単なエラーの返し方としてOptional型を使うことができます。

エラーの表現として-1や空文字を返すようなパターンは古くから存在しますが、-1や空文字を失敗として扱うと理解しづらくなりますし、失敗しうるのかどうかがドキュメントを読まない限りわかりません。Nullを返すパターンは多少ましですが、結局失敗しうるのかどうかは関数のシグニチャからはわかりません。エラーをthrowする書き方は良いのですが、「書くコスト」は無視できません。チームで開発する場合、メンバーのスキル感によってはコストの高い書き方に対してリターンを理解してもらうための学習コストもかかります。それらを加味して、Optionalを返すというエラーの返し方は手軽でありながらエラーを返す可能性がある関数なのかどうかがわかりやすいため可読性も高いのが良いと感じています。

また、引数がOptionalであれば文字通りオプショナルな引数と判断することもできます。このように、関数のインタフェースが表現豊かになるのは大きなメリットといえます。

Null安全の悩ましい点

メリットの多いNull安全ですが、悩ましい点もあります。

抜け道の存在

現実的に、Optional型でも処理的にNullにならないケースもあります。そのような場合に冗長性を廃するため、Null安全な言語でありながらNullチェックを回避する仕組みが多くの言語に存在しています。

例えばSwiftにはForced Unwrappingと呼ばれる仕組みがあります。これは正しく使えば冗長なチェックを減らすことができるのですが、間違って使ってしまうと結局実行時にNullにアクセスしてしまい、クラッシュにつながってしまいます。Forced Unwrappingするには、変数の後ろに!を付けます。

var opt: String? // StringのOptional型
opt = nil // Optional型なのでnil代入できる
var non_op = opt! // Forced Unwrapping。中身はnilなので実行時にクラッシュする。

正しく使えれば便利なこともあるのですが、これによって結局Nullによるクラッシュを100%なくすには至っていません。これはNull安全の仕組みを採用しないほどのデメリットとは考えていませんが、もう少し良い仕組みにもできそうな気がしています。

Null安全を導入する悩ましさ

これは使う上での話というよりはそもそも導入する上での障壁の話です。

Null安全な言語であることの条件の1つとして「Optionalでない型にはNullを代入できないこと」というものを上げました。これは、例えばJavaにOptionalを導入しても、通常のNull代入可能な参照型があることによってNull安全の恩恵を受けにくくなってしまうということです。

このような背景があるため、既存のNull安全でない言語にNull安全を導入するのは難しいところがあります。Null安全なしくみを利用したければ、そのようなしくみのある言語を採用する必要があるでしょう。そのためプロジェクトの初期に決定する必要があり、すでに動いているプロジェクトに導入するのは難しいと言えます。

ちなみに、AltJSの1つであるTypeScriptはそのへんをうまくやっていて、バージョン2.0からデフォルトでは後方互換性を保ちつつ、フラグをたてることで後方互換性を捨てる代わりにNull安全の機能を導入できるようになっているみたいです。とはいえ、後方互換性をもたせることの重要性が高い言語ではそのようなアプローチも難しいのかもしれないと思っています。

Non-Null Typeについて

Null安全について説明するとOptional型に注目してしまいがちなのですが、本当に強力なのはそれと対をなすOptionalでない型、つまりNon-Nullな型の存在です。

Optionalな型が生まれたときに素早くチェックし、登場する変数をOptionalでない型のみにできれば、そこはNullが存在しない世界、ロジックに集中できる世界です。Nullにまつわる煩わしい問題をプログラムの端に追いやって、ロジックの本質的な領域を増やすことができれば見通しの良いプログラムを組むことにつながるでしょう。

おわりに

近年のプログラミング言語における新しい概念としてNull安全について解説しました。

プログラミング言語は人間に優しくなるように進化しています。構造化プログラミング、オブジェクト指向、型安全など、どれも可能なこと自体は大きく変わっていませんが、人間にとって読みやすく、書きやすく、管理しやすくするためのアイディアです。Null安全もその一つと言えるのではないでしょうか。

Null安全は、Nullがもたらす煩わしさを低減し、コアなロジックに集中できるようにする強力なツールであると感じています。正しく活用できれば多くのメリットが得られるでしょう。

Swift界隈では色々と議論され、「良い」という認識が広まっているテーマな割に、コミュニティによってはまだ全然浸透していないと感じています。Null安全という考え方に興味を持ってもらうきっかけになれば幸いです。

参考リンク

新曲「裸の王様」出しました

ちょっと出してから時間立っちゃいましたが、新曲出しました。

ドラムもギターもノリノリの曲です。ぜひどうぞ。

過去の曲もぜひ。

1~2ヶ月に1曲ぐらいのペースで上げてます。 更新情報など気になったら各種SNSのフォローお願いします。

新曲「終わりのない物語」出しました

クリーントーンのギターが淡々とつぶやくようにシンプルなメロディを弾きながら広い世界を旅していくような感じで、素朴で暖かい曲になったと思います。

ぜひ聴いてください。

過去の曲もぜひ。

1~2ヶ月に1曲ぐらいのペースで上げてます。 更新情報など気になったら各種SNSのフォローお願いします。