投稿者「tsuyoshi」のアーカイブ

誰も教えてくれない。エンジニアのためのブログの書き方〜書けば書くほどキャリアアップした話〜

tsuyoshi|2018年07月26日
イベント/登壇

tsuyoshi(@numanomanu)です。技術ブログを書きたい!書いた記事をみんなに読んでもらいたい!と思っている方に向けて、 1年間で qiita コントリビューション 2,500 、はてブ総数 1000 弱(2018/07/01 時点)のエンジニアが 0 からここに至るまでに実施したノウハウをエンジニアのためのブログライティング入門 という内容で登壇したので、資料を公開します。

対象者
– エンジニアや技術のブログを書いたことないけど、書きたいと思っている人
– 書いてはいるけど qiitaのいいねやはてブが思うように伸びない人

内容

  • 記事を書くようになって自分に起きた変化
  • どんな記事を書けば良いのか?
  • ネタの集め方、どうやってブログを書けばいいのか?
  • まさかりが怖くないのか?
  • いいねやはてブの集め方
  • おまけ

エンジニアブログを書いたことのない人が、ブログを書くきっかけになれば嬉しいです。
また、ブログを書いてる人達が、もっといいねやはてブをもらえるようになれば、この上なく嬉しいです。

新規事業開発におけるエンジニアの心得〜失敗事例から学ぶツクラナイ開発〜

tsuyoshi|2018年06月19日
DevOps

tsuyoshi(@numanomanu)です。
先日、エンジニア向けのイベントで登壇して来たので、その時の資料を共有させていただきます。【サポーターズCoLab勉強会】新規事業開発におけるエンジニアの心得
私自身、昨年、CtoCサービスの新規事業の立ち上げからリリース、グロースまでを一通り経験させていただきました。その中で多くの失敗や学びがあり、ぜひその内容をシェアさせていただければと思います。特に、自分が新規事業で携わった pook というサービス(テレビにも何度か取り上げられました)を作っていく上で、主に失敗したことをベースに、学んだことや、こうしておけばよかったことなどを共有できればと思います。

内容としては

  • 作りすぎて失敗した事例紹介
  • つくりすぎないためにどうするか、コアバリューという考え方がとても大事
  • ユーザーに向き合うことが一番重要
  • 早く作って早く出す

など、実例や結果を交えながら説明しています。
文面だけでは伝えられない感があるので、是非興味を持っていただいた方は弊社に聞きに来てください。

社員さすらいワーク制度でテレワークと週末小旅行を楽しむ〜岡山県編〜

tsuyoshi|2017年12月29日
イベント/登壇

ランサーズ社の福利厚生制度に「社員さすらいワーク」という制度があります。
https://www.lancers.co.jp/news/pr/12740/

企業の働き方改革や複業を取り入れたい企業の支援をする「オープン・タレント推進」の取り組みの第二弾として、テレワーク活用によって地域での活動を支援する試み「社員さすらいワーク」を実施します。 社員さすらいワークとは、2020年に向けた「働き方改革」の国民運動プロジェクト『テレワーク・デイ(2017年7月24日開催)』に合わせ、従業員に地域でのテレワークを推奨する取り組みです。

 

実際に社員が提携自治体でテレワークするだけでなく、そこで行われている「ライター養成講座(セミナー)」の補助講師として参加し、全国各地でランサーズを活用する人を増やすことも行っています。

ランサーズと提携している自治体の中で、セミナーが行われる地域に社内から応募して参加します。

自分は岡山県和気町に行ってきたので、そのレポートをご紹介したいと思います。

 

当日までの準備

地方自治体で行われるライティング講座のセミナーはランサーズ社員メンバーだけではなく、全国各地にいる地域ディレクターと呼ばれる、すでに活躍しているランサーさんたちを講師に招いているため、その方たちとの打ち合わせや、各自治体の担当者の方との顔合わせがあります。
ランサーズ本社からビデオ通話で自治体や、地域ディレクターの方と MTG して当日の段取りなどや、連絡事項の確認などを行いました。
(みなさんいい人ばかりで、初めての土地に行くのも安心です!)

さすらいデー

セミナーは2日目なので、1日目は岡山の好きな場所でテレワークができます。

東京から岡山間の新幹線でも作業をしていたのですが、あまり集中できなかったので近くのカフェを散策しました。

勉強カフェというなかなか良さそうなカフェがあったのでこちらで作業しました

電源 wifi 完備。飲み物もフリードリンクで飲み放題。おいてあるお菓子も何個かいただきました〜。

定時までこちらのカフェでテレワークしました。
近くの席で学生さんが受験勉強してました。なんだかいつもより身が引きしまる思い。

仕事終わりは岡山を探索

 

駅前の桃太郎のイルミネーション。
渋谷で言うハチ公みたいな感じですかね、待ち合わせスポットのようで人がたくさんいました。

 


ホテル近くの川。クリスマス感。(12/22)

移動で少し疲れたので、今日はここまで。
泊まったホテルは肉まん、アイスキャンデーが食べ放題でした。

 

二日目(講師補助)

ライティングセミナーの講師補助として、和気町に向かいます。

和気駅までの道。
早朝の電車は通勤や通学の人たちで割と混んでいました。
ここに住んでる人は当たり前かもしれないですが、あさひが田んぼに反射してきれいでした。

 

電車は山陽本線、オレンジ色が可愛い。和気駅にて

講師の方に車で迎えに来てもらっていざ和気町の役場へ!

講師のお二方。お二人ともバリバリのフリーランス!

セミナー開始

終始笑顔の絶えない楽しいセミナーでした~。

受講生の皆さんがサービスの使い方で詰まった箇所は、開発チームに共有され、改善要望として issue が立ちます。また、実際に使っている生のユーザーの声が聞けるので、普段作っていると気づかないところを教えてくれるので、非常に良いサーベイにもなります。

トップフリーランサーの方が講師なので内容もとても充実していて、リアリティのある講座が特徴的です。

特に講師の方の金言が、忘れられないです。

「お金を払ってスキルアップするより、お金をもらってスキルアップする方が結果として自分の成長につながる。」

自分がやったことのない案件でも、チャレンジしてみます!というふうに仕事を受けて、お金をもらっているからこそ、真剣に取り組めるという事実。

「お金を生み出すのは「時間」ではなく「成果」」

「終身雇用はファンタジー」

「今の時代、情報はアウトプットしてこそ信頼が得られる」

 

次回の講座が非常に楽しみです(全4回の1回目)

すでに、この講座の受講生でライティングの案件をもらっている方が何人もいて、この講座すごいなと実感しました。

時間の都合上、和気町をあまり散策できなかったのが心残りですが、次はいろいろ見て回ろうと思います。

 

週末旅行編

週末は岡山県周辺を散策しました。
(週末の分の出張費は出ないので、普通に実費です)
岡山県岡山市は、自転車先進都市おかやまを掲げており、「ももちゃり」という自転車貸し出しサービスを行っているため、市内の観光地などへの移動は、これを利用してみました。

市内のあちこちに、ポートがあり、アプリでポートの空き状況などを確認できます。

フェリカ搭載 IC カードや携帯端末、携帯電話(会員登録用)を持っていれば、ポートですぐに会員登録できます。

登録したカードをかざせば、自転車を取り出せます。

平日は通勤にも利用されているのか、結構な数のももちゃりを見かけました。

岡山城と後楽園

ももチャリで駅から飛ばすこと15分ぐらいでしょうか、岡山城と後楽園に到着。ゆったりと和菓子をいただいたり園内を散策しました。

お堀(?)から眺める岡山城。かっこいいですね。

桃太郎っぽい人が歩いてた。

 

全体的に落ち着いた雰囲気で、リラックスな気分。紅葉シーズンや、桜のシーズンにまた来たい。

瀬戸大橋

岡山といえば瀬戸大橋!
鷲羽山と言う山に登って、瀬戸大橋を一望しました。

 

児島駅からバスでこられるので、オススメです。

倉敷

定番の倉敷

街の雰囲気が落ち着いていて好きです。半日くらいでくるっと回れるので、私のように体力のないエンジニアにも優しい設計の街だと感じました(笑)

 

グルメ

おかやまといえばフルーツ!。
岡山駅前のイオンに売っていた白桃をいただきました。
単に甘いのではなく、みずみずしさと甘さを兼ね備えた上品な味がしました。これはまた食べたい。

おかやま周辺で人気のラーメン屋に行ってみました。
小豆島の醤油と魚の出汁が効いたスープがうまかったです。

変わった味のサイダーが売ってました。オリーブ味の方はハイチュウみたいな味がして個人的にかなり好みの味でした。醤油サイダーは・・・

そずり鍋。そずり肉の入った鍋。そずり肉とは骨の周りの肉のことらしいです。脂がのっていて大変美味でした。

白桃パフェ。
岡山の白桃を使ったパフェ。これより大きいサイズは売り切れてました。

倉敷名物的な地元野菜などを使った料理。右側にちょっと写っているのは黄ニラと言う、暗所で育てたニラです。刺身みたいな食感で自分にとって新感覚でした。

 

まとめ

最後の方はただのグルメ旅行記になってしまいましたが、テレワークしつつ週末小旅行することは、控えめに言って最高です。
業務の方もほとんど問題なく、進行できました。営業職ではないのと、もともとリモートで仕事をするメンバーがいたりしたので、チャットでのコミュニケーションやタスク管理もオンラインで完結できるため、ほぼ平常通りでした。(テレワーク周りの取り組みについても需要がありそうだったら書きます。)

 

以下に、「さすらいワーク」制度のメリットをまとめます。

 

ユーザーの生の声が聞ける

ライティングセミナーの講師補助として参加することで、普段どんなユーザーが、どういう気持ちで使っているのか、現場でフィードバックが得られるため、プロダクトを作る上での参考にもなり、とても有意義でした。今後のサービス向上に努めたいと、改めて気が引き締まりました。

 

テレワークを通して、地方で働くランサーの疑似体験ができる

ランサーズを利用しているユーザーは、ほとんどオンラインで仕事をしています。実際に運営している我々は東京のオフィスで仕事をしているため、すべてオンラインで完結させているユーザーの気持ちを完全に理解することはできません。しかし、こういった体験を通すことで、少しでもその感覚を理解でき、それらをプロダクトに反映していけるのではと思います。

 

小旅行を通してリフレッシュできる

普段、東京で働くよりも、開放的な土地で仕事すると、頭も心もリフレッシュできます。また、気分を単にリフレッシュさせるだけでなく、旅行を通して新たな発見や、その土地の魅力に気づくこともできます。今回は、岡山県を少し旅してみて、岡山県が好きになりました。こういった取り組みを通して、各地域と連携して、今後もサービスを盛り上げていければと思います!

さすらいワークをしたいエンジニアの方募集してます!また、さすらいワークの提携先として提携していただける自治体の方も募集してます!

某お笑い番組っぽい結果発表シーンを JavaScript CSS で再現してみた

tsuyoshi|2017年12月03日
JavaScript

tsuyoshi(@numanomanu)です。ランサーズアドベントカレンダ−3日目の記事です。前回 React Redux を用いた SPA 新規サービスを運用して得た知見と実装例 を書いたので、今回も引き続き javascript 周りについて書きました。話は変わりますが、忘年会シーズンですね。会社でクイズ大会などのお楽しみコンテンツがあるかもしれません。今日はそんな時にしか役に立たない(!?)某お笑い番組的な結果発表シーンを JavaScript と CSS を使って再現するチップスのご紹介です。

雑な完成品は以下の gif 画像または、 音出ます注意 からどうぞ

これはランサーズ、「熱狂」の全社合宿を実施しました! にて、地方プレゼンバトルというコンテンツで利用した、結果発表をインタラクティブに表示する仕組みです。地方プレゼンバトルとは各地方出身者がその土地の魅力を発表しあい、頂点を争い合う競技です。(最終盤はもう少しクオリティが高いのですが、著作権などを侵害しないように現バージョンで止めております)
最初に、審査員たちの得点をスタイリッシュに並べるシーンがあり、合計得点をドーンとだし、最後にグイッと結果を表示するというフローでできています。

今回は上記を実現するために使った Javascript と CSS のテクニックを、それぞれご紹介します。

数字をクルクルしてシュキーンとさせる



<li class="kurukuru">50</li>


.kurukuru {
  transition: transform 0.3s ease-in;
  transform: rotateX(0deg)
}
.start {
  transform: rotateX(1800deg)
}
  $('li.kurukuru').addClass('start')

クルクル要素は transform の rotate で実現できます。
1800 / 360 = 5 回クルクルさせてます。rotateX で x 方向(横軸)の回転を表現し、 start が付与されるタイミングで 0 -> 1800dg の角度回転します。
transition を使う事でプロパティの変更があった時に、一定時間(今なら 0.3s)の間でクルクル回転している様が再現されます。

さらに、手前から来ているシュキーン感を出すために、 scale を使い、最初は大きく、最後は小さくします。
こちらも transition の効果で、大きくなるところから徐々に小さくなっていく様が再現できます。
transition については、以下の記事が詳しくてわかりやすいです。
https://qiita.com/soarflat/items/4a302e0cafa21477707f

.kurukuru {
  transition: transform 0.3s ease-in;
  transform: rotateX(0deg) scale(5)
}

.start {
  transform: rotateX(1800deg) scale(1)
}

fps が荒いですがこんな感じ。

ブルブルっとさせる

.buruburu {
    animation: hurueru .05s;
    animation-iteration-count: 5;
}

@keyframes hurueru {
    0% {transform: translate(0px, 0px) rotateZ(0deg)}
    25% {transform: translate(2px, 2px) rotateZ(1deg)}
    50% {transform: translate(0px, 2px) rotateZ(0deg)}
    75% {transform: translate(2px, 0px) rotateZ(-1deg)}
    100% {transform: translate(0px, 0px) rotateZ(0deg)}
}

震えを再現するために、 @keyframes を使います。
またまた fps が荒いですがこんな感じです。

フォントをそれっぽくする

Google Fonts から、太めのフォントを探して、埋め込みます。
一番それっぽかった「Russo One」を利用しました。text-shadow を使えば、文字を立体的に見せることができます。

<link href="https://fonts.googleapis.com/css?family=Aldrich|Changa+One|Russo+One|Squada+One|Stalinist+One" rel="stylesheet">
.score {
    color: #ffee10;
    font-size: 4rem;
    font-style: italic;
    font-weight: bold;
    text-shadow: 1px 3px 0px #939393, 0px 6px 0px #949350;
    font-family: Russo One;
}

下からふわっとしてドーンとさせる

結果の順序を入れ替えるところを実装します。

.insertTarget {
  transition: opacity 0.6s, transform 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
  transform: translate(0px, 600px) rotateX(0deg) scale(5)
}
  $(function () { $('.insertTarget').css({
      transform: 'translate(0px, 200px) scale(5)'
  }).on('transitionend', function () {
      $(this).css({
          transform: 'scale(1)'
      }).off('transitionend');
  })});



<div class="insertTarget">hoge</div>



ポイントは、 jquery で ‘transitionend’ のイベントをキャッチして、 トランジションが終わった後に新たな transition を発生させています。
具体的には transform: translate(0px, 600px) で下から translate(0px, 200px) とふわっと出した後に、scale を scale(5) -> scale(1) に変更することで、吸い込まれるようなインサート感のあるアニメーションを演出しています。

キラっとさせる

結果のデータを目立たせるために、キラっとさせてみます。
こちらを参考にしました。
http://www.trust5.jp/jquery-light/

.kira {
    width: 100%;
    height: 300px;
    background: #4a3f3f;
}

.reflection {
    height      :100%;
    width       :30px;
    position    :absolute;
    top         :-180px;
    left        :0;
    background-color: #fff;
    opacity     :0;
    transform: rotate(45deg);
    animation: reflection 2s ease-in-out infinite;
}

@keyframes reflection {
    0% { transform: scale(0) rotate(45deg); opacity: 0; }
    80% { transform: scale(0) rotate(45deg); opacity: 0.5; }
    81% { transform: scale(4) rotate(45deg); opacity: 1; }
    100% { transform: scale(50) rotate(45deg); opacity: 0; }
}


<div class="kira">
  
<div class="reflection"></div>

</div>


ドゥクシッ!させる

音を出すには audio タグを使います

<audio id="duqushi" preload="auto">
  <source src="duqushi.mp3" type="audio/mp3">
</audio>
function duqushi() {
    var se = $('#duqushi');
    se[0].currentTime = 0;
    se[0].play();
}

音源は以下のサイトの 拳銃1 という音を利用しました。個人的にハマったドゥクシッ!音ですが、他にもたくさんあってお好みのものをどうぞ。
https://soundeffect-lab.info/sound/battle/battle2.html

着弾時にバーンと景気よく爆発させる

こちらの記事を参考にしました。
http://blog.enyojs.com/post/93812705854/sprite-tastic

css のスプライト画像を用意(930 x 400 で 10列、4行のスプライト画像)

930 × 400 のサイズなので、それぞれ、1コマ(93px)ずつ keyframes で切り取ります

@keyframes boom {
	0%     { -webkit-transform: translateZ(0) translateX(93px)   translateY(0px); }
	25%    { -webkit-transform: translateZ(0) translateX(-837px) translateY(0px); }
	25.01% { -webkit-transform: translateZ(0) translateX(93px)   translateY(-100px); }
	50%    { -webkit-transform: translateZ(0) translateX(-837px) translateY(-100px); }
	50.01% { -webkit-transform: translateZ(0) translateX(93px)   translateY(-200px); }
	75%    { -webkit-transform: translateZ(0) translateX(-837px) translateY(-200px); }
	75.01% { -webkit-transform: translateZ(0) translateX(93px)   translateY(-300px); }
	100%   { -webkit-transform: translateZ(0) translateX(-837px) translateY(-300px); }
}
.explosion {
    left: 0px;
    width: 93px;
    height: 100px;
    overflow: hidden;
    position: absolute;
}
.explosion:after {
    width: 930px;
    height: 400px;
    content: "";
    display: block;
    position: absolute;
    background-image: url(sprite-explosion.png);
    -webkit-animation: boom 1s steps(10, start) infinite;
 }

すると、以下のように、左から順にスプライトを表示し、アニメーションが完成します。

つなげてみる

var animationDelay = 1000;
$('li.kurukuru').each(function(i, elem){
  $(elem).delay(animationDelay * i).queue(function() {
    $(elem).addClass('visible').dequeue();
    $(elem).addClass('start').dequeue();
   });
});
<ul>
  <li class="kurukuru">50</li>
  <li class="kurukuru">20</li>
  <li class="kurukuru">39</li>
  <li class="kurukuru">14</li>
  <li class="kurukuru">10</li>
</ul>
.kurukuru {
  width: 100px;
  height: 100px;
  display: inline-block;
  transform: rotateX(0deg) scale(2);
  position: relative;
  visibility: hidden;
}

.visible {
  visibility: visible;
}

.start {
  transition: transform 0.3s ease-in;
  transform: rotateX(1800deg) scale(1);
}

ポイントは、 addClass では delay が使えないので、 queue と dequeue を使って、 順番にクラスを付与しているところです。
同じように、爆発のエフェクトや、ぶるぶるのエフェクトも、タイミングを合わせて class を付与して行えます。

応用例

スタイリッシュ(?)な自己紹介。

時限爆弾タイマー

あふれるほどのLGTM

最後に

最終的に色々組み合わせたりスタイルを当てると、以下のような仕組みが出来上がります。
全体のコードは 音出ます注意 の resources からダウンロード可能です。
ぜひ、今年の忘年会の結果発表などに役立てていただければ幸いです。

明日の記事は EC2オリジンのCloudFrontでサムネイルをキャッシュした話 です。

React Redux を用いた SPA 新規サービスを運用して得た知見と実装例

tsuyoshi|2017年11月15日
DevOps

@tsuyoshi です。先日行われた React Redux を用いた SPA 新規サービスを運用して得た知見と実装例 と言うイベントで使ったスライドをアップロードしました。 https://pook.life/ と言うサービスをReact Redux の SPA で運用して得た知見などを共有できればと思い。公開してみた次第です。

内容としては

  • 利用しているライブラリや開発環境、開発フロー
  • コードベースでの実装例の紹介
  • その他 SPA サービスを運用する上での構成や知見

など、実例や結果を交えながら説明しています。
何かの参考になれば幸いです。

スライドを貼ってますが、以下のgoogle スライドで見た方が、アニメーションとか動いて見やすいかもしれません。
https://docs.google.com/presentation/d/1TIEg5rYJ9vlWTSO6etwupBBO0egapA1lIwVh3Fw4k84

レスポンシブ対応の LP を簡単に作れるツールを React Redux で作った。ソースコードあり

tsuyoshi|2017年06月20日
JavaScript

pook チームの tsuyoshi です。レスポンシブ対応の LP を簡単に作れるツールへのニーズが社内で高まってきたので React Redux の練習がてら先日の開発合宿で作りました。社内でもランディングページの制作を依頼されたり、発注したりするわけですが、大体が同じようなデザインではないでしょうか?要件としては、アイキャッチがあって、レスポンシブ対応で、コンバージョンボタンがある。ぐらいです。企画などが立ち上がる度に新規作成しているとキリがありません。そういった工数を削減するためにも直感的な入力でLPを簡単に作れるツールを作ってみました。
その名も、 react-lp2cool(リアクトエルピーツクール)。

注意)残念ながらプロダクションレベルで使えるものではありません。作った物の共有程度なので、モックの作成ぐらいにとどめてください

こちらからダウンロードして頂くとすぐに使えます。サーバーやインストールも不要です。必要なのは、 index.html と bundle.js の二つだけ。ブラウザが動く環境であれば、すぐにLPを作れるのが、このツールの特徴です。

DEMO

アイキャッチと、タイトルを挿入

画像を選択して、タイトルを入力するだけです。

セクションを選択して追加し順番を入れ替える。

大まかなデザインは選択して入力し、細かい部分の調整は直接 HTML をいじることができます。ドラッグ&ドロップで入れ替え機能もついていて便利です。

レスポンシブ対応のコンバージョンボタンを置く

Bootstrap が内蔵されているので、レスポンシブ機能がお手軽に実装できます。

ダウンロードして完成

右下の「ダウンロード」ボタンを押すと最終的に index.html ファイル1枚にまとまります。操作画面は react ですが、出力はただの HTML です

いかがでしょうか?それなりのデザインのLPを作ることができました。(上記所要時間5分くらいです)

所感

React と Redux を使ってみる利点は、それなりの UI やインタラクションを持ったツールをライブラリなどをうまく利用することで、サクッと実装できる点です。
今回は編集ページに以下のようなライブラリを用いました
meterial-ui : ダイアログや、編集フォームのデザイン
react-sortable-hoc : ドラッグ&ドロップで並べ替え
redux-form : フォームの制御全般

コードもこちらに用意していますが、1泊2日の合宿で作った全く自信のないコードですので、あまり参考にしないでいただけると幸いです。主にランサーズ流 React.js/redux アプリ開発入門に記載してある構成を利用しているので、全体感を掴むにはこちらのソースコードとブログの解説を読むことを強くお勧めします。

ちなみに、社内でこのツールの運用を検討した結果、今回作ったツールのように HTML を直接書く運用よりも、 json や yaml 形式で必要項目を管理するやり方のほうが、社内利用でのニーズにマッチしているようでした。残念ながらモック程度の用途にとどまりそうです。

お知らせ

現在私が所属する pook チームでは、フロントエンド職の募集以外にも、サーバーサイド職の募集も行っています。新しい働き方を一緒に生み出しませんか?ご応募待ってます。

API仕様書をMarkDownで書き、GitHubをつかって運用する方法

tsuyoshi|2016年12月10日
DevOps

追記 2018/06/05
すぐに試せるサンプルリポジトリ作ったので、使って見てください。
https://github.com/TsuyoshiNumano/api_document_sample

生成されるドキュメント

開発サーバーを立ててリクエストする例


こんにちは、tsuyoshiです。
API仕様書の作成や、その運用。皆さんはどうやっていますか?

現在自分が所属するチームでは、以下のツールを使って API をドキュメント形式で書いて管理しています。

- api blue print: APIドキュメントを MarkDown で記述する言語
- aglio: APIドキュメントをHTML化するツール
- api-mock(新しいnode.jsで動かない) drakov: APIドキュメントをモックサーバ化するツール

API仕様書をドキュメントで管理することで、API仕様書をGitHubのプルリクエストベースで開発、運用を行うことができます。
具体的にツールを利用して仕様書を書く方法についてはAPI Blueprint で Web API の仕様を書くという記事やAPI 設計ドキュメントをGitHubのプルリクでレビューしつつ Apiary みたいに使うには、という記事が非常にわかりやすいので、この記事では触れず、運用についてだけお話しします。

以下に、API仕様書をドキュメントで管理して運用するイメージを示します。(API仕様書の記述内容などはダミーのデータです)

API仕様書の作成とその運用

この運用にする以前は Confluence などの 社内wiki で管理したりしていました。
しかし、社内wiki などで管理すると、コードを変更した後に、社内wiki の更新を忘れるなどして、仕様とコードが合わなくなるというような問題が発生したりしていました。

また、そういった問題を解決するために apidocというツールを使って、アプリケーションコード上にAPIの仕様書を記述していました。
コードと API仕様書が同じところにあれば、wikiを更新し忘れるようなことにもなりませんし、GitHub上でやり取りが可能なので、API仕様自体のレビューも一緒に行えます。
しかし、今度はコードに記述が増えることで、ロジック部分が読みにくくなったり、API仕様書の閲覧をディレクターが行うには、ツール群のインストールが必要になる、などの問題が発生しました。

そのため
– 仕様変更や更新が漏れ、メンテされなくなる
– コード内に記述しても、アプリケーションコード内に書くと見通しが悪くなる

というような状況が発生していました。
そういった観点も踏まえながら、現在は

  • API 仕様のドキュメントを MarkDown で記述
  • API 仕様書自体の閲覧は HTML ファイルで行う

といった方法を利用しています。そうすることで、API仕様書はアプリケーションコードと分離して MarkDown で書くことができますし、ディレクターもツールをインストールせずに、ブラウザですぐにAPIの仕様などを確認することができます。
他にも、api-mock drakovを用いて、API仕様書の内容をモックサーバから叩くという方法で開発を進めています。

上記のツールを使いつつ、 APIをドキュメントで管理するようにしたため、運用方法は以下のように行っています

  • GitHubのプルリクエストベースでAPI仕様書の更新を行う
  • APIに付随するロジックや補足説明は github issue へリンクさせる

APIに新しい仕様を追加したい時は、新しい機能を実装したプルリクエストを作成し、レビューが通ればマージします。
仕様変更をしたい時も、プルリクエストを作成し、レビューの中で議論を行い、レビューが通ればマージします。
GitHubのプルリクベースで運用することで、認識の差異を減らしつつ変更履歴の経緯などを追いやすくなるというメリットがあります。

また、APIの仕様書に書き込むだけでは足りない機能は issue に切り出します。
例えば、単なるリクエストと、レスポンスで解決できないような以下の要望があったとします

例)
画像登録用のAPIにPOSTした場合、画像のデータはある条件を加えて S3 に保存したい。

このような、APIのリクエストと、レスポンスだけでは済まないような機能の場合、issue に切り出します。
MarkDown で記述していることによって、リンクの挿入と閲覧が、以下のように行えます。
マークダウンにリンクを挿入

issue 自体をコードの中に埋め込むことで、HTMLファイルで開いてみたときに、どのAPIリソースの issue なのかが、リンクになっているので一目でわかります。
仕様をHTMLファイルで見ている人は、そのリンクを辿って、詳細な内容を確認することができます。
さらに、その issue 上で議論を行った結果などを残せるので、経緯などを追うことが可能です。
アプリケーションコード内に書くと、リンクをカジュアルに作って確認するということができなかったので、かなり重宝しています。

上記以外にも、仕様変更などを行う場合に issue のリンクを先に作って、それをMarkDown内に埋め込み、issue の対応を行ったら、そのリンクをMarkDown内から削除する。
というような運用を行えば、変更もれや更新もれを防ぐことができます。

まとめ
– github を利用した開発フローにより、コードレビューベースで仕様書をメンテナンスできる
– 仕様変更した際のプルリクエストを見れば、経緯なども追うことができる
– HTML形式のファイルに吐き出すことで、開発者以外もAPI仕様書の確認がスムーズ
– issue のリンクを活用することで、見通しが良くなったり、仕様更新もれなどを防ぐことができる

開発を行う上で、こういったドキュメントをGitHubで管理することで、人数が多くなった場合でもメンテナンスしやすい環境になるのではないでしょうか。
導入したものの、運用されないといったことは大いにあり得るので、ルールとツールをうまく使い分けて、今後も開発していければと思います。

究極のPDCA!その名も「PD鮨A」でプロダクト開発を超速化!

tsuyoshi|2015年08月14日
DevOps

ランサーズのtsuyoshiです。

今回も社内コミュニケーションを活性化させ、プロダクトをよりよくするような【ネタ】です。

サービスやプロダクト開発のPDCAにおいて、日々カイゼン要望を吸収し、高速なPDCAを回すことが必要不可欠です。

ですが、よくよく考えるとカイゼン案件自体が現在アサインされているプロジェクトのアドオン(150% workしましょうと???)だったりと

カイゼンしたくてもできない夜を過ごしているかと思います。

今回はそんな半ばやけくそ気味の状況を打開し、より高速にPDCAを回すためにランサーズで実践したプロダクト開発の手法についてです。

 

目次

  • す背景と目的:カイゼンプロジェクトの始動
  • しカイゼンのためのPDCAサイクル
  • がPDCAを回してみて変わったこと
  • たカイゼンプロジェクトの課題
  • べもっと高速に回すためのPD鮨Aサイクル
  • たダーツで白熱するカイゼン競争
  • いまとめ

 

背景と目的:カイゼンプロジェクトの始動

「最高のユーザ満足の創造」

これは、ランサーズの行動指針の一つで、日頃から使っていただいているユーザさんからの要望や意見を吸収し、プロダクトに反映していくことです。

とはいえども、実際の現場では、プロダクトに反映しようとしても都度対応になってしまったり、明確な案件として切られておらずと言った状態で・・・

特に、「大きな機能開発でやるからいいっか」という社内の某プロデューサーにあるように、次の施策でマージするケースは多々ありますが、お客さんはそれを待ってる間に「うーん、使いづらい・・・」と思っていたりもします。

そこで始まったPDCAを日々回していくサイクルが「カイゼンプロジェクト」でした。

カイゼンのためのPDCAサイクル

 

カイゼンのPDCA概念図

カイゼンのPDCA概念図

Plan(起案・案件整理)

ユーザさまからのお問い合わせや、社内要望を案件化し、いつでも着手できるように準備しておく。

DO(実行)

整理された案件を元に、エンジニアが空いた時間で着手し、カイゼンをリリースする。

Check(計測、結果報告)

施策による効果や、結果を報告

Action(さらなるカイゼン)

計測結果などをもとに、より良いカイゼンへと昇華させる

 

*世間一般で言われているPDCAとは少し異なりますが、図のようなフローでプロダクトをカイゼンしていくと捉えていただければ幸いです。

 

具体的に、それぞれのフェーズについて説明します。

 

Plan(起案・案件整理)

お問い合わせなどでよく上がってくる案件や、気づいた点、社内要望などを全部まとめてGoogle Spread Sheetに記載し1箇所に集約します。

お問い合わせの案件については、カスタマーコミュニケーション部門のメンバーに取りまとめてもらっています。

案件管理はスプレッドーシートで

案件管理はスプレッドーシートで

集約された案件は、細かい要件を詰めたり、確認を行って、「すぐに着手できそう」な状態にしてからwrikeというタスク管理ツールに登録します。

 

wrikeについてはこちら

www.wrike.com

(アフィリリンクじゃないよ!!安心して!!本当だよ!!)

 

Wrike上で精査した案件を一覧化

Wrike上で精査した案件を一覧化

 

整理された案件に「募集中」というワークフロータグをつけることで、着手可能な案件が一目でわかるので便利です。

誰でも気づいた人が着手できる状態を作っておくことで、空いた時間にすぐに取りかかることが可能です。

Do

「募集中」タグのついた案件を、エンジニアの手が空いた時間に見つけて実施します。githubのプルリクエストにはカイゼン用のラベルをつけます。

 

Check

社内で利用しているChatWork上にリリース情報や、その後の結果のデータを共有します。

 

Action

得られたデータを元に、さらなるカイゼンを行っていきます。

 

実際に行われているカイゼン事項の例:

  • わかりにくい文言の修正や、ガイドの追加
  • ボタンの大きさや表示位置の変更
  • インフラ周りの細かいパフォーマンスチューニング
  • 新しい技術やアーキテクチャの導入(socket.io-emmiter、Carbon、React、Flux)

などなど、大きいものから、小さいものまで、幅広くやっております。

とくに、新しい技術などは積極的に取り入れることで、エンジニアのモチベーションと共に、カイゼンが行われております。

 

PDCAを回してみて変わったこと

・プロダクトが徐々にカイゼンされるようになった。(きた・・・)

 5月初旬から始めて、8月までの3ヶ月で100個の案件をカイゼンしました。

 フローができたことによって、案件やアイデアが上がりやすくもなりました。

 

・社内の雰囲気が変わった

 Q:カイゼンプロジェクトによって変わったことはありますか?

他部署のメンバーからありがたいお言葉が

他部署のメンバーからありがたいお言葉が

カイゼンプロジェクトの課題

ここまでのやり方で、ある程度のフローの基盤はできました。

しかしながら、結局は一部のエンジニアしかカイゼンに貢献できていません。

エンジニアメンバー全員、カイゼンしたいという思いはあるもののけど、通常業務が忙しかったり、これでも動機づけが弱かったりして、なかなか全員とはいきません。

もっとキッカケやインセンティブがあれば、カイゼンに参加するのでは?

 

・・・・

 

そうだ!鮨にいこう!

そうだ鮨行こう。

そうだ鮨行こう。

 

「鮨」なら彼らも動くのでは。(ふふ・・・)

そうだ名前は、新発明「PD鮨A」だ・・

 

PD鮨Aの概念図

PD鮨Aの概念図

P → D →  → A

 

開発・改善することにより、鮨が手に入り、超高速でPDCAが回るという素敵な考え方です。

さっそく弊社CTOに、このアイデアで鮨をおごってもらうところ打診してみました。

 

tsuyoshi

「boss聞いてください。鮨をinsentiveにすれば、みんなもっとがんばると思うんですっ!」

CTO

「う〜ん。。。それでPDCAが本当に回るなら、いいですよ!」

(さすがCTO、(C)しーすー (T)たくさん(O)おごりたい。の略は、だてじゃなかった!)

 

鮨をおごってもらう約束を取り付けPD鮨Aを実践してみました。

結果!

 

どーーん。

上がりまくるカイゼンラベル付きのプルリク。

1日1個だった対応件数が1日2個にアップ!!(本当に忙しかったのかい?イママデ)

おそるべきPD鮨A効果!!

CTO

「すごいね!でも普通におごっても面白くないよね、ダーツで当たれば高級鮨おごります」

tsuyoshi

「what’s mean?」
私の頭の中

<?php
switch ($kaizen) {
case "ちょっと頑張った":
return 回転寿し;
case "まぁまぁ頑張った";
return ギリ回らないすし;
case "めっちゃ頑張った";
return 憧れの萬円鮨;
}
?>

確かに普通にもらうだけでは面白くありません。どうせおごってもらうなら高級鮨が食べたい!

というわけで、鮨をめぐるダーツプロジェクトが開催されることとなりました。

 

ダーツで白熱するカイゼン競争

 

ルール:

対応案件をポイントに変換。

 

1案件3pt (ただし、効果が高いものはポイントアップ)

起案した人にも1pt(実施された時点で付与)

プルリクエストをレビューすると1pt

スペシャル改善は、法外なptが。(社外秘)

 

2週間の間で、合計25pt集めた人が、ダーツと交換!

※他にも細かいルールなどがあります。

 

最終結果

 

1位 111pt y−satoshiさん

2位 27pt seijiさん

3位 26pt ryoichiさん

 

今回は特別に対応件数が過去の対応件数が多い人もダーツを付与しました。

部長が的を塗る

部長が的を塗る

これが、プロダクト開発部の部長。

ダーツの的の大きさを決めてます。

 

赤い鮨のあたりがめちゃくちゃ小さく塗られてます(涙)

 

ちなみにダーツの的は発泡スチロールで、後ろはサーキュレーターです。(かなり高速回転します)

投げます!一投入稿

投げます!一投入稿

頑張ったKazukiさん、結果はどうなるでしょうか?

 

見守る観衆

見守る観衆

wkwk

アタッタ!?

アタッタ!?

超高速で回転する的に当たった!!

結果は?!?!

 

 

鮨は赤いゾーンだ〜

鮨は赤いゾーンだ〜

 

ジーザス。

 

ハズレは、「あめ玉1つ」です。(涙)

 

外れのすしアメ

外れのすしアメ

外れた人には「すしアメ」が配られました。(涙)

次こそは絶対高級鮨をゲットしたいと思います。

(意外とすしアメも嬉しい?)

 

この辺りの盛り上がりは、人事ブログでも紹介されています。(ランサーズ人事ブログ

 

今後は月1回の恒例行事として、実施していくことが社内でも承認されました。

PD鮨Aの取り組みはまだまだこれからも続きます。

アソビュー、フューチャーアーキテクト、ランサーズ3社合同勉強会でも、対外的に「PD鮨A」について発表させていただきました。@ランサーズ渋谷会議室

合同勉強会でも対外的に発表

合同勉強会でも対外的に発表

 

まとめ

最後に、このPDCAを回すにあたって苦労したことや意識したことです。

 

・とにかくやる。

  まずはやらないと始まらない。スモールスタートが大事。

 

・やり続ける。

  続かないと誰もついてきてくれない。カイゼンプロジェクトのPDCAをまず回す。

 

・誰でも案件をあげれるようなフランクな雰囲気を作る。

  意見を言うことも、意外とパワーが必要です。敷居を下げるには日頃から声をかける。

 

・案件を「あとはやるだけ」の状態にしておく

  できるだけ具体的に、案件やアイデアを上げてもらえるように、フォーマットを整える

 

・やった結果を残して、見えるようにしておく

  結果を可視化することで、やっていることが全社に伝わり、自然と応援してくれる。

 

・周りに声をかけて、とにかく盛り上げる

  チャットワークで専用の部屋を作り、定期的にみんなの進捗を共有。

 

始めたばかりの頃は、まさかこんな風に部署や会社を巻き込んで、鮨のためにダーツまでするとは思いませんでした。3ヶ月で100個もカイゼンできたのは、みんなが頑張ったおかげですね(鮨のために)。「べっ、べつにカイゼンしたいわけじゃなくて、鮨を食べたいだけなんだからね!(プルリク上げながら)」(エンジニアってなんでみんなツンデレなんでしょう?)

今後はこのフローを基盤に「最高のユーザ満足の創造」を本質的に実現し、よりよいサービスにしていければと思いますので、引き続きよろしくお願いいたします。

 

PD鮨A、ぜひお試しあれ!

uGUIで簡単!Unityクイズアプリで社内コミュニケーションの活性化

tsuyoshi|2015年05月28日
iOS

みなさんはじめまして。2015年3月後半からジョインしました、ランサーズWEBエンジニアのTsuyoshiです。ランサーズは近頃成長フェーズなので、この数ヶ月で多くのメンバーがジョインしました。私もそのうちの一人です。ベンチャーにおける成長フェーズでは、増えた社員同士のコミュニケーションやバックグラウンドの共有などが上手くいかないのが、ベンチャーあるあるだと認識してます。

今回は、そういったあるあるが起こる前に、新メンバーと既存メンバーがシームレスにコミュニケーションを取れる場を提供するため、みんなのことを気軽に知れる社内クイズアプリをUnityで作ってみました。

できたゲームはこんな感じです。(プライバシー保護のため、コンテンツの内容は改変しております)

ゲーム画面

ゲーム画面

この記事では、Unityを使った基本的なゲームの作り方などをご紹介し、コミュニケーション不足に悩まされるベンチャー企業の方々の手助けになればと思います。

(ちなみに今回は、チャレンジドリブンなランサーズの文化を踏襲すべく、WEBアプリではなく、あえて自分も初めて使うUnityのuGUI機能に挑戦してみました)

*ソースコードはページの一番下にあります。

 

 

Unityのダウンロードとプロジェクトの作成

まずはUnityをダウンロード。(ここからのレベルです)

http://japan.unity3d.com/unity/download/

このプログでご紹介するバージョンは5.0.1です。
会員登録などを済ませて、早速起動します。(無料版)

プロジェクトを作成します。「2D」を選び「Create Project」しましょう。

CreateUnityProject

CreateUnityProject

プロジェクトが作成できたら、レイアウトを「2by3」にして、「Window」→「console」で、コンソール画面を表示すると、後々作業しやすいです。本ブログでも、そのレイアウトで進めて参ります。
画面の見方を下記の図に簡単に示します。

WindowDetail

画面の説明

 

 

スタート画面を作る

今回作成するアプリは、下記のようなシンプルな画面遷移をするアプリです。

Quizゲームフロー

Quizゲームフロー

まずは、ゲームのスタート画面から作りましょう。
スタート画面にはLancersのロゴを入れたいと思います。
まずはおもむろに、「Scene」タブのなかに、入れたい画像をドラッグ&ドロップしましょう。

Lancers_create_image

画像ファイルをUnityにドラッグ&ドロップ

JPEGの画像を入れただけで左下のゲーム画面にもロゴが表示されました。
プロジェクトを作成した際に「2D」を選択しましたが、Unityの2Dモードでは、
画像は「Sprite」という単位で扱われることを、頭のどこかに置いておいてください。

 

 

スタートボタンを設置する

次に、Unity4.6以降から実装されたuGUIを使って、スタートボタンを作ります。
「GameObject」→「UI」→「Button」を選択します。

GameObjectUIButton

UI Buttonを設置

「Hirrarchy」タブに「Canvas」→「Button」というオブジェクトが現れたかと思います。基本的にUnityのuGUIの機能では、すべてのUI要素はCanvasの子要素として扱われます。なので、ボタンを増やすと、自動的にCanvasの下に入ってきます。

また、「Button」だけでなく「EventSystem」というオブジェクトも一緒についてきますが、このEventSystemを通して、ボタンとマウスの当たり判定などが計算される仕組みです。

Sceneに対して大きすぎる UIボタン

Sceneに対して大きすぎるUI

Canvasを作成した際、上図のように最初に入れた画像よりも異常に大きいボタン(もしくは小さいボタン)がScene画面に表示される場合は、「Canvas」のInspectorから「ScreenSpace」を「Main Camera」に合わせてあげるとカメラとUIが1:1となって上手くいきます。

カメラとUIを1対1の大きさに

カメラとUIを1対1の大きさに

作成したボタンの名前は、Canvas→Button→Text から「GameStart」のような文字列に変えることができます。

 

 

ButtumNameChange

ボタンの表示テキストを変更する

 

 

ゲーム画面の遷移について

「GameStart」ボタンもできたので、早速画面を切り替えてみましょう。
現在のゲーム画面を保存し、新しいゲーム画面を追加します。
現在のゲーム画面を「File」→「Save Scene」より「Title」という名前を付けて保存します。

SaveUnityScene

画面をSceneとして保存する

保存できたら「File」→「New Scene」より、新しいSceneを作成します。

すると、まっさらなゲーム画面ができるので、一旦これも保存しましょう。

ゲームスタート後に遷移する画面を想定しているので、クイズアプリらしく、出題画面にしたいので、「File」→「Save Scene」より「Quiz」という名前で保存してください。

すると、Unityのマークがついた「Title」「Quiz」というファイルができます。

SaveSceneFilese

シーンファイルの作成

この「Title」や、「Quiz」をダブルクリックしてあげると、それぞれのシーンを編集していくことができます。一旦「Title」→「Quiz」の遷移を作成するため、

「File」→「Build Settings」を開いて、「Title」と「Quiz」をドラッグ&ドロップして追加してください。この作業を行うことで、シーンからシーンの移動が可能になります。

QuizStartBuildSetting

BuildSettingsへのシーン追加

※これだけでは遷移しないので、次はボタンがクリックされたら遷移するロジックを書きます。

 

uGUIでの画面遷移:onClickイベント

「GameStart」をクリックすると「Quiz」画面に遷移するロジックを作りたいと思います。ロジックの作成は、スクリプトを書くことで実現できます。

「Assets」→「Create」→「C# Script」でファイル名を「GameStart」にします。

AddScriptOnClick

C#スクリプトを追加

作成したスクリプトに以下のコードを書きます。

using UnityEngine;
using System.Collections;

public class GameStart : MonoBehaviour {

    public void  NextScene(){
        //今いるシーンがTitleという名前であれば、Quizという名前のシーンに移動する
        if (Application.loadedLevelName == "Title") {
            Application.LoadLevel ("Quiz");
        }
    }
}

Application.loadedLevelNameというのが、現在のScene名に対応しているので、Titile画面であれば、Quiz画面に遷移するという単純なロジックです。

ロジックができたら、ボタンにスクリプトをアタッチしましょう。

ここからようやくuGUIの登場です。

スクリプトをボタンに設置

スクリプトをボタンに設置

次に、Canvas→Buttonの、On Click()イベントに、ボタンをリックした時に起こる動作を指定します。

  1. Canvas→Button 「On Click」「+」ボタンでイベントを追加。
  2. Buttonのゲームオブジェクト自身をドラッグ&ドロップで割り当てる。
  3. Click時に実行する関数を、先ほど作ったメソッド「NextScene」に設定。
CallScriptOnclick

クリックイベントの設定

ここまで出来ると、Title画面からQuiz画面へ遷移することができます。

実行画面で確認してみましょう。

無事遷移できましたか?Xcodeのストーリーボードや、AndroidStudioではこの辺りの処理は一瞬でできそうですが、Unityをつかってアプリの画面遷移を作るとこんな感じになるかと思います。

Unity自体が、こういったアプリを作ることに向いていないのもあるかもしれませんが、逆にUnityなら面倒なことをすれば、こんなこともできちゃう。とポジティブに捉えましょう。

 

 

クイズ画面の作成

スタート画面から遷移できたので、次は、実際のクイズ問題画面を作っていきます。

今回は、画像のお題に対して4択で答えるシンプルなアプリにするので

  • 画像
  • 問題文
  • 回答1、回答2、回答3、回答4

を画面に配置していきたいと思います。早速作っていきたいところですが、Quizのシーンを開くと、先ほどと同じように、Canvasを置いて〜、とやる必要があるので、同じ設定を何度もするのは面倒です。同じ機能を実装する際はPrefab機能を使います。

 

Prefab化して、同じ画面を呼び出すオブジェクトを作る。

UnityにはPrefabという機能があり、同じ効果を持つオブジェクトを簡単に複製できます。今回は、Canvasを映しているMainCameraをPrefab化して、シーンが移動しても、同じ画面をすぐに作れるようにしましょう。

Hierarchy タブにて、MainCameraの中にCanvasオブジェクトをドラッグ&ドロップ。

MainCameraObjectをProjectタブのAssetsにドラッグ&ドロップ。

ゲームオブジェクトのプレハブ化

ゲームオブジェクトのプレハブ化

すると、図のような青いキューブができます。

これがPrefabです。シーンを切り替えても、リソースとしてフォルダに残っているので、各シーンで扱えます。(ドラッグ&ドロップでHierarchyタブに持っていく)

では、Quiz画面に行って、Prefabを使ってみましょう。

新しいシーンにはデフォルトでMainCameraがあるので、一旦削除します。

先ほど作った、PrefabをProjectタブからHierarchyタブにドラッグ&ドロップします。(デフォルトのMainCameraを削除しておくことを忘れないでください。また、prefabをコピーして作るとEventSystemが作成されないので、EventSystemも「GameObject」→「UI」→「EvetntSystem」から生成しておきましょう)

Prefabload

プレハブをSceneに追加する

 

 

UIを配置する

今までやってきたことを組み合わせて、「画像」「ボタン」「 テキスト」を配置します。

  • 画像は任意の画像をドラッグ&ドロップ
  • ボタンは GameObject→UI→Buttonから
  • テキストも GameObject→UI→Text

またCanvasの名前を「Quiz」に、「Button」の名前を「AnsButton」に書き換え、それぞれの要素に固有の名前をつけてあげましょう。そうすることでスクリプトから固有の名前の要素にアクセスできます。

変更した各オブジェクトの名前

変更した各オブジェクトの名前

 

 

問題文と回答文を挿入

問題文と、回答選択ボタンができました。実際に問題文などを読み込ませましょう。問題文や回答文は動的に変化させたいので、オブジェクトのテキストにスクリプトからアクセスして変化させてみます。

新しくAssets→Create→C#Scriptから、「QuizMgr」というスクリプトを作成します。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;//UI オブジェクトを扱う時は必須
public class QuizMgr : MonoBehaviour {

     //アタッチしたオブジェクトが呼ばれた時に実行される。
    void Start () {
        QuestionLabelSet ();
    }

    private void QuestionLabelSet(){
        //特定の名前のオブジェクトを検索してアクセス
        Text qLabel = GameObject.Find("Quiz/QLabel").GetComponentInChildren<Text> ();
        //データをセットすることで、既存情報を上書きできる
        qLabel.text = "ランサーズ君は何歳?";
    }
}

Findを使えば、UI部品につけた名前をキーに検索して、GameObjectにアクセスできます。上記場合「Quiz配下にあるQLabelの中にあるTEXT」の情報を取得するという意味です。

スクリプトができたら、MainCamera、もしくは空のオブジェクトを作って、そこにアタッチします。(シーンを開いた時に常にあるオブジェクトに適応)

ScriptAttach

スクリプトをオブジェクトにアタッチ

アタッチできたら実行してみましょう。

 

QLabelの文字が変化します。

LabelChange

テキストの変更

同様に、回答(AnsButton)のラベルも変更しましょう

 

QuizMgrを以下のように書き換えます。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;//UI オブジェクトを扱う時は必須
public class QuizMgr : MonoBehaviour {

    //アタッチしたオブジェクトが呼ばれた時に実行される。
    void Start () {
        QuestionLabelSet ();
        AnswerLabelSet ();
    }

    private void QuestionLabelSet(){
        //特定の名前のオブジェクトを検索してアクセス
        Text qLabel = GameObject.Find("Quiz/QLabel").GetComponentInChildren<Text> ();
        //データをセットすることで、既存情報を上書きできる
        qLabel.text = "ランサーズ君は何歳?";
    }

    private void  AnswerLabelSet(){
        //回答文面の作成
        string[] array = new string[]{"10歳","6歳","青二才","7歳"};
        //ボタンが4つあるのでそれぞれ代入
        for (int i=1; i<=4 ; i++){
            Text ansLabel = GameObject.Find("Quiz/AnsButton" + i).GetComponentInChildren<Text> ();
            ansLabel.text = array[i-1];
        }
    }

}
問題と解答テキストの挿入

問題と解答テキストの挿入

実行すると上記のような画面が表示されるかと思います。
クイズっぽくなってきましたね。
※データベースの扱いなどは、今回は説明しません。
次は、回答をクリックした時のイベントを作ります。

 

正誤判別をする

ユーザーが選択した選択肢の正誤を判別する処理を作ります。
新しく「Judgde」というスクリプトを書いてそれぞれのボタンに割り当てます。ボタンへの割り当ては「GameStart」ボタンのときに説明したuGUIを使いましょう。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class Judge : MonoBehaviour {

    //選択したボタンのテキストラベルと正解のテキストを比較して正誤を判定
    public void JudgeAnswer(){
        //正解のデータをテキストでセットする
        string answerText = "7歳";
        //選択したボタンのテキストラベルを取得する
        Text selectedBtn = this.GetComponentInChildren<Text> ();

        if (selectedBtn.text == "7歳") {
            Debug.Log("正解");
        } else {
            Debug.Log("不正解");
        }
    }
}

ボタンが押されたら、押された値によって、コンソール画面に、文字列を表示する単純なスクリプトです。

「Window」→「Console」でコンソール画面を開いた状態で、実行してみましょう。

ボタンをクリックするとConsole画面に、選択結果が反映されるかと思います。
*ボタンをクリックしても何も出ない場合は
・「EventSystem」オブジェクトがあるか?
なければ、「GameObject」→「UI」→「EventSystem」で作成
・スクリプトがきちんと割り当てられているか?
などを確認してみてください。

ChoiceAnswer

解答を選ぶ

 

 

 正誤判定画面へ遷移させる

クイズゲームなので、正解の回答を選択したら「正解!」誤った回答を選択したら「不正解!」と、表示させる画面を作ります。

「File」→「New Scene」で新しい画面を作ります。

シーンの名前は「Result」などの名前で保存してください。

Quizのシーンと同様に、カメラオブジェクトなどを設置します。今回は「◯」の画像を用意し、Imageとして配置しました。

JudgeImage

正誤画面

Quiz画面からこのResultシーンに移動するので、

「File」→「BuildSetting」から、新しく作った「Result」ファイルを追加します。

Judgeのスクリプトを編集し、Quizシーンの回答ボタンが押されたら、Resultシーンへ移動するようにします。

        if (selectedBtn.text == "7歳") {
            Debug.Log("正解");
            Application.LoadLevel ("Result");
        } else {
            Debug.Log("不正解");
            Application.LoadLevel ("Result");
        }

Quizシーンに戻って実行し、回答を選択すると、先ほど作った画面に移動できるかと思います。

ただ、今のままだと、不正解を押しても、「◯」が表示されるので、

正誤によって表示を切り替えてみます。

 

スクリプト間でのデータの受け渡し

状態によって表示を切り替えるために、スクリプト間でデータの受け渡しを行います。

データの受け渡し方法は色々ありますが、今回はグローバル変数を関数からセットする方法を用います。

Resultシーンにて 「Assets」→「Create」→「C#Script」で「ResultMgr」というスクリプトを作成します。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class ResultMgr : MonoBehaviour {
    //他のスクリプトからも参照可能な変数宣言
    public static string g_judgeData;

    void Start () {
        Debug.Log (g_judgeData);
    }

    //他のスクリプトからも参照可能な関数宣言
    public static  void SetJudgeData(string judgeData){
        g_judgeData = judgeData;
    }
}

public staticという宣言で、他のスクリプトからも関数などが読み込めるようになります。上記ではg_JudgeDataというグローバルな変数に値をセットするため、SetJudgeDataという他のスクリプトからも読み込める関数を用意しました。

回答選択 → 正誤判定 → 正誤データ受け渡し

としたいので、「Judge」スクリプトから、SetJudgeDataを呼び出し、g_JudgeDataに正誤データを受け渡してみます。

        if (selectedBtn.text == "7歳") {
            //選択したデータをグローバル変数に保存
            ResultMgr.SetJudgeData ("正解");
            Application.LoadLevel ("Result");
        } else {
            //選択したデータをグローバル変数に保存
            ResultMgr.SetJudgeData ("不正解");
            Application.LoadLevel ("Result");
        }

ResultMgr.SetJudgeData(string)という記述で、グローバル関数を呼び出し、値を引き渡せます。Quizシーンから遷移させてみます。

RunResult

実行結果

 

 

状態によって表示を切り替える

正解、不正解の正誤情報を送れるようになったので、表示を切り替えてみたいと思います。

まずは、切り替える画像を用意します。(マルの画像と、バツの画像)

画像の置き場は、Assetsフォルダの下に、新規で「Resources」フォルダを作り、そこに配置します。すでに配置してるマルの画像も、こちらに移しておきます。

Unityでは、Resourcesのように、Assetsフォルダの下につけるフォルダの名前が決まっているものがあります。(本来はScriptsやScenesなどのフォルダにまとめるのがルールです。※今回は動作第一優先)

Resourcesフォルダに置いたオブジェクトなどはResources.Load<T>()でスクリプトから呼び出すことができます。

なので、画像はResourcesフォルダ配下に保存します。

ImageAtResouces

Resourcesフォルダ配下に保存

ResultMgrのスクリプトのStart関数を以下のように書き換えます

    void Start () {
        //現在描画している画像を取得
        SpriteRenderer judgeImage = GameObject.Find("JudgeUI/JudgeImage").GetComponent<SpriteRenderer>();
        //Resourcesから指定した名前の画像データをロード
        Sprite loadingImage = Resources.Load<Sprite>("batsu");
        //画像を置換
        judgeImage.sprite = loadingImage;
    }

最初に置いてあった画像を取得し、新しい画像に書き換えます。
スクリプトを実行すると、以下のように、◯だった画像が×に変わります。
うまく切り替わらない場合は
・型を確認する。
Sprite、Image、SpriteRendererのようなGameObjectの型があるので注意。
・GameObject.Find()の中身が正しいか確認する
Hierarchy画面の文字列と合致している必要があります。

ExecuteGame

画像をスクリプトから切り替える

これで表示の切り替えができたので、選択した回答によって表示を切り替えたいと思います。
ResultMgrのStart関数をを以下のように書き換えます。

    //他のスクリプトからも参照可能な変数宣言
    public static string g_judgeData;

    void Start () {
        //デフォルトは正解、不正解なら画像と文言を切り替える
        if (g_judgeData == "不正解") {
            //現在描画している画像を取得
            SpriteRenderer judgeImage = GameObject.Find ("JudgeUI/JudgeImage").GetComponent<SpriteRenderer> ();
            //Resourcesから指定した名前の画像データをロード
            Sprite loadingImage = Resources.Load<Sprite> ("batsu");
            //画像を置換
            judgeImage.sprite = loadingImage;
            //表示テキストを取得して置換
            Text judgeLabel =  GameObject.Find("JudgeUI/JudgeLabel").GetComponent<Text>();
            judgeLabel.text = "不正解";
        }
    }

デフォルトの状態は正解とし、不正解の選択をした場合のみ、画像を切り替えます。
Quiz画面でゲームを実行すると、回答によって、表示が切り替わったかと思います。
あとは、Nextボタンに次の問題へいくロジックを書いてみます。画面遷移機能を持っているGameStart関数を書き換えて、ResultシーンならばQuizシーンに移動するように、スクリプトを書き加えます。

using UnityEngine;
using System.Collections;

public class GameStart : MonoBehaviour {

    public void  NextScene(){

        if (Application.loadedLevelName == "Title") {
            Application.LoadLevel ("Quiz");
        }
    }

    public void NextQuiz(){

        if (Application.loadedLevelName == "Result") {
            Application.LoadLevel ("Quiz");
        }
    }
}

スクリプトが書けたら、uGUIの機能を使って、GameStartスクリプトをNextボタンに付け加えて、ボタンイベントを登録しましょう。

NextScene

次のシーンへ移動させるスクリプトをアタッチ

これで、QuizシーンとResultシーンを行き来できるようになりました。

移動できない場合は、

  • Build Settingsに指定したシーンが登録されているか
  • UIのEventSystemがHierarchyにあるか
  • Buttonにスクリプトがコンポーネントとして入っているか

などを確認してみてください。

 

よりゲームらしくする

最後に、よりゲームらしくするために、得点機能をつけて、スコアを表示してみましょう。

ResultMgrのスクリプトに、正解だった場合、得点を加えるスクリプトを追記します。

    public static int g_scoreData;

        if (g_judgeData == "不正解") {
//..処理
} else if (g_judgeData == "正解") {
            //正解であればScoreを足す
            g_scoreData++;
        }
    //グローバルに宣言したスコアを他のスクリプトから読み込む
    public static int GetScoreData(){
        return g_scoreData;
    }
    //グローバルに宣言したスコアを他のスクリプトから書き込む
    public static int SetScoreData(int scoreData){
        g_scoreData = scoreData;
        return g_scoreData;
    }

<i>//グローバルに宣言したスコアを他のスクリプトから読み込む</i>

public static int GetScoreData(){

return g_scoreData;

}

これにより、g_scoreDataという変数に得点が蓄えられます。
スコアを最終的に表示するために、「File」→「NewScene」より、新しく「Score」というシーンを作成し、保存します。
保存したら、Build Settingに登録し、他のシーンから画面遷移できるようにしましょう。

ScoreScene

スコアSceneの作成

Scoreというスクリプトを書いてMainCameraにアタッチします。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class Score : MonoBehaviour {

    // Use this for initialization
    void Start () {
        //スコア表示用のゲームオブジェクトを取得
        Text scoreLabel = GameObject.Find("Canvas/Score").GetComponent<Text>();
        scoreLabel.color = Color.red;
        //グローバルに宣言したスコアをResultMgrのスクリプトから読み込む
        int Score = ResultMgr.GetScoreData ();
        scoreLabel.text = Score.ToString() + " 点" ;
    }
}

実行すると、指定したゲームオブジェクトが動的に変わるようになります。

ExecuteScoreScene

スコアSceneの実行結果

最後にGameStartスクリプトにて、3回問題を繰り返したら、Score画面に遷移するように、変更します。

public static int qCount;

public void NextQuiz(){

        if (Application.loadedLevelName == "Result") {

            if(qCount < 2){
                qCount++;
                Application.LoadLevel ("Quiz");
            }else{
                qCount = 0;
                Application.LoadLevel ("Score");
            }
        }
    }

    public void  BackToTitle(){

        if (Application.loadedLevelName == "Score") {
            ResultMgr.SetScoreData(0);
            Application.LoadLevel ("Title");
        }
    }

これで一通り、ゲームの完成です。

実際に動かしてみましょう。

ゲーム画面

ゲーム画面

*今回は説明するために流れをわかりやすくして書くことを心がけたため、変数の初期化場所などがスマートではありませんが、一通り作った後に、いろいろ試して書き換えていただければ幸いです。また、クイズの問題を変更するデータベースなどの作り方は、長くなりそうなので、またの機会にご説明できればと思います。

 

実際に会社のメンバーに使ってもらう

*実際に使ってもらったものは、社員のメンバーそれぞれの名前のクイズや、趣味などを問題として登録したものを使ってもらいました。

Aさん「面白いです。」
Mさん「なにこれすごーい。問題が面白い!」
Tさん「コンテンツ大事ですね。みんなで問題を編集したり追加できるようにしたい」
Hさん「だったらUnityじゃなくて、WEBアプリで良いのではないでしょうか?」

・・・・・

 

今後の課題

まだまだ、実装途中なので、コミュニケーションに関する結果はまだ出ていませんが、

・クイズの問題を社内メンバーで自由に作れるような機能を実装し、よりコミュニケーションの円滑化を図る。
・Unity以外にもWEBアプリで実装してみる。

などを視野に入れて、今後も取り組んでいきたいと思います。

 

まとめ

  • uGUIでぽちぽちしながらクイズゲームを作れる。
  • 画面遷移が少しとっつきにくい、慣れればいろんなパターンのゲームを作成可能
  • 冷静に社内コミュニケーションを活性化させるなら、WEBアプリでOK
  • 問題文や画像のコンテンツがとにかく大事

今回作成したファイルはこちらにアップロードしてあります。
ランサーズクイズアプリ

もしこの記事のはてぶ100ぐらい行ったら、データベース的な説明や、オンライン上でメンバーが問題を編集できる機能のつけ方を説明する新しい記事書きます。

これからも挑戦は続きます。

ランサーズでは、こういった楽しい開発を一緒にしてくださる、素直でポジティブなエンジニアを募集しております。ぜひ一緒に開発したいと思った方は、以下のページよりお気軽にお声がけください。