ホーム ブログ ページ 30

エターならないために

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ゲーム制作をする人なら多くの人が聞いたことがあり、 そうなりたくないと思っている「エターなる」。 今回はかつて個人でゲーム制作をしていて、現在アピリッツで 働いている身としてこの事を考えてみる。

「エターなる」って?

 知らない人もいると思うので「エターなる」の意味を一応解説しておこう。「エターなる」とは「永遠に(eternal)作品が完成しない」ことを意味している。その理由は制作環境の変化や病気といったものから、飽きたなんていうものまで多岐に渡る。
 昨今では「エターなりたくなかったらこうしたほうがいい」なんて話はあちこちで散見される。しかし、個々人によって性格や得手不得手があるので、どれが正しいとかは一概には言えない。それでも今回書くのは1人でも多くの人にエターなってほしくないからである。 

企画書・仕様書を書く

 「そんなガチなことしたくない」「どうせ頭の中に入ってるし」「書く暇があったら作りたい」と個人で制作している人ほど思ってしまい、飛ばしてしまうこの工程。(自分もかつて1人で制作していた身としては実に思い当たる節がある。過去に戻れるなら説教している。)
 企画書・仕様書を書くとは、「今から自分がどんなものを作ろうとしているのか」をまとめる行為であり、「後で見返して一貫性を保つ」と共に、「作品の限界を決定する」ことができる。「作品の限界を決定する」と言うと怒られそうだし、制作途中で新たな仕様を追加しても全然OKなのだが、よく考えずに「コレ良いから追加しよ!」は非常に危険と言わざるを得ない。
 追加するということは仕様が増えるということで、制作時間が伸びるということになる。制作途中でどんどん仕様が増えて永遠に制作が終わらない、エターなる一直線である。

モチベーションを維持する

 はい、そうですかと言って簡単にできるものではないのは百も承知だが大事なこと。ただ、「維持する」とは毎日四六時中「うおぉぉ!」ってなってることではないので、そこを勘違いしていると本当はモチベーションがあるのに維持できていないと思い込んで、本当にモチベーションが無くなってしまったりする。要は自分の環境や性格に合わせて「毎日20時から2時間」「土日に6時間」とか決めておいたり、やる気がでないときに無理にやったりしないようにすればいい。
 また、よく言われる対策として「ときどき友人・知人に見てもらったり、インターネットで公開すると反応が貰えてモチベーションに繋がる」というのがある。これは本当にそうだし、制作サイドでは気づかない観点で情報を得られるので作品のクオリティアップにも繋がるので絶対にやった方がいい。
 ただ、やりすぎると逆効果になることもあったり、実施に時間がかかるので数ヶ月に1回程度にするのをオススメする。

まとめ

 最後に1つだけ。よく言われるアドバイスではあるのだが、「完璧を目指す前に完成させろ」は大事な精神。クオリティアップは後から好きなだけ出来るし、一通り完成していると心持ちが全く違う。多少ハリボテでも遊べないよりはずっと良い。

3種類のアナリティクスレポートが一瞬で作れるGoogleデータスタジオTips

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回は、Googleデータポータルで一瞬で作れる3種類のアナリティクスレポートについてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
Googleデータポータルが完全に無償化されて半年ほどですが、徐々に使いやすくなってきていますね。

しかしながら、『Googleアナリティクスに慣れてるから・・・』、という理由でマイレポートやカスタムレポートを作り続けている人も多いのではないでしょうか。

その気持ちわかります。

ですが、どうやらGoogle的には『マイレポートやカスタムレポートよりもGoogleデータポータルを使ってほしい!!!』と思っているらしく、Googleアナリティクスデータを用いて3種類の実用的なレポートを一瞬で作れるようにしてくれました。

今回は、ユーザー・集客・行動それぞれに特化した実用的なGoogleデータポータルレポートを一瞬で作る方法についてご紹介いたします。

Googleアナリティクスのレポートを一瞬で作る方法

まず、Googleアナリティクスを開き、【マイレポート一覧】か【カスタムレポート】の一覧画面を開いてください。

enter image description here

ページ上部に見慣れないリンクがあるのがお分かりになりますでしょうか。
「ユーザー、集客、行動のレポートの外観が・・・」と書かれている部分です。

ここがリンクになっており、クリックするとそれぞれユーザー・集客・行動に特化したレポートがGoogleデータポータル上に作成されます。

基本的な作業はこれだけです。では、実際にどんなレポートが作成されるのか見てみましょう。

ユーザーレポート

enter image description here
※レポートのデータはGoogleが用意したデフォルトのものです。実際には、それまで見ていたアナリティクスデータが入るようになっています。

ユーザーレポートは以下の項目から構成されています。

  1. サイト全体のユーザー数、新規ユーザー数などの基本指標
  2. 新規・リピーターのユーザー割合
  3. 使用言語(新規・リピーター別)のグラフと表
  4. 利用国(新規・リピーター別)のグラフと表
  5. 利用都市(新規・リピーター別)のグラフと表

中には使わないデータもあるかと思いますが、これを基本構成として編集するには十分なクオリティになっていますね。

特に、新規・リピーターの区分けをデバイス別などに変更しても、そのままのフォーマットで使えそうな気がします。

集客レポート

enter image description here

集客レポートは以下の項目から構成されています。

  1. デフォルトチャネルグルーピングの内訳円グラフ
  2. 日別のユーザー数遷移グラフ
  3. 日別のCV率遷移グラフ
  4. 参照元/メディアをディメンションとした集客・行動・コンバージョンの基本指標の表

よく使う指標やデータの取り方が揃えられている印象です。
一部、右上のCV率グラフの縦軸が10000%とぶっ飛んでるような気がしますが、ここは要修正ですね(笑)。

その他に関しては、わざわざマイレポートやカスタムレポートで作るよりもお手軽なグラフ・表が搭載されていると思います!

行動レポート

enter image description here

enter image description here
※レポート画面が縦長だったのでスクショが2画面に分かれていますが、同じレポートの上下です。

行動レポートは以下の項目から構成されています。

  1. PV数・ユニークPV数・平均ページ閲覧時間のグラフ
  2. 離脱率と離脱数のグラフ
  3. ページURLとPV数の表
  4. ページタイトルとPV数の表
  5. ページグループとPV数の表
  6. サイト内検索での検索キーワードとPV数の表
  7. イベントカテゴリとPV数(イベント数?)の表

基本的なPV数関係のデータが搭載されているレポートになります。

ページグループやサイト内検索、イベントといった項目に関しては、利用していない場合は必要ない項目になりそうですね。

また、一番右下に記載されているのは、レポートの保存方法と編集方法についてのマニュアル的なものになります。
スクショでは省いてますが、他の2つのレポートにも書いてあるので参考にしてみてください。

注意点

ここまでのレポート画面を見てお気づきかと思いますが、現在は英語表記のレポートしかありません。

レポート中の文章がそこまで多くないものの、英語嫌いの方や日本語ラブな方にとっては看過できないことかもしれません。ご了承ください。

また、本機能は現時点でGoogleデータポータルのトップからは利用できないようです。

今回ご紹介した手順で利用してみてください。

まとめ:この機能はどんな人におすすめか

一瞬でレポートの基本構造が作成できるようになったことで、データポータルの敷居がかなり下がったのではないでしょうか。

まだまだカスタムレポートほど楽に作れるとは言えませんが、定点観測用にマイレポートを活用しておられる方はデータポータルへの移行を考えてみてよいかと思います。

また、こうした動きがGoogleアナリティクスにあると、ある日突然マイレポートが消える!?なんてこともあるかもしれません。

(新UIでレポート画面からレポート保存とマイレポート保存がなくなったため、ありえないとはいいきれませんよね・・・)

長いものに巻かれろ、ではありませんが、新しい機能を取り入れることは自身の成長やリスク管理にも役立つと思います。

ぜひともご活用を検討してみてください!

3種類のアナリティクスレポートが一瞬で作れるGoogleデータポータルTips

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルの認知が増え、だんだんとGoogleアナリティクスのレポート作成がデータポータルに移行してきています。しかし、慣れないうちはGoogleデータポータルの操作やレポート作成に手間取るのも事実。そこで今回は、Googleデータポータルで一瞬で作れる3種類のアナリティクスレポートについてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
Googleデータポータルが完全に無償化されて半年ほどですが、徐々に使いやすくなってきていますね。

しかしながら、『Googleアナリティクスに慣れてるから・・・』、という理由でマイレポートやカスタムレポートを作り続けている人も多いのではないでしょうか。

その気持ちわかります。

ですが、どうやらGoogle的には『マイレポートやカスタムレポートよりもGoogleデータポータルを使ってほしい!!!』と思っているらしく、Googleアナリティクスデータを用いて3種類の実用的なレポートを一瞬で作れるようにしてくれました。

今回は、ユーザー・集客・行動それぞれに特化した実用的なGoogleデータポータルレポートを一瞬で作る方法についてご紹介いたします。

Googleアナリティクスのレポートを一瞬で作る方法

まず、Googleアナリティクスを開き、【マイレポート一覧】か【カスタムレポート】の一覧画面を開いてください。

enter image description here

ページ上部に見慣れないリンクがあるのがお分かりになりますでしょうか。
「ユーザー、集客、行動のレポートの外観が・・・」と書かれている部分です。

ここがリンクになっており、クリックするとそれぞれユーザー・集客・行動に特化したレポートがGoogleデータポータル上に作成されます。

基本的な作業はこれだけです。では、実際にどんなレポートが作成されるのか見てみましょう。

ユーザーレポート

enter image description here
※レポートのデータはGoogleが用意したデフォルトのものです。実際には、それまで見ていたアナリティクスデータが入るようになっています。

ユーザーレポートは以下の項目から構成されています。

  1. サイト全体のユーザー数、新規ユーザー数などの基本指標
  2. 新規・リピーターのユーザー割合
  3. 使用言語(新規・リピーター別)のグラフと表
  4. 利用国(新規・リピーター別)のグラフと表
  5. 利用都市(新規・リピーター別)のグラフと表

中には使わないデータもあるかと思いますが、これを基本構成として編集するには十分なクオリティになっていますね。

特に、新規・リピーターの区分けをデバイス別などに変更しても、そのままのフォーマットで使えそうな気がします。

集客レポート

enter image description here

集客レポートは以下の項目から構成されています。

  1. デフォルトチャネルグルーピングの内訳円グラフ
  2. 日別のユーザー数遷移グラフ
  3. 日別のCV率遷移グラフ
  4. 参照元/メディアをディメンションとした集客・行動・コンバージョンの基本指標の表

よく使う指標やデータの取り方が揃えられている印象です。
一部、右上のCV率グラフの縦軸が10000%とぶっ飛んでるような気がしますが、ここは要修正ですね(笑)。

その他に関しては、わざわざマイレポートやカスタムレポートで作るよりもお手軽なグラフ・表が搭載されていると思います!

行動レポート

enter image description here

enter image description here
※レポート画面が縦長だったのでスクショが2画面に分かれていますが、同じレポートの上下です。

行動レポートは以下の項目から構成されています。

  1. PV数・ユニークPV数・平均ページ閲覧時間のグラフ
  2. 離脱率と離脱数のグラフ
  3. ページURLとPV数の表
  4. ページタイトルとPV数の表
  5. ページグループとPV数の表
  6. サイト内検索での検索キーワードとPV数の表
  7. イベントカテゴリとPV数(イベント数?)の表

基本的なPV数関係のデータが搭載されているレポートになります。

ページグループやサイト内検索、イベントといった項目に関しては、利用していない場合は必要ない項目になりそうですね。

また、一番右下に記載されているのは、レポートの保存方法と編集方法についてのマニュアル的なものになります。
スクショでは省いてますが、他の2つのレポートにも書いてあるので参考にしてみてください。

注意点

ここまでのレポート画面を見てお気づきかと思いますが、現在は英語表記のレポートしかありません。

レポート中の文章がそこまで多くないものの、英語嫌いの方や日本語ラブな方にとっては看過できないことかもしれません。ご了承ください。

また、本機能は現時点でGoogleデータポータルのトップからは利用できないようです。

今回ご紹介した手順で利用してみてください。

まとめ:この機能はどんな人におすすめか

一瞬でレポートの基本構造が作成できるようになったことで、データポータルの敷居がかなり下がったのではないでしょうか。

まだまだカスタムレポートほど楽に作れるとは言えませんが、定点観測用にマイレポートを活用しておられる方はデータポータルへの移行を考えてみてよいかと思います。

また、こうした動きがGoogleアナリティクスにあると、ある日突然マイレポートが消える!?なんてこともあるかもしれません。

(新UIでレポート画面からレポート保存とマイレポート保存がなくなったため、ありえないとはいいきれませんよね・・・)

長いものに巻かれろ、ではありませんが、新しい機能を取り入れることは自身の成長やリスク管理にも役立つと思います。

ぜひともご活用を検討してみてください!

手軽にゲームを面白くする工夫

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回はタイトル通り、ゲームを少しの手間をかけて面白く見せる工夫をしようと思います。
まずは3時間くらいかけて錬成したゲームをみてください 。

enter image description here

疑う余地の無いホッケー (?)ゲームです。
ちなみに左側は僕が操作していて右は適当にプログラムで動かしています。

これが面白く見えるように要素を足していこうと思います。


何かしら動かす


無操作状態だとしても全く動きのない画面のあるゲームはあんまり無いと思います。動きが無いと動作しているのかのか不安ですし寂しいですよね。
ですが、逆にゲーム画面は動きがあるだけで少しそれっぽくなるものです。

なので足してみました。
enter image description here

四角を適当に降らしているだけでもなかなか観れるものになったと思います。
背景などプレイに関係の無いものは一定の動きを繰り返すような単調な動きが楽だし丁度いいです。


アクションにはリアクション!


ユーザーのアクション対して反応があると気持ち良さが上がります。
このゲームのアクションは球にぶつかるくらいなものなのでぶつかった時にエフェクトを出してあげます。

enter image description here

当たった感が増えました。
そしてなにより当たらなかった事がよりわかりやすくなりました。
当たっている事を明確にする事により、表現しにくい「当たらなかった」ということも伝える事ができます。


情報を視覚化させる


このホッケーゲームは球を弾くたびに球の速度が上がっていきます。
早さに応じて色を赤くしていますがゲームのメインにしては少し物足りない気がするのでわかりやすく軌跡をつけてあげましょう。

enter image description here

スピードが上がっていくのが分かりやすいだけでなく、滑らかに動いているようにすら見えます。
このゲームでユーザーが一番見るところはおそらく球なので、主役にはもう少し手間をかけてもいいと思いました。


まとめ


enter image description here

少しは楽しく見えるようになったのではないでしょうか。
これらの追加にかかったのは30分くらいで、思ったよりお手軽にできたと思います。
以上、ゲームを面白くする工夫でした。

※この記事の内容はあくまで作者の主観によるものです。

【0秒帰宅!?】テレポートについて考える

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回は、近い将来に実用化がされるかもしれない、「量子テレポーテーション」という現象について紹介します。※本記事は分かりやすさを重視するため、正確性を犠牲にしています。ご了承ください。ふんわりと内容をお伝えできればと思います。

量子テレポーテーションとは?

Wikipediaによると、

古典的な情報伝達手段と量子もつれ (Quantum entanglement) の効果を利用して離れた場所に量子状態を転送することである。

とあります。難しい言葉がふんだんに用いられているので、自分なりに用語を解説したいと思います。
まず、
・量子:物理量の最小単位、ものっっっすごく小さい粒というイメージです。
・古典的な情報伝達手段:現在使われている、メールや電話といった一般的な情報伝達手段のことです。
・量子もつれ
 これが一番意味の分からない単語ですね。簡単に解説すると、
「片方の状態が分かると、対になるもう片方の状態が分かる」ような状態のことです。
例えば、二つの箱の中の一方にボールを隠します。ボールは二つの箱の内の一つにしか隠されていません。従って、片方の箱を開けて中身を確かめれば、自動的にもう片方の箱の中身が決まります。簡単に言うと、このような状態のことです。

これらを踏まえて、量子テレポーテーションを説明すると、
「特別な関係にある粒子の効果と電話を一緒に使って、離れた場所に粒子の状態を転送すること」
となります。まだまだイメージが付きにくいと思うので、例を用いて説明していきます。

ものすごく大雑把な例

ここでは例として、「卵焼き」をテレポートさせてみようと思います。
前提として、二人の人間、AさんとBさんに「全く同じ卵」を渡して、遠く離れた場所にいてもらいます。(「量子もつれ:特別な状態」を簡略化し、全く同じものとして考えます。)
ここからBさんの作った卵焼きをAさんのもとへテレポートさせます。
①Bさんがこの特別な卵を使って卵焼きを作ります。
②Bさんが出来上がった卵焼きをよく味わって食べて、超詳細にレポートを書きます。
③BさんがAさんへ電話をし、レポートと作成手順を超詳細に教えます。
④AさんがBさんの言われたとおりに卵焼きを作ります。
⑤あら不思議、Bさんの作った卵焼きがAさんのもとへテレポートしました。

enter image description here

いかがでしょうか。ただのレシピの口伝じゃないか、と思うかもしれませんが、ここで重要なことが二つあります。
一つ目は、BさんはAさんにレシピを伝えるために、火の入れ加減から箸でつついた回数、卵を割るときのヒビの入り方、さらには卵分子の並び方に至るため、超詳細に分析しているということ。
二つ目は、AさんはBさんの情報をもとに、卵分子の並び方まで完全に再現できたということ。
この二つです。こんなこと非現実的だと思われるかもしれませんが、その通りです。
卵焼きのような大きな物質では非現実的に思えるほど難しいですが、現在では、考えられる状態が少ない超小さい粒子において、この量子テレポーテーションの実験に成功したと発表されています。

応用①:テレポート

ここからは現実的かどうかは置いておいて、応用例を紹介します。
その①はテレポートです。
上の例での「卵焼き」を「人間」に置き換えるだけです。
すると、会社から自宅へ「私」の構成要素と作り方を送ると、自宅の機械が「私」を再現し、あたかもテレポートしたように移動できます。
つまり、人間を構成する要素と、その詳細なレポートを書いてくれるマシーンがあれば、どこにでもテレポートすることが出来るのです。
ただし、技術的な壁も高いですが、会社にいた「私」は、分子の並び方などの超詳細なデータを取るために機械にバラバラにされてしまうので、倫理的にも非現実的なものと言えます。

応用②:情報通信

こちらは現実的な応用例です。
上の卵焼きの例で、一つ重要なことがあります。
それは、
「手元に特別な卵がない限り、この卵焼きを再現できないこと」です。
現在の情報伝達手段では、送りたいものを(暗号化等の処理を挟むにしても)、そのまま送ることしかできません。情報漏洩が起これば、大変な被害が生じかねません。
しかし、この量子テレポーテーションを用いれば、粒の状態をどうやって変化させるか、という手順書を送るだけで情報のやり取りができます。
これは、たとえ情報漏洩が起こったとしても、特定の粒(上の例では特別な卵)が手元に存在しなければ意味がありません。従って、情報漏洩に対してとても強い情報通信手段になりえます。

終わりに

いかがでしょうか。人間のテレポートという夢のような手段にしては、倫理的にも技術的にも問題だらけであるのが現状ですが、とても面白い技術ではないでしょうか。
※繰り返しになりますが、本記事は分かりやすさを重視するため、正確性を犠牲にしています。ご了承ください。

アピリッツ・ブロックチェーン・ラボの結成

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

アピリッツは、日頃より最新技術にアンテナを張り研究しています。それを、新しいビジネスに役立てたり、お客様のサービスにとって最適な情報である場合は、ご提案したりと役立てています。 今回、会社の中からブロックチェーンに興味のある技術者やコンサルタントなど職種や役職を問わず募集し、「アピリッツ・ブロックチェーン・ラボ(ABCL)」を2017年6月8日に創設しました。

創設の目的

昨今、ブロックチェーンは注目され、各社研究され実証実験が行われ、金融、IoT、物流などの幅広い分野で応用されています。
少し乗り遅れていますが、アピリッツではブロックチェーン技術を利用したビジネスの検討を行うため、アピリッツ・ブロックチェーン・ラボ(ABCL)を創設し、情報収集や実証実験などを行っていきます。

ABCLの活動内容

  • 定例会
    • 収集した情報の報告・宿題事項の報告
  • ハッカソン、アイデアソン実施
    • 実際に触れてみて、仕組みを理解
    • ビジネスを考えてみる
  • DoRuby記事執筆
    • BCCC委員会への参加・フィードバック
    • JBA定例への参加・フィードバック

今後の予定

  • 情報収集
    • ユースケース調査
    • 仮想通貨またはトークンの目的と技術調査
  • 技術検証
    • Bitcoin、Litecoin、Ethereumなどのソースを触り、実際に稼働させ、マイニングの実施や簡易アプリケーションの作成を行います。
    • ハッカソンを実施(社内)します。
  • 企画
    • アイデアソンを実施(社内)します。
    • 共同研究などが出来るのであれば実施します。
  • 施策検証
    • 実際に企画したものを作成して動作・効果検証します。
  • 情報共有
    • 社内外にABCLで行っていることを共有します。

ActiveRecordの速さを追い求める. 1

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

2があるかどうかは微妙。

 こんにちは、HelloWorld+です。
 今回もまた、ActiveRecord関連の話をしようと思います。

状況

 どんなゲームにおいても、キャラクターは無くてはない存在です。
 そして、以下のような人間マスタと、人間パラメータマスタがあるとします。

HumanMaster

id:                          integer
code:                        integer
name:                        string
hp_parameter_code:           integer
power_parameter_code:        integer
intelligence_parameter_code: integer
speed_parameter_code:        integer


HumanParameterMaster

id:        integer
code:      integer
age:       integer
parameter: integer

 才能とか、画像コードとか、職業とか年収とか余命とか、そんなものも実際のHumanMasterには含まれますが、今回は簡略化してこんな感じで。
 そして、上記のマスタからだと、人間そのもののデータの形は以下のようになります。

Human
id:             integer
human_code:     integer
hp:             integer
power:          integer
intelligence:   integer
speed:          integer
age:            integer

 Humanそのもので保存するデータは、HumanMasterと紐付ける為の最小限のデータ(今回だと、HumanMasterのcodeとHumanのhuman_codeが紐付いている形になります)と、Human一体一体で違った値になるパラメータ周りになります。
 そして、Humanが加齢した際には、HumanMasterのパラメータコード、そしてHumanの年齢を参照し、HumanParameterMasterそれぞれのパラメータの値を取得、更新する形になります。
 今回は、パラメータはHuman単位ではなく、Parameter単位で管理されている、とします。どちらにも利点と欠点があるのですが、そこあたりは割愛します。

加齢の工程

Human加齢!

Humanのcodeから該当するHumanMasterを取得。

Humanのage、HumanMasterのそれぞれのparameter_codeからHumanParameterMasterのパラメータを取得。

Humanのパラメータを上書きして加齢による能力値変動が完了。

この工程を、サーバー側で行う為の、Railsのコードに起こしてみましょう。

def birthday!(human)
  #人間マスタ取得
  human_master = HumanMaster.find_by(code: human.code)
  #パラメータ上書き
  ["hp", "power", "intelligence", "speed"].each do |param_str|
    parameter_code = human_master[param_str + "_parameter_code"]
    parameter_master = HumanParameterMaster.find_by(code: parameter_code, age: human.age)
    human[param_str] = parameter_master.parameter
  end
  #保存
  human.save
end

 基本的には、まあ、こんな感じでしょう。でも、これだとやや冗長なところがあります。
 以下の一文になります。

parameter_master = HumanParameterMaster.find_by(code: parameter_code, age: human.age)

 え? 単純に取得してきてるだけじゃん、と思うかもしれませんが、これだとまだ冗長なのです。
 パラメータマスタを取得してきて、使っているのはparameterだけです。それ以外のデータは必要ありません。
 そして、レコードそのものを取ってくるより、カラムの一つのデータを取ってくる方が速いのです。
 今回はパラメータを参照する回数はhp, power, intelligence, speedの4回だけですが、もっと数が増えてきた場合、同じように一々レコードそのものを参照していると如実に処理速度の差が出てきます。
 ただ、ここで問題が生じます。
 find_byからでは、カラム単体のデータを取ってくる術はありません。
 では、どうしたら一つのデータを取って来る事が可能か?
 方法は二つあります。
 一つ目は、whereからのselectとかpluckとか。

parameter = HumanParameterMaster.where(code: parameter_code, age: human.age).select(:parameter).take.parameter

 もう一つは、SQL直打ち。

parameter = ActiveRecord::Base.connection.select_value("SELECT parameter FROM human_parameter_masters WHERE code = #{parameter_code} AND age = #{human.age}")

 SQL直打ちの方がちょっとだけ速いのですが、まあ、コードの中にSQL直打ちするのは美しくないと色々言われたりするので、本当に速さを求めない限りは、上で大丈夫でしょう。上に置き換えるだけでも、処理速度はかなり速くなります。

 さて、最後にRailsで実際に作った人間パラメータマスタで以下のようなコードを打ってみて、実行時間の差を感じて貰って終わりにしたいと思います。

def get_time
  time = Time.now
  yield
  p Time.now - time
end

#レコードそのまんま
get_time do
  1000.times do |n|
    HumanParameterMaster.find_by(id: n + 1)
  end
end
#3.851174sec

#絞り込み
get_time do
  1000.times do |n|
    HumanParameterMaster.where(id: n + 1).select(:parameter).take.parameter
  end
end
#0.714646sec

#SQL直打ち
get_time do
  1000.times do |n|
    ActiveRecord::Base.connection.select_value("SELECT parameter FROM human_parameter_masters WHERE id = #{n}")
  end
end
#0.369945sec

 では、より速さを求める(時にはコードの綺麗さを犠牲にして)Railsライフを送りましょう。

Markdownのすすめ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

エンジニアも非エンジニアも、Markdownを使うと生活が豊かになることでしょう。

Markdownとはなんぞや

Markdown は プレーンテキストで見出し・箇条書きなどのちょっと構造化した文章がかける便利なマークアップ言語です。
が、細かい話はなしで 記号や書式をちょっと変えてみませんか? くらいの話です。

Markdownでものを書くときの利点は

  • そのままでもそこそこの見た目の文書になる
  • 変換するとかなりそこそこの見た目の文書になる

ことです。

たとえばこの記事もMarkdownで書いています。上の文章は実際には以下のようなテキストです。

Markdownとはなんぞや
====

[Markdown][1] は プレーンテキストで見出し・箇条書きなどのちょっと構造化した文章がかける便利なマークアップ言語です。
が、細かい話はなしで **メモをとるときの記号や書式をちょっと変えてみませんか?** くらいの話です。

Markdownでものを書くときの利点は

* そのままでもそこそこの見た目の文書になる
* 変換するとかなりそこそこの見た目の文書になる

ことです。

[1]: https://daringfireball.net/projects/markdown/

ここでは色々使っていますが、とりあえず箇条書きと見出しだけでも覚えれば生活が楽になります。
エディタやサービスによっては少し書式が違うものもありますが、主要なものはあまり差はありません。

フォントを変えたり色を変えたりするほど高機能でなくてもいいけど、ただの文章よりはもう少しちゃんとした文章を書きたい…そんなときに便利です。

「markdown エディタ」などで検索すると、markdownの入力補助や変換、表示をしてくれるものが色々見つかると思います。

普段は Kobito を使ってメモを書いたりしていたのですが、この記事を書いていたところ HackMD というWebアプリを教えてもらいました。
共有・共同編集も簡単にできますし、チーム内で使うのによさそうです。dockerイメージもあることなので今度導入してみたいですね……。

エンジニアとして幾つか挙げましたが、この世に数多存在するエディタから、導入や使い方のハードル・目的に応じて好きなものを選んでいただければと思います。

すぐにできるかんたんMarkdown

箇条書き

メモをとるときに箇条書きする人は多いと思いますが、私もその一人です。
箇条書きは箇条書き記号を半角アスタリスクと半角スペースにして、前後に空行を入れるだけです。

* あああああ
* いいいいい
  • あああああ
  • いいいいい

箇条書き記号はアスタリスクではなく半角ハイフンでもよいです。
また、箇条書きは先頭に半角スペースかタブを入れることで入れ子にできます。階層によって記号を変えると読みやすくなります。
半角スペースの数は4つにしておくとだいたいどんなものでもきちんと入れ子にしてくれます。

* あああああ
    - いいいいい
    - ううううう
* かかかかか
    - ききききき
  • あああああ
    • いいいいい
    • ううううう
  • かかかかか
    • ききききき

もっと入れ子にできますがそこまではあまり使う機会がないかもしれません。

見出し

要するに章・節を分けたときのタイトルですね。今この文章の上にある「見出し」もそうです。

大きいほうから

# 一番大きい見出し
## 二番目に大きい見出し
### 三番目に大きい見出し
#### 四番目に大きい見出し
##### 五番目に大きい見出し

一番大きい見出し

二番目に大きい見出し

三番目に大きい見出し

四番目に大きい見出し

五番目に大きい見出し

一番大きい見出し、二番目に大きい見出しには別の記法もあります。

一番大きい見出し
====

二番目に大きい見出し
----

一番大きい見出し

二番目に大きい見出し

=や-の数は1つ以上であればいくらでも伸ばせます。
見出しの前後に改行を入れると見出しとして認識しやすくなります。

引用

文章を引用するときは、以下のように行頭に > と半角スペースを入れます。

> ああああああ
> いいいいいい

ああああああ
いいいいいい

強調・打ち消し線などの文字装飾

斜体・太字・打ち消し線なども書けます。テキストで見たときに箇条書きや見出しほど直感的でないのが少し残念です。
個人的によく使うのは 太字 です。

*あああああ*
**いいいいい**
~~ううううう~~

あああああ
いいいいい
ううううう

文中で使うときは **このように** 前後に半角スペースを入れる必要があります。

他にも色々な記法がありますが、普通の文章(こういったブログなど)を書くのにはこのくらいわかれば十分な気がします。

まとめ

ぼーっとしているとゴミのような文章を書いてしまうことも多いのですが、箇条書き・見出しを活用すると構造を少し意識して書くようになって少しまともな文章が書けるようになった気がします。
読みやすい文章を書いて豊かな生活を送りたいものです。

Prefabの中身を読んでみよう

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

こんにちは motsukaです。

みなさんUnityを使うとき何気なくオブジェクトをプレハブ化して使っていますよね?
ですが、その中身がどうなっているかなんて知らないで使っている人が多いんじゃないですか?わたしは実際どうなっているか知りませんでした。
ですが、UnityをGit管理しているとき、よくプレハブがコンフリクトを起こしてしまって手動でマージしないといけない時、適当なエディタでファイルを開きますよね?
その時の構造を知れば、もっと安全に修正ができるとは思いませんか?
ということで、中身を読んでいきたいと思います。

GameObjectを読む

では下準備として、インスペクター上で新しくゲームオブジェクトをつくり、それをそのままプレハブとして保存します。

その保存したプレハブをテキストエディタで開いてみましょう。

そうすると、以下のようになっています。

  %YAML 1.1
  %TAG !u! tag:unity3d.com,2011:
  --- !u!1001 &100100000
  Prefab:
    m_ObjectHideFlags: 1
    serializedVersion: 2
    m_Modification:
      m_TransformParent: {fileID: 0}
      m_Modifications: []
      m_RemovedComponents: []
    m_ParentPrefab: {fileID: 0}
    m_RootGameObject: {fileID: 1000012251039328}
    m_IsPrefabParent: 1
  --- !u!1 &1000012251039328
  GameObject:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    serializedVersion: 4
    m_Component:
    - 4: {fileID: 4000012487135774}
    m_Layer: 0
    m_Name: GameObject
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
  --- !u!4 &4000012487135774
  Transform:
    m_ObjectHideFlags: 1
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 100100000}
    m_GameObject: {fileID: 1000012251039328}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 2464.8406, y: 272.8769, z: 0}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
    m_Children: []
    m_Father: {fileID: 0}
    m_RootOrder: 0

では、上から見ていきましょう。

上から2行はただのヘッダーですので、気にしないでいいです。
3行目の !u!1 &6 とは、基本的にコンポーネントの切れ目に存在するもので、!u!の後の数字は オブジェクトクラスというUnityに割り振られたオブジェクトのIDが書かれています。このIDを使ってこのオブジェクトがなんなのかを判別しています。
&10010000は任意に名付けられるファイルIDでこの値を参照してどこのオブジェクトの子にいるのかなどに使われています。
その下からプレハブ内部の情報が書いてあります。

  Prefab:
    m_ObjectHideFlags: 1
    serializedVersion: 2
    m_Modification:
      m_TransformParent: {fileID: 0}
      m_Modifications: []
      m_RemovedComponents: []
    m_ParentPrefab: {fileID: 0}
    m_RootGameObject: {fileID: 1000012251039328}
    m_IsPrefabParent: 1

基本的にプレハブの参照関係が書かれています。
また参照 {fileID: 1000012251039328}は、
このファイルIDを参照していることを意味しています。
ファイルIDは、ファイル内でユニークな値ですので、違うファイルにも同じ値があることがあります。また、{fileID: 0} はどこにも参照していないことを示しています。
では、このプレハブが参照しているファイルIDのゲームオブジェクトを見ていきましょう

--- !u!1 &1000012251039328
GameObject:
  m_ObjectHideFlags: 0
  m_PrefabParentObject: {fileID: 0}
  m_PrefabInternal: {fileID: 100100000}
  serializedVersion: 4
  m_Component:
  - 4: {fileID: 4000012487135774}
  m_Layer: 0
  m_Name: GameObject
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1

先ほど参照されていたファイルIDと同じものだということが1行目で確認できますね。
先ほど示したものはプレハブの情報だけしか載っていなかったのですが、ここからはゲームオブジェクトにくっついている様々なコンポーネントなどの情報が書かれています。
ここで大事な部分は、7行目のm_Componentの部分です。
これはこのゲームオブジェクトにどんなコンポーネントがついているかの参照が書かれています。

m_Component:
- 4: {fileID: 4000012487135774}

ここでは、オブジェクトクラスIDとファイルIDの参照が書かれています。
4という数字がオブジェクトクラスIDで、Unityのリファレンスで確認してみると、Transformということがわかります。
では、この参照されているTransformのファイルIDをファイルないから探してみましょう。

    --- !u!4 &4000012487135774
    Transform:
      m_ObjectHideFlags: 1
      m_PrefabParentObject: {fileID: 0}
      m_PrefabInternal: {fileID: 100100000}
      m_GameObject: {fileID: 1000012251039328}
      m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
      m_LocalPosition: {x: 2464.8406, y: 272.8769, z: 0}
      m_LocalScale: {x: 1, y: 1, z: 1}
      m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
      m_Children: []
      m_Father: {fileID: 0}
      m_RootOrder: 0

これが参照されているファイルIDのオブジェクトです。
確かにオブジェクトクラスIDに示されえている通りTransformですね。
TransformなのでPositionやRotationなどの項目がありますね。
またm_GameObjectの参照を見てみると先ほど見ていたゲームオブジェクトに参照がされていることがわかります。

まとめ

いかがだったでしょうか?プレハブファイルが読めるようになるとgitでコンフリクトした時にも役に立つので皆さんも是非読んでみてくださいね。
興味のある人はSceneファイルも同じ形式で書かれているので読んでみるといいと思います。
もう少し詳しく知りたいなら、Unityマニュアルの
https://docs.unity3d.com/ja/current/Manual/FormatDescription.html
のところを読んでみると面白いと思います。

プランナーがやる発注の仕方~敵キャラ編~

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

皆さんこんにちは
モツ太郎です。
そろそろ記事のネタが尽きてきました…
そんな中今回どんな記事を書こうかなーと思っていたのですが、せっかくなので最近から始めたプランナーが行う発注について書いていこうかなと思います。
※いつも通り個人のやり方なので悪しからず。

そもそも発注とは?

新しいマップやイベントを行う際には当然敵のキャラクターも場面にあったものを作らないといけないですよね。
そこで、こういう敵がほしいというのをデザイナーさんにお願いすることが、発注となります。

発注の要件

個人的に発注を行う際に必ず伝えているのが、以下の二つになります。
・モチーフは何か
・どういう形をしていてほしいか

この二つの中身についてちょっと解説していきます。
まず「モチーフは何か」というところですが、当然デザイナーさんにお願いするときには前述したとおり新しいマップやイベントの時にすることが多くなります。その時にそのマップやイベントのイメージを伝えます。
イベントが一番わかりやすいと思うのですが、例えば4月の「花見イベント」や8月だと「海イベント」など大枠のイメージを伝えます。

次に「どういう形にしてほしいか」というところですが、大雑把に言うと人型であるかそれとも動物の何かをモチーフにするのか、はたまた機械的な何かにするのかというのを指定します。例えばですが、4月の花見イベントの時の敵キャラを酔っぱらった人にしてほしいといったように書くための大まかな指針を立ててデザイナーさんにお願いします。

おわりに

今回はデザイナーさんへの発注について書き綴って見ましたが、いかがだったでしょうか?
今回の記事では最低限ここは抑えておくべきというところを書いていきました。
人によってはもっと細かく指定する場合もあります。ただ、自分の中では「餅は餅屋」という考えがあり、基本的には細かく指定しないでそのデザイナーの想像力に任せたいかなと考えています。(もちろん相手もプロであるという前提の上でですが…)
この記事を読んで、発注することがある人がいたら上記の最低の要件を抑えつつ自分なりにどこまで相手にお願いするかということを考えて発注をすればいいと思います。
今後こういう機会がある人の役に立てば幸いです。

bashをカスタマイズして快適なgit生活

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

gitを利用して開発する際に、branch名を入力するのが煩わしいというのが悩みでした。
何か良い方法は無いかと調べた結果、簡単に補完出来るようになることがわかりました。
また、合わせてプロンプト上にgitの情報を表示できるようになったので、そちらも紹介したいと思います。

参考にした記事:
MacのターミナルでGitのブランチ名を表示する
MacのGitで補完を効かせたりブランチ名を表示する設定

環境

CentOS release 6.5 (Final)

git-completion.bashの利用

git-completion.bashは、gitコマンドの補完スクリプトです。
こちらを利用することで、tab補完を利用することが出来るようになります。
gitのインストール時に既に準備されているので、そのまま利用することが出来ます。

$ find / -name "git-completion"
/usr/share/doc/git-1.7.1/contrib/completion/git-completion.bash

環境やgitの導入方法によって、パスは異なるようです。(自分はyumで導入しました)
また、個別に直接入手することも可能です。

git/contrib/completion

git-prompt.shの利用

git-prompt.shを利用することで、プロンプトでgitの情報を表示出来るようになります。
こちらも同様に、インストール時に準備されているものか、直接入手したものを利用します。

git/contrib/completion

利用方法はgit-prompt.shに記載されているので、今回は一部を紹介したいと思います。

$ find / -name "git-prompt"
/usr/local/git/contrib/completion/git-prompt.sh

bashrcへの記述

git-completion,git-promptを読み込むことで、補完やプロンプトへの情報表示を実現します。
それぞれを読み込んだ後に、__git_ps1を環境変数に加えれば、情報の表示が可能です。

今回は、色の変更も合わせて行いました。
また、__git_ps1には様々なオプションがあるので、用途に合わせてカスタマイズすることも可能です。こちらもgit-prompt.sh内に説明があります。

~/.bashrc

# git-completion,git-promptの読込
source /usr/share/doc/git-1.7.1/contrib/completion/git-completion.bash
source /usr/local/git/contrib/completion/git-prompt.sh

# __git_ps1のオプション指定

## unstaged fileがある時は*, staged fileがあるときは+を表示
GIT_PS1_SHOWDIRTYSTATE = 1
## stash fileがあるときは、$を表示
GIT_PS1_SHOWSTASHSTATE = 1
## untracked fileがある時は、%を表示
GIT_PS1_SHOWUNTRACKEDFILES = 1

# 環境変数PS1の変更
export PS1='\[\033[1;32m\]\u\[\033[00m\]:\[\033[1;34m\]\w\[\033[1;31m\]$(__git_ps1)\[\033[00m\] \$ '

実際の画面は以下のようになります。
デフォルトのまま使っていたので、だいぶわかりやすくなりました。
また、gitコマンドやbranch名もtab補完出来るようになっています。

利用例

おわりに

tab補完のおかげで、branch名の入力ミス等が減りだいぶ捗るようになりました。
色々調べていると、まだまだ作業に役立ちそうなカスタマイズ等を見かけるので、暇をみて試してみたいと思います。

イカしたSlackの使い方!知っていると役立つ3つの機能!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Slackを使っていてただチャットツールとして使っているだけでは気づきにくい、でも知っていると便利な使い方を3つご紹介します。

Slackって何?

“よくぞ聞いてくれました!Slack とは一連の業務の拠点となるデジタルワークスペースです。人々と組織、そしてツールをつなぐことで、作業効率を改善し、組織を活性化します。”※

Slackガイドより引用

ビジネス向けのチャットツールという認識の方が多いのではないかと思います。
使っていて楽しいこともあってビジネスに限らずコミュニケーションツールとしても有用です。
今回はSlackを使っていてただチャットツールとして使っているだけでは気づきにくい、でも知っていると便利な使い方を3つご紹介します。

自分と会話しよう!?

ダイレクトメッセージを打つところに自分の名前があるのは皆さんお気づきでしょうか?
そうです!なんとSlackでは自分と会話が出来るんです!
自分と会話出来たからなんやねん!って思った方、甘く見てはいけません!
To Doリストを作成できたり、リマインド設定することで簡易タスク管理も出来てしまいます!
工夫次第では他にも活用できるかもしれませんね。
enter image description here

Threadを活用しよう!

Threadとは話題ごとに発言を別途まとめることが出来る機能です。
チャットツールにありがちな発言が多くて前の話が流れてしまって反応しづらいなどといった状況を防ぐことができます。

実際どのようにして使うのか見ていきましょう。

Step1
enter image description here
使い方は簡単、発言のリアクションボタンの横の「Start a thread」を選択。

Step2
enter image description here
これだけでThreadが作成できました。
あとは「Reply…」にメッセージを打つだけ!

Step3
enter image description here
今回は一つ目に紹介した自分にダイレクトメッセージを送る機能と併用してタスクの詳細チェック表を作ってみました。

通知はどこに来るの?
enter image description here
ちなみに通知はAll Threadsにきます。
通知が来ると「All Threads」が「New Threads」に変わります。

大勢の人が参加しているチャンネルでもトピックごとに会話をすることが出来るのでまだ使ったことがない人はぜひ活用してみてください。

チャンネルを使い分けよう!

パブリックチャンネルであればJOINしなくても他のチャンネルを見ることができる。
これはSlackの大きな特徴の一つとも言えるでしょう。
すでにご存知の方も多いと思います。
既存チャンネルに入らなくても先に会話を見れることで入る前に自分もそのチャンネルに参加するかどうか考えることが出来ます。お試しに近いイメージですかね。(決して覗き見しているわけではありませんよ!)
この機能はコミュニケーションツールとしては非常にありがたく、またビジネスの観点からは同じ会社の仲間の仕事の状況の把握や、ノウハウの共有などに役立ちます。
どうしても見られたくない、社内の中でも一部の人間が知るべき情報などもあると思います。そんなときはプライベートチャンネル。JOINしていない人は見ることは出来ない設定もきちんと用意されています。
上手く情報を共有して、皆で活用していきたいですね。

まとめ

今回は
自分にダイレクトメッセージを送る機能の活用
Thread機能について
パブリックチャンネルとプライベートチャンネルを使い分ける

以上3点をご紹介しました。Slackを使い始めて数カ月と初心者であるため、基本的な内容になりましたがSlackは中々便利なツールだと感じています。まだまだ他にもbotやスラッシュコマンド、外部サービスとの連携など多くの機能があるようです。その辺り詳しいことはまた別の機会に書きたいと思います。
それでは皆さん良いSlackライフを!

※本記事の内容は個人の見解によるものを含みます。

夏の気だるさは暑さのせいじゃない?クーラー病とは

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

最近都会独特の暑さにやられつつあるBe82Mです。
九州で生まれ育ち上京して今年初めての夏を過ごしていますが、都内は排熱やコンクリート等でこもったような暑さ。想像を超える辛さで会社でも家でもずっとクーラーがついた部屋で過ごしていますが、それでもけだるい。なんか頭痛い。いろいろ調べていたらクーラー病なるものを見つけたので、症状や原因、対策についてまとめてみようと思います。
 

症状と原因

人によってさまざまですが、頭痛やだるさ、肩こり、不眠症、食欲不振などが主な症状。これよりも症状がひどくなっていくと発熱、吐き気までしてくる人もいるようです。これは、自立神経の乱れが主たる原因だそうで、クーラーの温度を涼しく設定しすぎてしまうと体が冬と勘違いして寒さに対応しようとし、外に出ると暑いので今度は暑さに対応しようとします。これを繰り返すと自律神経が混乱してしまい、このような症状が出てきてしまうようです。
夏になるとなぜかこれらの症状が出てくる、という人はクーラー病の可能性が高いです。
 

対策

これらの症状を改善する方法をいくつか調べてみました。

外気と室内の温度差を5度以内に抑える

体感的に涼しさを感じるまで設定温度を下げてしまいがちですが、一番の原因はこれ。
温度差が激しすぎると先述したように自律神経を混乱させてしまう要因になります。

でも暑いから強くしてしまう…

クーラーの設定温度を下げず、他の方法をとりましょう。
※ どうしても暑い場合は熱中症の危険性も出てきてしまうため少しずつ温度を下げましょう。

  • 首元を冷やす
  • 扇風機を利用する
     寒いけど公共の場はどうにもできない…温度だけでなく、単に体を冷やさないようにするだけでも対策になるようです。
  • ブランケットや軽い羽織りものなどで体を冷やさないようにする
  • 温かいものを口にして体の内部から温める

外で汗をかいた後にクーラーの効きすぎた部屋に入ってしまうと夏風邪をひいてしまう原因にもなるので気をつけましょう。
 

食生活を改める

主に夏野菜といわれるものは体温を下げる効果があるため暑さを凌ぎやすくなるため、夏野菜を摂取するといいそうです。逆に、冬野菜は体温を上げる効果があるものが多いため、あまりよくないようです。
夏野菜:きゅうりなどのウリ科、トマトやピーマン、ナスなど
冬野菜:大根や白菜、ほうれん草など
また、夏の暑い日にキンキンに冷えた飲み物はとてもおいしいですが、体を急激に冷やすのもあまりよくないので、せめて寝る前は控えるようにしましょう。
 

最後に

夏の気だるさや頭痛は暑さが原因とばかり思っていましたが、暑さゆえの行動が原因だったようです。
今後は少しずつ生活を見直して夏を乗り切りたいと思います。

立ち絵を魅力的に描く②【体型による個性を考える】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

nocoです。夏らしからぬ涼しい気候が続いたかと思いきや最近また暑くなってきましたね。

前回に続き立ち絵を魅力的に描くためのポイントを共有したいと思います。
今回はキャラクターの体型による個性についてお話しします。

体型による個性とその特徴

一つの世界観を作り上げる中で、同じ年齢や体型のキャラクターばかりがいるわけではないと思います。
体型の異なる4人の男性のシルエットを並べてみます。
enter image description here

衣服を着用していないただの素体ですが、シルエットだけでもそれぞれの年齢がおおよそ伝わるのではないでしょうか。

シルエットを外しました。
enter image description here

子供は大人に対し線が細く体に対して頭が大きく、
太った人はお腹が突き出て少しだらしない立ち方に、
老人は腰が曲がり体のバランスを杖で支えたり…
年齢、体型によってさまざまな特徴があります。
日頃からプロポーションの比率を観察してみましょう。

背格好や肉の付き方に伴って立つ時の重心も異なってきます。
その点も意識して立ち絵に取り込むことでキャラクターの個性が強まります。

キャラクターデザインはシルエットだけで誰か判別できると良いと言われていますね。
髪型や服装はもちろんですが、体型やその特徴を意識して描き分けることでシルエットも自然と差別化されていきます。

体型の異なるキャラクターが並ぶことでお互いの個性を引き立て、そのコントラストによってそれぞれをより魅力的に見せてくれます。
ヒーローがいるからヒロインはより美しく、ヒロインがいるからヒーローはより格好良くなるものです。
イラストそのものの魅力も大切ですが、キャラクター同士のバランスも考えてデザインできると尚良いでしょう。

終わりに

趣味でイラストを描いているとどうしても自分の得意なタイプのキャラクターばかり描いてしまうのですが、業務で老若男女を描く中でそれぞれの個性の付け方について考えさせられました。
体型の描き分けだけでもキャラクターの職業や人柄を表現することができます。
前回お話したポーズや表情による表現とも合わせて、さらに魅力的なキャラクターを作っていきましょう。

立ち絵の描き方については今回でおしまいになります。
次回からまた別のテーマでイラスト制作に関する記事を書いていきたいと思います。

第3回「Lionがゲームプランナーになるきっかけを与えたゲームとは!?」

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

第3回「第3回!Lionがゲームプランナーになるきっかけを与えたゲームとは!?」を話します。 興味があれば、見ていってね!

みなさんお久しぶりです!Lionです。
前回の記事いかがだったでしょうか?
和製と海外製のゲームって何が違うのだろう?が少しでも伝わったのであれば、こちらとしても嬉しいです。

さて、本日は「第3回!Lionがゲームプランナーになるきっかけを与えたゲームとは!?」について話させていただきます。
今回は、自分語り的な内容となりますがお付き合いくださいませ(੭ु´・ω・`)੭ु⁾⁾

「自分の人生を変えたゲーム」

enter image description here
私の人生を大きく変えたゲームのタイトルは「ゼルダの伝説 時のオカリナ」です。
今じゃアクションRPGの金字塔と言われるほど人気の作品です。
※『ゼルダの伝説 時のオカリナ』は、1998年11月21日に任天堂より発売されたNINTENDO64用アクションアドベンチャーゲーム
ゼルダの伝説 時のオカリナの公式ページ
※Wii Uのバーチャルコンソールではありますが、公式ゲームPVがありましたので載せておきます。
Wii U ゼルダの伝説 時のオカリナ

少しゲームの概要を話しますと…
ゼルダの伝説シリーズの第5作目であり、今までの2D作品からシリーズ初の3D作品となったことが最大の特徴です。
3Dになったことにより、奥行きのある立体的な空間内をよりリアルな視点位置で見渡すことができるようになりました。もちろん、バトルや謎解きにも革新的な変化がもたらされました。

・3Dゲームに付きものだったカメラワークや操作性の問題点を軽減する「Z注目システム」
・Aボタンアクションでの特殊アクションの自動化

それ以外でも、カットインムービーも多数盛り込まれ、物語の臨場感を大幅に高めています。
シナリオ面でも、少年リンクと青年リンクに区分したことで、色々なリンクを見ることもでき、
猪の怪物だけだった魔王ガノンに「ガノンドロフ」という本名と人間の姿が与えられ、以後のゼルダ作品の要素・設定に引き継がれシリーズに与えた影響は大きかった模様。

完成度の高さと革新的なゲーム性は世界中から高く評価され、第3回CESA大賞や、第2回文化庁メディア芸術祭 デジタルアート部門 大賞など、日米欧で数多くの賞を受賞した。

いわゆる神ゲーである( ˘•ω•˘ )
参考資料:Wikipedia

「人生を変えるほどに面白かった理由とは?」

当時、このゲームを始めてプレイした時が、確か小学三年生くらいだったかなぁと思います。
あまりに面白すぎるor感動してしまい、父親に段ボールで剣や盾を作ってもらったほどです(笑

今でもニコニコ動画などの実況プレイ動画を見たり、友人と寝ずに全クリアできるかなど
徹夜で遊ぶほどです。

では、私を含めた世界各地のユーザーを魅了した「時のオカリナのパワーとは一体何か!?」を要素ごとに書いていきます。

「過去、現在、未来を行き来する圧巻のストーリー!」

enter image description here
ハイラルのコキリの森に住む少年リンクは、いたって普通の子供でした。
ただ、コキリの森に住む住人として、必要なパートナーである妖精を自分だけ持っておらず、仲間に馬鹿にされている日々。
そんなある日のこと、リンクのもとに妖精ナビィが訪れ、コキリ族の守護神である「デクの樹サマ」が危機に落ちていることを知らせにやってきます。
勇敢な少年リンクは、デクの樹サマの体内に入り、苦しませている原因の魔物を退治しました。
しかし、蝕まれたデクの樹サマの命までは戻らず、命尽き果てていくデクの樹サマから最後に森の精霊石を授けられ、ハイラルで「神に選ばれし姫」に出会うように言われます。

ここから、少年リンクの大冒険がスタートします。
「神に選ばれた姫」に出会いなさい。
子供のころこれにすごくワクワクとドキドキを隠せませんでした。

その後、ゼルダ姫に出会ったリンクは、彼女から魔盗賊ガノンドロフの野望と精霊石の秘密を聞かされます。
ガノンドロフは聖地に眠る「トライフォース」を得るため、その地への扉を開くために必要な「精霊石」を探していると…。
リンクはガノンドロフの野望を阻止するため、彼より先に精霊石を集めて聖地への扉を開こうとした。
そして、扉を開けることに成功した。しかし、扉の鍵である「マスターソード」を引き抜いた途端に、リンクの身体が封印されてしまうとう事態に!?
封印の末に大人に成長したリンクは封印が解かれ7年もの歳月を得て目を覚まします。
しかし、ハイラルは既に「力のトライフォース」を得たガノンドロフに支配されていた…
ガノンドロフを倒すためには「伝説の賢者」の力が必要であると聞かされたリンクは、賢者たちの協力を得るため、マスターソードを手にハイラルを救う勇者になり立ち向かうのであった!

これが大まかなストーリーとなります。
このストーリーは、この先のゼルダの伝説シリーズに多大な影響を及ぼしたと言っても過言ではありません。
少年時代、青年時代、とリンクのハイラル世界に対する視点も変わってくるのも面白さの1つです。
また、自分が子供の時にプレイしたのもあってか、少年リンクから青年リンクに変わって世界を救うという部分に「自分も大人になったら世界を救うんだ!」と心から思っていました(笑)
当時、自分と同じことを思った方も少なくはないんじゃないでしょうか?

「3Dだからこそできるゲームシステム!」

enter image description here
ゼルダシリーズおなじみの謎解きとアクションというゲームシステムは色あせない状態で、完全に3D用として制作されました。
「草や岩を持ち上げて任意の方向に投げる」、「ヒビの入った壁や石像を爆弾やハンマーで壊す」など過去作同様のアクションを3Dでもできるように開発!
また、このゲームにおいて一番大事なシステムである「Z注目システム」があります。

プレイヤーは対象となる物体を任意にロックオンすることができ、対象物に向かって移動したり、パチンコや弓矢などを確実に当てることを可能としたシステムです。
このシステムのおかげで、戦闘もしやすくなり、対象が見えなくならないようにカメラワークもセミオートで補正してくれるため、キャラクターの位置の把握や敵との間合いを取ることが分かり易い&容易となるのです。
このシステムによって、3Dアクションの難点とされていたカメラワークと操作性の問題が大きく改善され、以後多くの3Dアクションゲームに類似したシステムが搭載されることとなりました。

戦闘が苦手な人でも気軽に楽しめます。
自分も小学三年生でしたが、とても戦いやすかったのを覚えています。
また、フィールドを自由自在に走り回り、剣や弓矢で敵をバッサバッサとなぎ倒していくのもとても面白かったです。
当時、ここまで爽快感があるゲームはそうそうなかったと思います。

「全てのダンジョンの謎解きやギミックが面白い!」

enter image description here
ゼルダの伝説シリーズおなじみの謎解きやギミックですが、過去最高だとユーザーからの声も高いと思います。
ダンジョンで手に入れたアイテムや武器を使って謎を解き、そしてボスを倒すという過去作と同じですが、3Dになったことで、天井、床、壁と360度全体でギミックを仕込むことができます。
特に、皆様お馴染みである「水の神殿」の難易度は今になっても語り継がれていると思います。
神殿内の水位を変動させて、移動したり物を動かしたりするのが本当に難しかったです。
この神殿で手に入る「ロングフックショット」は、壁にフックをかけて、そこまで飛んで行ったり、遠くのアイテムを引き寄せたりできる神アイテムでした。
また武器にもできるというところも魅力の1つです。

ちなみに私は難しすぎて友人にクリア法を教えてもらった経験があります(笑)
今ではきちんとクリアできます。しかし、大人の方でも初見でプレイさせると確実に詰まると思われます。
それほどに難しいですが、プレイ応えがある最高のダンジョンでもあります。

「ここまで話してみて…」

どうでしょうか?少しでも「ゼルダの伝説 時のオカリナ」の魅力は伝わったでしょうか?
まだまだ、語ろうと思えば語れますが、際限がないのでこれくらいにしておきます。

そして、私がゲームプランナーになると決めた理由は、「自分自身で、ゼルダの伝説 時のオカリナのような面白い世界を作ってみたい!そして、自分が作ったゲームで自分が味わったこの感動を世界中の人たちに伝えたい!」と子供の頃に思ったからです。
実際、大人になってもこの思いは色褪せることはありませんでした。
現在はプランナーとして働いていますが、もっと上を目指して精進していく所存です!

今回の記事、いかがだったでしょうか?
「ゼルダの伝説 時のオカリナ」の魅力や筆者ってこんな人なんだなぁというのが少しでも伝わってくれたら嬉しいです。

次回は来月開催されるTGS(東京ゲームショー)についてお話します。
「第4回 TGSで日本ゲーム大賞に選ばれた作品たち!」についてお話します(੭ु´・ω・`)੭ु⁾⁾
※筆者は極度のファンです
では、みなさん!夏ももう終わりですが熱中症にはお気を付けください( ˘ω˘ )

N+1問題

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

 railsで開発しているとN+1 Queryというエラーに遭遇しました。このN+1 Queryについて調べてみると、別名N+1問題と呼ばれており、サービスのパフォーマンスを落とす問題の一つであることがわかりました。今回は、この問題を解決する為に調べたN+1問題の原因と解決方法について記事にしました。

N+1問題とは

 N+1問題を簡単に説明すると、クエリがデータ数よりも多くなります。データ数よりも多くのクエリが発行されることで、サービスのパフォーマンスを低下させます。少量のデータの場合は、問題を感じることは少ないと思いますが、実際にサービス運用では膨大なデータ量を扱うことがほとんどなので放っておくことはできません。

問題発生例

 実際に、どのような場合にこの問題が発生するのか例題を使って説明します。
 以下のようなハードウェアモデルとソフトウェアモデルが存在するとします。ハードウェア1つに対して複数のソフトウェアが結びつく関係です。

class Hardware < ActiveRecode::Base
  has_many :softwares
end

class Software < ActiveRecode::Base
  belongs_to :hardware
end

 この2つのモデルを使用したコードが以下にありますが、このコードがN+1問題を発生させてしまいます。このコードの処理は次のことを行っています。
1. ジャンルがアクションのソフトウェアのデータを取得
2. 取得したソフトウェアのデータ1つ1つに対してハードウェアのデータを取得

softwares = Software.where(genre: "action")
softwares.each do |software|
  software.hardware
end

1.の処理では、ジャンルがアクションのソフトウェアをまとめて取得している為、クエリの数は1つになります。
2.の処理では、取得したソフトウェアの数だけバードウェアを1つずつ取得しているので、クエリの数は取得したソフトウェアの数になります。
つまりこの2つの処理では、取得したソフトウェアの数をNと置き換えると、N+1のクエリを発行していることになります。

解決方法

 N+1問題の原因は、データ一覧取得後、取得していないデータを参照していることです。(上の例だと、ソフトウェアを取得している時にハードウェアを取得せずに、後から取得している。)この原因を解消する為に、データ一覧取得時にincludesで関連するデータをまとめて取得する方法があります。下のコードは、先ほどの例題にincludesを使用して改善したものです。

softwares = Software.where(genre: "action").includes(:hardware)

 このようにincludesを使用することで後からデータを参照した場合でもクエリが発生することはありません。includesを使用した場合のクエリ数は、ジャンルがアクションのソフトウェア取得の1回と取得したソフトウェアに結び付くハードウェアの取得の1回の計2回となります。

まとめ

 RailsエラーでN+1という文字を発見したら、クエリが余分に発行されていないか確認してincludesで対応しましょう。

CLIPSTUDIOvsPhotoshopここはこうなる仕様の違い②

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

イラスト作成ツールのCLIPSTUDIOPAINTとPhotoshopの各ツールやコマンドの仕様を比較してみました。

 こんにちはtokinです。
 前回の続きでイラスト制作ソフト「CLIPSTUDIOPAINTPRO」と「PhotoshopCC」の仕様の比較を行いました。大きな違いは勿論ありますが同じツールで異なる仕様も多数存在します。この記事は私がイラスト制作を行っている最中に気づいた微かな違いをご紹介していきます。

前回の記事はこちらCLIPSTUDIOvsPhotoshopここはこうなる仕様の違い①

今回も引き続き比較対象は

  • セルシス CLIP STUDIO PAINT PRO(クリスタ)
  • Adobe PhotoshopCC2017(フォトショップ)

この上記二点のソフトです。
 ちなみに文の中にクリスタEXが登場しますがこちらはCLIP STUDIO PAINT PROをバージョンアップさせたCLIP STUDIO PAINT EX というソフトです。こちらはPROよりも更に漫画作成に特化しているタイプのものでPROの仕様に加え様々なシステムが加わったソフトとなっております。
それでは続いていってみましょう。

キャンバスに右クリック

 クリスタでは右クリックを押している間だけスポイトツールが、フォトショップの右クリックではブラシサイズ設定のタブが開かれます。右クリックの設定については今のところどちらのソフトもカスタマイズは不可能な様子です(クリスタは右クリックの無効化なら設定可能です)。ちなみにフォトショップで一時的にスポイトツールを使用したいときはブラシやバケツツールを選択した状態でAltキーを押すと、クリスタのように押している間だけスポイトツールに代わります。

レイヤーを別キャンバスに貼り付け

 クリスタでは別キャンバスにレイヤーを移すときはコピー&ペーストを行います。逆にフォトショップでは、キャンバスを二面開いた状態で移動させたいレイヤーをそのままドラッグ&ドロップすることで内容を移すことができます。勿論コピー&ペーストで移動することもできるのですがその際はまずコピーしたいデータを選択範囲に入れる必要があります。コマンドだとCtrl+A(全面選択)→Ctrl+C(コピー)→Ctrl+V(ペースト)でできます。ちなみにドラッグやペーストしてデータを移動させる際、shiftキーを押しながらペーストすると移動する前のキャンバスと同じ位置にデータを配置できます。

直線コマンド

 クリスタもフォトショップもShiftキーを押しながら直線を引くことができます。直線の始まりに点を打ち、そこから引きたい線の終点をShiftキーを押しながら打つと直線が描けます。クリスタとフォトショップの違いはクリスタの場合は終点を打つ際にどんな線が引けるかガイドが表示されるところ。これによって描く前の線の角度、長さや太さをよりイメージしやすくしてくれます。
 勿論コマンドではなく直線ツールそのものも搭載されています。クリスタでは図形のサブツール内に、フォトショップではシェイプツールの設定を「シェイプ」→「ピクセル」に変更すれば通常レイヤーに直線が引けます。

色調補正

 クリスタにも色調補正は備わっていますがフォトショップは圧倒的です。写真編集ならではの「自然な彩度」、「露出量」や「カラーフィルタ」など画像データをさらに細かく補正・調整できるシステムが備わっています。
 驚いたのは色調補正レイヤーの存在でした。作画したレイヤー本体の色調は変えることなく、全体の色調の調整のみを色調補正レイヤーで行えるのです。試しに色味を変えてみたり様々な色調補正を重ねたり…これらが全てレイヤーで管理できてしまうのです。補正レイヤーは複製することもクリッピングマスクをかけることもできるので特定のレイヤーのみの調整も可能です。結合すれば補正内容はそのまま適用されます。

フィルタ・アクション機能

 デフォルト状態のクリスタPROにもさほど多くはないのですがぼかしやシャープなどのフィルタが存在しています。更にバージョンアップしたクリスタEXでは有志のユーザーが作り出したフィルタプラグインを導入することができます。一方写真加工に特化したフォトショップに実装されているフィルタはとても多いです。フィルタ一つで一味違った雰囲気の画像にしてしまえるので単体で使ったり重ね合わせたりして使ってみたいもの。デフォルトで備わっているのでCDジャケットのようなスタイリッシュな画像まで簡単に作り出すことが出来ます。
 また、クリスタPRO/EX・フォトショップの両方に備わっているアクション機能もオススメです(クリスタではオートアクション機能と呼ばれています)。これを使いこなせばフィルタを使ったような画像加工も一発でできるのです。というのもこちらはソフトでの一連の作業を記憶し、必要なときに再びそれを利用できるようにする機能なのです。幾つかの工程を記録させればワンクリックでそれらを自動で実行してくれるので短い時間でクオリティの高い加工が行えます。クリスタもフォトショップも、DLできるフィルタプラグインやアクション機能がネット上に多数存在しておりますのでぜひ自分好みの機能を探してみてください。

レイヤー効果

 クリスタのレイヤー効果のうち注目したいのがトーン効果です。レイヤーで描いた部分をそのままトーンに変更できてしまうのでこれ一つで漫画作成で大変だったトーン作業がとても楽になります。色の濃度はそのままトーンの濃さに反映されるので濃さに合わせてドットの大きさも自動で調整してくれます。効果を外せばもとの状態に戻すこともできドット数やドットの形も変更できます。またバージョンアップされたクリスタEXのみの実装なのですが線画抽出のレイヤー効果もそのまま漫画背景にできそうな線を抽出してくれるので話題となっています。enter image description here
 フォトショップのレイヤー効果は「グラデーション」から「ドロップシャドウ」、「べベルとエンボス」など平面を加工するものから影をつけ立体にみせる効果などバラエティに富んでいます。その富み具合たるや直接描き込まずとも効果のみでも数段クオリティをあげたものことが作れるほど。レイヤー効果のすばらしいところは拡大縮小しても効果自体は荒れないところ。UIボタンなどのサイズを変更する可能性の高いデータには効果での演出もオススメです。
enter image description here

素材

 どちらのソフトにもネット上に豊富にありますが、クリスタは漫画作成向けソフトということもあってペンツール・トーン素材が特に多く、写真加工からはじまり色彩に強いフォトショップはブラシ素材が豊富な印象を受けます。クリスタはCLIP STUDIO内のサービスから素材を検索・配布・DLすることができ、DLしたものは全てクリスタペイント内の素材欄に表示されますので後はペンツール内にドラッグして読み込みが完了します。フォトショップは個々のサイトからDLしたabr.データをフォトショップのブラシパレットから読み込み取り入れます。また、サイトの他にもAdobeのもつ「Adobe Stock」というサービスもあり、こちらからも素材の検索やDLが可能です。色を塗ったり、線を描いたりするペン・ブラシツールの中でも煙や泡、花やサラダなどスタンプに近いバラエティ豊かな素材も登場しているのでぜひ探してみてください。

最後に

 いかがでしたでしょうか。最後に前回今回と書き連ねました内容を表にまとめました。
enter image description here
 個人の趣味、業務範囲で使ってみて感じたレベルなので掘り出せばもっとそれぞれの似た点便利な点たくさんあると思います。今回はどちらの設定もデフォルト状態での比較でしたが中にはコマンド設定で差が気にならなくなったりカスタマイズでより自分に合う使い方に仕様変更できたりします。ソフトを移行したときに混乱しない為にも是非自分好みのソフトにカスタマイズしてみてくださいね。それでは。

【Unity】オブジェクトプーリングでオブジェクト節約術

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

オブジェクトを生成・破棄する際にかかるコストを、簡単なオブジェクトプーリングの仕組みを実装して軽減してみます。

まえがき

こんにちは。17新卒エンジニアのinoooooocchiです。
今まではUnity入門的なネットに溢れかえってるような記事をここ(DoRuby)に投稿していましたが、そろそろ多少は実用的な記事を書かなければいけないと気を引き締め、今回はオブジェクトの生成・破棄と”オブジェクトプーリング“について書いていきます。これを皮切りに、これから少しずつ技術的な話を書いていきたいと思います。(願望)

Unityにおけるオブジェクトの生成・破棄

Unityでは、オブジェクトを新たに生成したり、使い終わったオブジェクトを破棄したりする際、それぞれ Object.Instantiate や Object.Destroy を用いて行います。
一般的に、オブジェクトをスクリプトで生成する場合、UnityのPrefab機能を用いてオブジェクトのPrefabを作っておき、それをスクリプトに渡して Instantiate することで生成します。

この Instantiate・Destroy はゲームを動かす上で何百、何千、何万回も呼ばれるであろう関数ですが、処理が重いことで知られています。
(→ Debug.Log() や Instantiate() などの速度を計測してみる (外部サイト))

スマートフォン向けにゲームを作ってみよう!と思い立ち、いざUnityを立ち上げてゲームを作ってみると、意外とこの Instantiate・Destroy の負担は目に見えて現れます。
弊社で運営しているようなRPGベースのゲームでは頻繁に Instantiate と Destroy を繰り返すことは少ないですが、アクションゲームやシューティングゲームなどでは必然的に敵や弾などのオブジェクトの数が多くなるため、Instantiate や Destroy を行う回数は相当なものです。
特に筆者の好きな弾幕系シューティングゲームでは物によっては合計数百〜千程度の弾オブジェクトが生成されては消えを繰り返すため、スペック次第では処理落ちが発生し、プレイヤーの操作感を損なうことに繋がってしまいます。
(コルーチンならフレームを跨いで処理が行えるため、処理落ちを多少は回避できそうですが、今回は置いておきます)

オブジェクトプーリングしよう

そこで登場するのが、 “オブジェクトプーリング” という手法です。
オブジェクトプーリングとは、一定数のオブジェクトを溜めておく(poolしておく)ための貯蔵庫のような物を作り、オブジェクトが必要になったら取り出し、使い終わったら戻すことで、なるべく少ない数のオブジェクトを使い回してオブジェクト数及び生成・破棄のコストを抑えようというものです。
リサイクルみたいなもんです。

今回は、受け取ったPrefabを元にGameObjectを最初に一定数まとめてInstantiateで生成し、それらを使い回すといった簡単なオブジェクトプーリングを実装してみます。
また、最初に生成した数では足りなくなった時は、逐次生成してプールしているリストに加えます。

実装

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ObjectPool : MonoBehaviour {
    private List<GameObject> _poolObjList;
    private GameObject _poolObj;

    // オブジェクトプールを作成
    public void CreatePool(GameObject obj, int maxCount){
        _poolObj = obj;
        _poolObjList = new List<GameObject>();
        for (int i = 0; i < maxCount; i++) {
            var newObj = CreateNewObject();
            newObj.SetActive(false);
            _poolObjList.Add(newObj);
        }
    }

    public GameObject GetObject(){
        // 使用中でないものを探して返す
        foreach (var obj in _poolObjList) {
            if (obj.activeSelf == false) {
                obj.SetActive(true);
                return obj;
            }
        }

        // 全て使用中だったら新しく作って返す
        var newObj = CreateNewObject();
        newObj.SetActive(true);
        _poolObjList.Add(newObj);

        return newObj;
    }

    private GameObject CreateNewObject(){
        var newObj = Instantiate(_poolObj);
        newObj.name = _poolObj.name + (_poolObjList.Count + 1);

        return newObj;
    }

}

オブジェクトを管理するオブジェクト(例: 大砲の弾を管理する大砲オブジェクト)でObjectPoolクラスのCreatePool関数にオブジェクトのPrefabと最初にまとめて生成する個数を渡すことで、オブジェクトプールがリストとして作成されます。
生成されたオブジェクトはSetActive(false)で非アクティブ状態にしておきます。
今回の場合、オブジェクトが使用中かどうかをアクティブかどうかで判断しているためです。
管理オブジェクトからGetObject関数が呼ばれた場合、リストの中から使用されていないものを探して返します。
リスト内のオブジェクトが全て使われていた場合、新たに1個だけオブジェクトを生成し、それを返します。

それでは、実際にプールするオブジェクトと管理オブジェクトを作り、動作を確認してみます。

オブジェクト管理クラス

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

[RequireComponent(typeof(ObjectPool))]
public class BulletCreator : MonoBehaviour {

    [SerializeField] private GameObject _bulletPrefab;
    private const int BULLET_MAX = 50;
    private int _state = 0;
    private float _originDirection = 0.0f;
    private bool _isReverse = false;
    private ObjectPool _pool;

    private void Awake () {
        _pool = GetComponent<ObjectPool>();
        _pool.CreatePool(_bulletPrefab, BULLET_MAX);
    }

    // Update is called once per frame
    void Update () {
        if (_state % 30 == 0) {
            var way = 16; // 16方向
            for (int i = 0; i < way; i++) {
                var bullet = _pool.GetObject();
                if (bullet != null) {
                    bullet.GetComponent<Bullet>().Initialize(_originDirection + i * (360.0f / way), _isReverse);
                }
            }
            // 発射のたびに10度ずつ回転し、弾の回転方向を反転
            _originDirection = (_originDirection + 10) % 360;
            _isReverse = !_isReverse;
        }
        _state++;
    }
}

オブジェクト

using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {

    private float _speed = 4.0f;
    private float _direction;
    private bool _isReverse;
    private Rigidbody2D _rigidBody;

    public void Initialize(float direction, bool isReverse){
        _direction = direction;
        _isReverse = isReverse;
        _rigidBody = GetComponent<Rigidbody2D>();

        if (_isReverse) {
            GetComponent<SpriteRenderer>().color = new Color(1.0f, 0.3f, 0.3f); // 赤っぽい色
        } else {
            GetComponent<SpriteRenderer>().color = Color.white;
        }

        SetDirection();
    }

    public void Update(){
        if (_isReverse) {
            _direction = (_direction - 1) % 360;
        } else {
            _direction = (_direction + 1) % 360;
        }
        SetDirection();
    }

    public void OnBecameInvisible(){
        gameObject.SetActive(false);
        ResetPosition();
    }

    private void SetDirection(){
        Vector2 v;
        v.x = Mathf.Cos(Mathf.Deg2Rad * _direction) * _speed;
        v.y = Mathf.Sin(Mathf.Deg2Rad * _direction) * _speed;

        _rigidBody.velocity = v;
    }

    private void ResetPosition(){
        _rigidBody.velocity = Vector2.zero;
        transform.localPosition = Vector3.zero;
    }
}

動作確認

enter image description here

画像サイズ上限の都合上短いですが、上記ソースコードでは最初に生成するオブジェクトプールを50個に設定しており、数が足らなくなったことで追加で2個生成されています。
管理オブジェクトは、30フレームに一度、16個の弾を発射するようになっています。
画像は管理オブジェクトが弾を発射する様子を5秒程度切り取ったものなので、本来なら160個のオブジェクトが必要なところ、オブジェクトプーリングを導入することで52個のオブジェクトで済むようになっています。
これが1分2分と続いていくとしても、弾が定期的かつ規則的に発射される限り、52個前後のオブジェクトで本来なら数千個必要なオブジェクトを賄えるということになります。
すなわち、数千回分のInstantiate・Destroyを削減出来たわけです。

最後に

今回の実装は、オブジェクトプーリングの形だけを作りましたが、実際にゲームで運用するためには幾つか改善すべき点があります。

  1. ObjectPoolがオブジェクト管理オブジェクトと1:1の関係になっているため、同じオブジェクトを生成する管理オブジェクトが複数ある場合、ObjectPoolを共有できず無駄が多い
  2. 最初に生成しておくオブジェクトの数を大きくし過ぎると、最初だけ処理が重くなる  →描画コストなどとの兼ね合いですが、基本的には逐次生成が良さそうです

実際はゲームの種類やシステム、オブジェクトの特徴などによって、どのような形式のオブジェクトプールを使うのか考える必要がありますね。
また、オブジェクトプーリングの考え方はUIにも応用出来ます。
例えば何らかのオブジェクトを一覧表示してスクロールさせるUIでは、最初に幾つかオブジェクトを生成しておき、スクロールに応じて中身を入れ替えることで擬似的にたくさんのオブジェクトが並んでいることを表現できそうです。

以上、「オブジェクトプーリングでオブジェクト節約術」でした。

誰が買うゲーム?~顧客について考える~

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

自分の作りたいゲームを作る!という人は「関係無い」と思うかもしれないが、 整理しておくと困ったときに役立つのでそういう人も一度しておきたいのが顧客についての研究だ。勿論、売り上げを出すには必須となる。

どんな顧客がターゲット?

 売る相手となる顧客から考えるか、作りたいゲームがあってそこから考えるかはそれぞれの製作状況によるが、とにかく「どんな人がターゲットなのか」はなんとなくでも想像はついているはず。
 もし、顧客について考えずに単に「RPGを作る!」とだけ思って作り始めてしまうと「あれもいれたい、これもいれたい・・・」と右往左往するのは目に見えている。RPGと一口に言っても男性女性、子供、成人など色々な層が存在しているのだから、しっかり考えるのは重要だ。
 今回は「小学生の男の子向け冒険活劇RPG」を例にして考えてみる。総務省の統計によれば平成27年(2015年)4月1日時点で日本の小学生(6~11歳)の男の子の人口は330万人となっている。こういった役所から調べられる情報はきちんと収集しておきたい。

参考:http://www.stat.go.jp/data/jinsui/topics/pdf/topics89.pdf(我が国のこどもの数 – 総務省統計局)

ターゲットとなる顧客について考える

 年齢と男女が決まったので、本格的にターゲットとなる顧客について考えていく。その顧客がどんな性質かを見極めるのには様々な観点、手法があるが、今回は「整理したい項目を並べてそれらについて考える」とする。なお、ネットアンケートをとるなどの手法は有効だが、費用がかかるので今回は割愛させていただく。
 今回の例では小学生の男の子が対象なので、例えば「難しい表現や漢字は分からない」といった事を最終的に整理した結果として得ることとなる。以下のように簡単にExcelでまとめてみた。内容や項目は適当なので、詳しくは「マーケティング 基本」などで調べてみるといいだろう。
enter image description here

顧客からゲームを考える

 さて、小学生の男の子の特徴をまとめたところで、どんなゲームにすれば良いかを考えてみる。ここまで特に触れていなかったが、ゲームの形態としては「携帯ゲーム機での買い切りゲーム」としている。
 所得の少なさや相場から考えて価格は5000円程度に抑えることは必須そうだ。趣向を「冒険活劇」としているが、小学生の男の子でも冒険活劇が好きではない子もいるだろう。こういった「携帯ゲーム機を持っている」「冒険活劇が好き」といった項目によって実際の顧客対象となる人口は減っていくこととなる。両方を満たすのは330万人の5割と想定すると165万人となる。(実際には何かしらの手法でどれぐらいの割合となるかは調べる必要がある)
 次に、知識や経験の少なさから、「難しい表現や漢字は使わない」「チュートリアルは丁寧に」「カッコいい演出やストーリーにする」などといった事が決まってくる。プレイ環境は複数人プレイが容易なので、ゲーム構成によっては通信対戦などを取り入れることも出来る。こういった「どんなゲームにするか」の方針も顧客の特徴を掴むことで立てられる。

まとめ

 いかがだっただろうか。きちんと顧客について想定をしていないと、「思ったより全然売れなかった」なんていうことが起こってしまう。仕様に迷ったとき、「どんな顧客か」に立ち返れば多くのことはどうするのが最善か分かるので、しっかりと整理して記録しておきたい。それでは、良い製作ライフを。

Rails時短の巻 -seed編-

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

いちいち本番で1からデータを作る必要なんてありません。既存seedに時間がかかるならまず使うことをやめましょう。DBのダンプと差分管理と並列処理で本番へのデータ投入を爆速にするのです。

はじめに

みなさま、お久しぶりです。新卒エンジニアのくろすです。
素手人間になって久しいですが、たまーにオレンジ折りたくなる衝動に襲われます。

今年こそは一番綺麗な空を飛べると信じて初日参加します。
推しが出るので2日目も参加します。
3日目はチケットがありません。チケットが、ありません。

データ投入用高速seed

localでダンプしたデータを差分管理しつつ直接本番に流し込める高速seedをyaml_dbparallelを用いて作成したのでその紹介です。

差分を管理してデータ更新を高速化する、seed_fu:expressのご紹介
を参考に差分管理を実装し、
RailsのDBの初期データ(rake db:seed用)をyamlで美しく管理する方法
をヒントにデータをyaml_dbで管理することを思いつきました。
実際にはテーブル毎のダンプが出来さえすればいいのでmysqldump等でも問題ないと思いますが、sql管理に比べデータの視認性が良い、手修正がしやすいという2点からyaml_dbを使っています。
まだブロックスタイルでしかダンプできていないのであまり使い勝手はよくありませんが、フロースタイルでダンプできるようにできれば手修正はより容易になると思います。

背景

弊社ではExcelで作成していることが多いゲームのマスターデータですが、これはそのまま使うものもあればdbに投入する際にプログラム側で使いやすくするため加工するものもあります。
このデータを加工する作業というものは、ゲーム運営が長くなりデータが増えていくに従い時間を食う作業になっていきます。
また、このデータの作成に他のモデルを参照しながらデータを作るような書き方をしていると各masterに依存関係が生まれ並列処理できないため、既存seedプログラムにがっつり手を入れなければ高速化のしようがない…なんてこともあります。

新卒としてアピリッツに入社しrubyを書き慣れるにつれ、DRYに精神を乗っ取られ始めました……
スゥパァドゥルァァァァイ
今回の場合Don’t Repeat Ourselfでいきましょう。
なにもデータ作成までDBサーバーで行う必要なんてどこにもありません。
データ作成はlocalのみで行い本番はそのデータだけを流し込んではいけない決まりなんてありません。
すっぱりきっぱりと既存のseedを捨て去る覚悟をしましょう。

投入用データ作成

とりあえずdb:seedの後にダンプを行うrake taskを作ります。

namespace :gundum do
  desc "gundum:seed"
  task :seed => :environment do
    Rake::Task["db:seed"].invoke
    Rake::Task["db:dump_masters"].invoke
  end
end

できました!!!ガンドゥムSEEDです!!!!
この高速seedを作ってる時にseedにinvokeを生やそうと[ seed invoke ]でググってしまったあの日からこれをやろうと心に決めていました。

さて、ここで呼んでいるdb:dump_mastersですが中身はyaml_dbの拡張である以下のプログラムをロードするようになっています。

module YamlDb
  module SerializationHelper
    class Base
      # @Override
      def dump_to_dir(dirname, *dump_table_names)
        Dir.mkdir(dirname) if Dir[dirname].empty?
        tables = if dump_table_names.present?
                   dump_table_names
                 else
                   @dumper.tables
                 end
        tables.each do |table|
          File.open("#{dirname}/#{table}.#{@extension}", "w") do |io|
            @dumper.before_table(io, table)
            @dumper.dump_table io, table
            @dumper.after_table(io, table)
          end
        end
      end
    end
  end
  module RakeTasks
    MASTER_TABLES = ["fizz_master", "buzz_master"].freeze
    def self.dump_masters
      SerializationHelper::Base.new(helper).dump_to_dir("#{Rails.root}/db/masters/yml", *MASTER_TABLES)
    end
  end
end

#--------------------------
YamlDb::RakeTasks.dump_masters

テーブルを指定したダンプが行えるよう拡張して、マスターのみダンプする新しいRakeTaskを追加しています。

データ投入と差分管理

一番最初に紹介した
差分を管理してデータ更新を高速化する、seed_fu:expressのご紹介
を参考に差分管理しつつデータ投入を行えるようyaml_dbを拡張していきます。

require 'parallel'
module YamlDb
  module SerializationHelper
    class Base
      def load_masters_from_dir(dirname, truncate = true)
        updated_masters = []
        Dir.entries(dirname).each do |filename|
          next if filename =~ /^[.]/
          master = MasterVersion.find_or_create_by(master: File.basename(filename, ".yml"))
          checksum = Digest::MD5.file("#{dirname}/#{filename}").to_s
          if master.chesksum == checksum
            p "✔ "
          else
            p "✖"
            updated_masters << master
          end
        end

        if updated_masters.present?
          Parallel.each(updated_masters) do |master|
            filename = "#{master.name}.yml"
            begin
              ActiveRecord::Base.transaction do
                @loader.load(File.new("#{dirname}"/#{filename}", "r"), truncate)
                master.save!
              end
            rescue => e
              p "✖"
              raise e
            end
            p "✔ "
          end
        end
      end 
    end
  end

  module RakeTasks
    def self.load_masters
      SerializationHelper::Base.new(helper).load_masters_from_dir(dump_dir("/masters/yml"))
    end
  end
end

#--------------------------
YamlDb::RakeTasks.load_masters

テーブル情報の管理にMD5を使っています。
MD5の衝突耐性は容易に突破され、ハッシュ値から入力値を求めることができるようになっていますが、テーブル管理に使うくらいなら問題ないでしょう。
手元のファイルからハッシュ値を計算しているため、管理対象のテーブルがタイムスタンプを持っている場合は削除しておきましょう。
seedで更新されるデータのの更新時間なんてそんな使うもんじゃありません。

後はこれを標準のrakeから使えるようにrake taskを作ります。

namespace :gundum do
  desc "gundum:seed_destiny"
  task :seed_destiny => :environment do
    load "gundum/seed_destiny.rb"
  end
end

U・N・M・E・I 感じちゃいますね

まとめ

今までローカル反映にすら15分ほどかかっていましたが、一度誰かが取り込み済みのデータなら全データ入れ替えても1分30秒で済むようになりました。
既存seedが遅い原因は富豪プログラミングによるString.newが走りまくることだったので、それも解決。
結果としてデータ入れ替えながらの作業が捗るようになりました。
gundum:seed_destiny最高ですね。

BOM付きUTF-8で文字化けしないCSV出力

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Railsで出力したCSVファイルがExcelで文字化けを起こしてしまった場合にBOMを付けて対応する方法をまとめました。

はじめに

 またまた1か月ぶりの投稿となります、むらさきです。探していたSwitchも無事購入できて同期と日々インクを掛け合ってます。
さて、データベースに入っているデータをCSVファイルにUTF-8で出力してExcelで見られるようにしたい!と思い実装してみたところ盛大に文字化けしていた…なんて経験誰もが1度は体験したことがあると思います。
文字化けした文字を解読して読んでやる!…と挑戦した経験も1度ではないと思います。
 ですが、僕に文字化けを解読する能力は備わってなかったようなので、今回はUTF-8の文字コードにBOMを付けて、出力する段階で文字化けしないようにする方法をまとめようと思います。

目次

  1. BOMとは?
  2. CSVをUTF-8で出力する
  3. 終わりに

1.BOMとは?

 BOMとは、バイト・オーダー・マーク(Byte order mark)の略で、Unicodeの符号化形式で符号化したテキストの先頭に着ける数バイトのデータのことです。
 ExcelはCSVファイルを開くときデフォルトでShift-JISで開きに行ってしまいUTF-8では確実に文字化けしてしまいます。ですがUTF-8で出力する際にこのBOMを付けることでExcelにUTF-8で書かれていると認識させることができます。

2.CSVを出力する

 今回は適当な日本語をBOM付きUTF-8とBOM無しUTF-8でCSV出力してExcelで文字化けしているかどうかを確認するところまでやりたいと思います。
まずはBOM無しCSVを出力します。

require 'csv'
def csv_export
  File.open(path + 'test_doruby.csv', "w:UTF-8") do |f|
    csv_data = CSV.generate do |csv|
      csv << csv_text
    end
    f.write(csv_data)
  end
end

def csv_text
  [
    "これは",
    "UTF-8の",
    "BOMなしの",
    "testです"
  ]

 このメソッドを実行すれば、pathに指定した場所に”test_doruby.csv”がUTF-8で作成されるのでそれをExcelで開いてみます。
enter image description here

 案の定日本語の部分が無駄に画数の多い漢字の羅列に置き換わりました。先ほど述べたようにUTF-8をShift-JISで開きに行っているからです。

では次に先ほどのコードを書き換えてBOMを付けます。

require 'csv'
def csv_export
  File.open(path + 'test_doruby_bom.csv', "w:UTF-8") do |f|
    bom = "\uFEFF"
    csv_data = CSV.generate(bom) do |csv|
      csv << csv_text
    end
    f.write(csv_data)
  end
end

def csv_text
  [
    "これは",
    "UTF-8の",
    "BOMありの",
    "testです"
  ]

bom = "\uFEFF"
と宣言し、CSV.generateの引数に渡すことでBOMを付けることができます。

BOMを付けたファイルをExcelで開いてみると
enter image description here
文字化けなく表示することができました。

3.おわりに

 いかがだったでしょうか、今回紹介した方法以外にもWindowsのメモ帳で表示してから保存し直すなど、BOMを付ける方法はありますが何度も出力する必要がある場合はこちらの方が手間が1度でいいので良いと思います。自分の状況にあった方法を選択してください。

最近人気な記事