しがないエンジニアのブログ 技術的な内容をメモ代わりにつらつら 2019-10-07T01:50:14+09:00 turgure Hatena::Blog hatenablog://blog/6653812171406460875 [Unite2019] 「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック hatenablog://entry/26006613445729012 2019-10-07T01:50:14+09:00 2019-10-07T01:50:14+09:00 動画・スライド:https://learning.unity3d.jp/3345/ 平井 佑樹 KLab株式会社 稲田 真吾 KLab株式会社 西那 康志 KLab株式会社 学んだ知見 100人同時接続を実現するために オブジェクトの再利用(newを抑える) 同期ずれ 重複した通知は最後の値のみ適用 アセットバンドルロード ロードの優先度 UI > ミッションに関連するもの > カメラに近いプレイヤー アセットダウンロード 並列化, Rangeリクエスト データ量が増えてもがロード長くならない 講演概要 通信基盤の紹介 RPCクライアント(Remote Procedure Call) [クライ… <p>動画・スライド:<a href="https://learning.unity3d.jp/3345/">https://learning.unity3d.jp/3345/</a></p> <p>平井 佑樹 KLab株式会社<br/> 稲田 真吾 KLab株式会社<br/> 西那 康志 KLab株式会社</p> <hr /> <h2>学んだ知見</h2> <ul> <li>100人同時接続を実現するために <ul> <li>オブジェクトの再利用(newを抑える)</li> </ul> </li> <li>同期ずれ <ul> <li>重複した通知は最後の値のみ適用</li> </ul> </li> <li>アセットバンドルロード <ul> <li>ロードの優先度 <ul> <li>UI > ミッションに関連するもの > カメラに近いプレイヤー</li> </ul> </li> </ul> </li> <li>アセットダウンロード <ul> <li>並列化, Rangeリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト <ul> <li>データ量が増えてもがロード長くならない</li> </ul> </li> </ul> </li> </ul> <hr /> <h2>講演概要</h2> <h3>通信基盤の紹介</h3> <p>RPCクライアント(Remote Procedure Call)</p> <ul> <li>[クライアント]<a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a> メソッド実行 &lt;-> goの関数実行[サーバ]</li> </ul> <p>受信処理のチューニング</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GC">GC</a> allocを最小限にしたい <ul> <li>遅延&amp;上書きデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a></li> </ul> </li> </ul> <p><img src="https://image.slidesharecdn.com/magatsu-190930095346/95/unite-tokyo-2019100-29-638.jpg?cb=1569837333" width="600"></p> <h3>リアルタイムバトル実装</h3> <p>課題</p> <ul> <li>スペックの差により、サーバから送られてくる通知をさばける量が違う</li> </ul> <p>原因</p> <ul> <li>通知処理に1フレーム以上の時間がかかる <ul> <li>エフェクト周りが重い</li> </ul> </li> </ul> <p><img src="https://image.slidesharecdn.com/magatsu-190930095346/95/unite-tokyo-2019100-61-638.jpg?cb=1569837333" width="600"></p> <p>対策</p> <ul> <li>不要な通知を無視する <ul> <li>サーバからの通知は上書き更新</li> <li>実行時刻が過去のものを無視</li> </ul> </li> </ul> <h3>アセットロードの負荷軽減</h3> <p>課題</p> <ul> <li>プリロードできない</li> <li>操作中のロード負荷</li> </ul> <p>対策</p> <ul> <li>priorityによるロード順の制御 <ul> <li>UI、プレイヤー、敵の優先度</li> </ul> </li> <li>操作中のロード不可の軽減 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/FPS">FPS</a>に応じて並列ロード数を動的</li> </ul> </li> <li>instantiateの高速化 <ul> <li>キャッシュ</li> </ul> </li> </ul> <p><img src="https://image.slidesharecdn.com/magatsu-190930095346/95/unite-tokyo-2019100-73-638.jpg?cb=1569837333" width="600"></p> <h3>アセットダウンロードの高速化</h3> <p>課題1</p> <ul> <li>進行に応じで都度DLができない <ul> <li>プレイヤーが何を装備しているかわからない</li> </ul> </li> </ul> <p>対策1</p> <ul> <li>メインスレッドを使わない(<code>WWW</code> / <code>UnityWebRequest</code>を使わない) <ul> <li>メインスレッド非依存のHTTPライブラリ <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>: <code>NSURLSession</code></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>: <code>OkHttp</code></li> </ul> </li> </ul> </li> <li>コネクション数を増やす</li> </ul> <p>課題2</p> <ul> <li>まだファイル数に依存して時間がかかる</li> </ul> <p>対策2</p> <ul> <li>まとめてDLして受信後に展開 <ul> <li>Rangeリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト</li> </ul> </li> </ul> <p><img src="https://image.slidesharecdn.com/magatsu-190930095346/95/unite-tokyo-2019100-95-638.jpg?cb=1569837333" width="600"></p> <hr /> <h2>所感</h2> <ul> <li>随時DLが使えない場合の対策としてとてもよくまとまっている内容だと思った <ul> <li>SINoALICEとの比較</li> </ul> </li> <li>HTTP/2を実装できない場合、こちらの対処法を使うことができればある程度緩和できそう</li> </ul> turgure [Unite2019] Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~ hatenablog://entry/26006613445728805 2019-10-07T01:48:44+09:00 2019-10-07T01:48:44+09:00 動画・スライド:https://learning.unity3d.jp/3341/ 小端 みより 株式会社ミクシィ 学んだ知見 Unityサーバを利用することで、 クライアントエンジニアでもサーバ構築が可能 c#で実装できる Unity機能が使える(Animation, Physics, AIなど) プロファイラが使える!! 単一プロジェクトで管理 サーバ処理型で実装できる チート耐性が高い 通信が安定する クライアントの処理負荷を軽減できる 講演概要 Unityサーバを作にあたって これまでのマルチプレイ実装 P2P型(クライアント処理型) メリット ミドルウェアやサービスが豊富 手軽 デメ… <p>動画・スライド:<a href="https://learning.unity3d.jp/3341/">https://learning.unity3d.jp/3341/</a></p> <p>小端 みより 株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%AF%A5%B7%A5%A3">ミクシィ</a></p> <hr /> <h2>学んだ知見</h2> <p>Unityサーバを利用することで、<br/> クライアントエンジニアでもサーバ構築が可能</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a>で実装できる</li> <li>Unity機能が使える(Animation, Physics, AIなど) <ul> <li>プロファイラが使える!!</li> </ul> </li> <li>単一プロジェクトで管理</li> </ul> <p>サーバ処理型で実装できる</p> <ul> <li>チート耐性が高い</li> <li>通信が安定する</li> <li>クライアントの処理負荷を軽減できる</li> </ul> <hr /> <h2>講演概要</h2> <p>Unityサーバを作にあたって</p> <p>これまでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4">マルチプレイ</a>実装<br/> <strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/P2P">P2P</a>型(クライアント処理型)</strong></p> <ul> <li>メリット <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DF%A5%C9%A5%EB%A5%A6%A5%A7%A5%A2">ミドルウェア</a>やサービスが豊富</li> <li>手軽</li> </ul> </li> <li>デメリット <ul> <li>チートされやすい</li> <li>通信が不安定になりやすい</li> <li>大規模タイトルに向かない</li> </ul> </li> </ul> <p>→ サーバ処理型にすればいいのでは?</p> <p>Unityサーバとは</p> <ul> <li>Unityで作る専用サーバ</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a>で実装できる</li> <li>Unity機能が使える(Animation, Physics, AIなど)</li> <li>クライアント、サーバ両方を単一プロジェクトで管理</li> </ul> <p>作成するゲームの概要</p> <ul> <li>アクション性の高いオンライン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4">マルチプレイ</a>ゲーム</li> <li>サーバ・クライアントを単一Unityプロジェクトで作成</li> <li>サーバを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>上で動作、20人以上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4">マルチプレイ</a></li> </ul> <h3>7つの課題と解決法</h3> <h4>1. どの通信ライブラリを使えばいい?</h4> <ul> <li>公式 <ul> <li>Unity Transport Package</li> <li>DOTS</li> </ul> </li> <li>非公式 <ul> <li>LiteNetLib</li> </ul> </li> </ul> <p>ゲーム設計によってどういう実装をすればいいかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%ED%A1%BC%A5%C1%A5%E3%A1%BC%A5%C8">フローチャート</a>も参考に<br/> <a href="https://blogs.unity3d.com/2019/06/13/navigating-unitys-multiplayer-netcode-transition/">https://blogs.unity3d.com/2019/06/13/navigating-unitys-multiplayer-netcode-transition/</a></p> <p>結論:<br/> LiteNetLibを採用<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>実装がある程度かたまっている</p> <h4>2. <a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a>どっちを使う?</h4> <p>初めて使うなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a></p> <ul> <li>ポピュラーで情報が多い</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>として信頼性が高い</li> </ul> <p>しかし、リアルタイム性という点において<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>の再送制御は致命的</p> <p>結論:<a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a>を採用</p> <h4>3. 再送制御による遅延を回避するには?</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a>を使う<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a>で信頼性を得るには…</p> <p>送信メッセージを<strong><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BE%E9%C4%B9%B2%BD">冗長化</a></strong><br/> <img src="https://image.slidesharecdn.com/09261630roomdmiyorikobata-190926082209/95/unite-tokyo-2019unity-36-638.jpg?cb=1569486693" width="600"></p> <p>結論:<a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a> + <a class="keyword" href="http://d.hatena.ne.jp/keyword/%BE%E9%C4%B9%B2%BD">冗長化</a>で対応</p> <h4>4. MTUって何?</h4> <p>Maximum Transmission Unit</p> <ul> <li>1回の通信で転送可能なデータグラムの上限サイズ</li> <li>超過した場合は分割される or そもそも到達しない</li> </ul> <p>対処法</p> <ul> <li>メッセージサイズを削減する <ul> <li>プレイヤー視界外のオブジェクトをカリング</li> <li>オブジェクトの距離、優先度に応じて通信タイミングを分散させる</li> <li>データを圧縮</li> </ul> </li> <li>デルタ圧縮 <ul> <li>送信内容をキャッシュする</li> <li>更新されたオブジェクト、プロパティのみを送信</li> </ul> </li> </ul> <p>結論:上記のテクニックでメッセージサイズを削減</p> <h4>5. ラグはなくせるのか?</h4> <p>一般的にラグ = 通信遅延と思われているが非常に小さい(1, 2ms)<br/> 実際は再送制御の遅延、通信サイクルに起因するもののほうが大きい</p> <p>入力のアップデートのタイミングが悪いと必ず起こる宿命<br/> → 体感上のラグを打ち消す</p> <p>例)<br/> <img src="https://image.slidesharecdn.com/09261630roomdmiyorikobata-190926082209/95/unite-tokyo-2019unity-52-638.jpg?cb=1569486693" width="600"></p> <p>結論:<br/> オンラインゲームにおいてラグは宿命<br/> 体感上のラグを減らす工夫をする</p> <h4>6. サーバとクライアントで同一プロジェクト管理できる?</h4> <p>ビルド設定で使用するアセットを切り替えればよい<br/> クライアント・サーバのどちらで必要なアセットかを区別する<br/> <img src="https://image.slidesharecdn.com/09261630roomdmiyorikobata-190926082209/95/unite-tokyo-2019unity-57-638.jpg?cb=1569486693" width="600"></p> <p>結論:<br/> シーン/アセットをどちらで使うかビルド時に判別・切り替え<br/> → AssemblyDefinitionを利用</p> <h4>7. 専用サーバをどうやって運用したらいい?</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>サービスの利用</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>の<code>GameLift</code></li> <li>Azure, Unity公式の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>サービスも開始されていくはず</li> </ul> <p>結論:GameLiftを採用</p> <hr /> <h2>所感</h2> <ul> <li>Unityでサーバ構築をできることを知らなかったのでとても参考になった</li> <li>結局サーバ構成を考える部分が生じるのでサーバエンジニアは必要そう</li> <li>1日目の講演であったGame Server Services(GS2)と両立できるのかが気になった</li> </ul> turgure [Unite2019] 大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~ hatenablog://entry/26006613445728487 2019-10-07T01:46:35+09:00 2019-10-07T01:46:35+09:00 動画・スライド:https://learning.unity3d.jp/3330/ 竹原 涼 株式会社セガゲームス 山田 英伸 株式会社セガゲームス 学んだ知見 結論:HTTP/2でのダウンロードがおすすめ 講演概要 HTTP/2特徴 stream多重化(TCP) HTTP/1.1は6コネクションくらい HTTP/2は100以上が推奨 レスポンスを待たずに通信が可能 ウィンドウサイズ制御(TCPのウィンドウサイズではない) 受信バッファあふれを防ぐ ヘッダ圧縮 HPACKフォーマット(ヘッダサイズが減る) バイナリフレーム 通信データがテキストデータからバイナリに ダウンロード特性の解説 HT… <p>動画・スライド:<a href="https://learning.unity3d.jp/3330/">https://learning.unity3d.jp/3330/</a></p> <p>竹原 涼 株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%AC%A5%B2%A1%BC%A5%E0%A5%B9">セガゲームス</a><br/> 山田 英伸 株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%AC%A5%B2%A1%BC%A5%E0%A5%B9">セガゲームス</a></p> <hr /> <h2>学んだ知見</h2> <p>結論:HTTP/2でのダウンロードがおすすめ<br/> <img src="https://image.slidesharecdn.com/09261530roomcryotakehara-190926073154/95/unite-tokyo-2019http2-5-638.jpg?cb=1569483368" width="600"></p> <hr /> <h2>講演概要</h2> <h3>HTTP/2特徴</h3> <ul> <li>stream多重化(<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>) <ul> <li>HTTP/1.1は6コネクションくらい</li> <li>HTTP/2は100以上が推奨 <ul> <li>レスポンスを待たずに通信が可能</li> </ul> </li> </ul> </li> <li>ウィンドウサイズ制御(<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>のウィンドウサイズではない) <ul> <li>受信バッファあふれを防ぐ</li> </ul> </li> <li>ヘッダ圧縮 <ul> <li>HPACKフォーマット(ヘッダサイズが減る)</li> </ul> </li> <li>バイナリフレーム <ul> <li>通信データがテキストデータからバイナリに</li> </ul> </li> </ul> <h3>ダウンロード特性の解説</h3> <p>HTTP/1.1では帯域を使い切れない</p> <ul> <li>小さいファイルの転送では帯域が余る</li> <li>HoLBの仕様</li> </ul> <p><img src="https://image.slidesharecdn.com/09261530roomcryotakehara-190926073154/95/unite-tokyo-2019http2-26-638.jpg?cb=1569483368" width="600"></p> <p>帯域を無駄にしないHTTP/2</p> <ul> <li>転送が終了したらすぐ別のストリームが開始される</li> <li>ストリームが複数動いたら帯域を分配する</li> <li>HoLB解消 <ul> <li>リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送りながらレスポンスを受け取れる</li> </ul> </li> </ul> <p><img src="https://image.slidesharecdn.com/09261530roomcryotakehara-190926073154/95/unite-tokyo-2019http2-29-638.jpg?cb=1569483368" width="600"></p> <p>HTTP/2の弱点</p> <ul> <li>下層が<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>のためパケット欠損でHoLBが発生しうる</li> </ul> <p>HoLBはHTTP/3で解決?<br/> まだドラフトの状態</p> <h3>HTTP/2通信の実装の注意点</h3> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a>ではHTTP/2を使えるモジュールが存在しない</li> <li>objective c / <a class="keyword" href="http://d.hatena.ne.jp/keyword/java">java</a>を利用するとこで<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>の対応は可能 <ul> <li>ただし<a class="keyword" href="http://d.hatena.ne.jp/keyword/windows">windows</a>の対応ができない</li> </ul> </li> </ul> <p>そのため登壇者は<a class="keyword" href="http://d.hatena.ne.jp/keyword/c/c%2B%2B">c/c++</a>で実装した</p> <p>2019/8現在も<a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a>で利用できるモジュールは存在してない</p> <hr /> <h2>所感</h2> <ul> <li>アセットバンドルのDLを高速化したい場合はこの方法が良いとおもいました</li> <li>ただし開発<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%A9%BF%F4">工数</a>がそれなりに掛かりそうなので要注意</li> <li>今後HTTP/2対応が進んだ場合は優先的に対応を進める価値はありそう</li> </ul> turgure [Unite2019] 『SINoALICE -シノアリス- 』〜 それは最速のゲーム起動 〜 hatenablog://entry/26006613445727837 2019-10-07T01:42:26+09:00 2019-10-07T01:44:23+09:00 動画・スライド:なし 中原 雄一 株式会社ポケラボ 学んだ知見 ゲーム開始時のロードが重い(データ量が多い、数が多い)場合は、 必要な場面で随時ダウンロードするようにするとよい 起動の高速化 開発のサイクル高速化 API通信料金の削減 UXを工夫することで体感時間を削減できる効果が見込める 講演概要 開発環境 Unity 2018.4.2f1 middle ware Spine(2D animation) SPARK gear(3D effect) CRIWARE 対策前、対策後の紹介 起動時間:2分→5秒に短縮 ゲーム起動シーケンス紹介 ログイン処理 ユーザーデータのDL マスターのDL マ… <p>動画・スライド:なし</p> <p>中原 雄一 株式会社ポケラボ</p> <hr /> <h2>学んだ知見</h2> <ul> <li>ゲーム開始時のロードが重い(データ量が多い、数が多い)場合は、<br/> 必要な場面で随時ダウンロードするようにするとよい <ul> <li>起動の高速化</li> <li>開発のサイクル高速化</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>通信料金の削減</li> </ul> </li> <li>UXを工夫することで体感時間を削減できる効果が見込める</li> </ul> <hr /> <h2>講演概要</h2> <p>開発環境</p> <ul> <li>Unity 2018.4.2f1</li> <li>middle ware <ul> <li>Spine(2D animation)</li> <li>SPARK gear(3D effect)</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CRIWARE">CRIWARE</a></li> </ul> </li> </ul> <h3>対策前、対策後の紹介</h3> <p>起動時間:2分→5秒に短縮</p> <h3>ゲーム起動シーケンス紹介</h3> <ul> <li>ログイン処理</li> <li>ユーザーデータのDL</li> <li>マスターのDL <ul> <li>マスタごとに<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を実行(80種類)</li> <li>ローカルに保存(<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQLite">SQLite</a>)</li> </ul> </li> <li>AssetBundleのチェック&DL <ul> <li>アイコン、キャラSpine、敵Spine、バトルエフェクト、バトル背景、バナー、その他</li> </ul> </li> <li>ResourceFileのチェック&DL <ul> <li>AssetBundle化していないバイナリ(<a class="keyword" href="http://d.hatena.ne.jp/keyword/CRIWARE">CRIWARE</a>系のファイル)</li> <li>動画、BGM、SE、キャラボイス、シナリオボイス</li> </ul> </li> </ul> <p>余談<br/> アプリサイズは150MB以下を指標としている</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%C8%A5%EB%A5%CD%A5%C3%A5%AF">ボトルネック</a>紹介</h3> <ul> <li>マスタDL <ul> <li>種類が多すぎる(80種類)</li> <li>一部マスタのサイズが大きい <ul> <li>カード(4MB) パラメータ</li> <li>ク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト(10MB) 敵、報酬</li> <li>シナリオ(5MB) ストーリー</li> </ul> </li> </ul> </li> <li>AssetBundle DL <ul> <li>アイコン(4500種類) → ゲーム起動時</li> <li>Spineなど → 随時 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%C8%A5%EB%A5%CD%A5%C3%A5%AF">ボトルネック</a>はアイコン</li> </ul> </li> </ul> </li> <li>ResourceFile DL <ul> <li>ゲーム起動時にDL</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%C8%A5%EB%A5%CD%A5%C3%A5%AF">ボトルネック</a> <ul> <li>シナリオボイスの数</li> <li>ファイルチェック回数</li> <li>動画の容量</li> </ul> </li> </ul> </li> </ul> <h3>対策内容紹介</h3> <h4>マスタDL</h4> <p>そのそもの管理の仕方</p> <ul> <li>各マスタはバージョン管理マスタで管理</li> </ul> <p>更新方法</p> <ul> <li>エクセルから<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>作成</li> <li>管理画面で入力 <ul> <li>事前に解析</li> <li>差分表示</li> <li>適用 <ul> <li>バージョン管理マスタも同時に更新</li> </ul> </li> </ul> </li> </ul> <p>ロードの処理フロー</p> <ul> <li>バージョンチェック <ul> <li>リク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト <ul> <li>ローカルに保存しているマスタID配列</li> <li>バージョン配列</li> </ul> </li> <li>レスポンス <ul> <li>差分があるマスタID配列</li> </ul> </li> </ul> </li> <li>必要なマスタ取得</li> <li>ローカルに保存</li> </ul> <p> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%C8%A5%EB%A5%CD%A5%C3%A5%AF">ボトルネック</a></p> <ul> <li>マスタの種類 <ul> <li>ゲーム起動時にまるごと取得するのをやめる</li> <li>必要なときに必要な分だけDL</li> </ul> </li> <li>既存<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のレスポンス内にマスタを含める</li> <li>サイズが大きい <ul> <li>使用していないマスタをフィルタリングして返す <ul> <li>マスタ上の有効期限(startTime, endTime)で管理</li> </ul> </li> <li>アプリで参照してないデータをフィルタリング <ul> <li>サーバーで除外して返却</li> </ul> </li> </ul> </li> </ul> <h4>AssetBundle DL</h4> <p>アイコン<br/> 起動時にDL → 随時DLに変更</p> <ul> <li>アイコン表示部分をすべて対応</li> <li>図鑑などアイコンが複数並ぶ画面は表示を行いながら非同期でDL</li> <li>キャッシュクリアなどを行うとアイコンが徐々に表示される挙動になるがそれは許容する</li> </ul> <h4>ResourceFile DL</h4> <ul> <li>シナリオボイス <ul> <li>随時DLに変更</li> </ul> </li> <li>ファイルチェック回数 <ul> <li>更新があったときのみチェック&DL <ul> <li>ResourceFile管理マスタで管理する <ul> <li>id, file_name, size, <a class="keyword" href="http://d.hatena.ne.jp/keyword/md5">md5</a>_key</li> </ul> </li> <li>マスタ生成は自動化 <ul> <li>git pullしたタイミングでjenkinsで実行</li> </ul> </li> </ul> </li> </ul> </li> <li>動画 <ul> <li>再生する場所で随時DL</li> <li>過去イベントの動画はDLしない <ul> <li>DLに時間がかかるため<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC%A5%B9%A5%D0%A1%BC">プログレスバー</a>の表示</li> </ul> </li> <li>動画管理マスタで管理 <ul> <li>id, play_scene, place, start_time, end_time</li> </ul> </li> </ul> </li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC%A5%B9%A5%D0%A1%BC">プログレスバー</a>の表現の工夫</p> <ul> <li>1本の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC%A5%B9%A5%D0%A1%BC">プログレスバー</a>(0~100%)をスムーズに動かす</li> </ul> <p>以下のように変更<br/> DL完了したファイル数 / DLするファイル数<br/> → DLした容量 / DLする容量<br/> (<code>System.Net.WebClient.DownloadProgressChanged</code>を併用)</p> <p>表現の工夫</p> <ul> <li>キャラ紹介画像削除 <ul> <li>タイトルタップしたらマイページへ遷移</li> <li>新規キャラが増えたときとみ表示</li> </ul> </li> </ul> <h3>まとめ</h3> <ul> <li>マスタ <ul> <li>起動時にロードするデータを少なく</li> <li>ロードするマスタは小さく(使っていないデータをフィルタリング)</li> </ul> </li> <li>AssetBundle, ResourceFile <ul> <li>随時DL方式にして分散すさせる</li> <li>ファイルチェックも時間がかかるので不要にIOアクセスを走らせない</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC%A5%B9%A5%D0%A1%BC">プログレスバー</a>で表現の工夫をする</li> </ul> </li> </ul> <p>効果</p> <ul> <li>お客様に喜んでもらえた</li> <li>新規インストールのDL料が減った</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>料金が減った</li> <li>開発の<a class="keyword" href="http://d.hatena.ne.jp/keyword/PDCA">PDCA</a>が早くなった</li> </ul> <h3>今後チャレンジしたいこと</h3> <ul> <li>バックグラウンドDL</li> <li>一括DL、随時D選択</li> <li>動画のストリーミング再生</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%EC%A5%B9%A5%D0%A1%BC">プログレスバー</a>などのUX工場</li> </ul> <hr /> <h2>所感</h2> <ul> <li>考えればそうなるよなという話だった</li> <li>UXの話が興味深かった</li> <li>他の講演では随時DLの方法をとらない紹介がいくつかあったので、消極的な対処法という印象を受けた</li> </ul> turgure [Unite2019] Google Cloud for Games 〜オープンソースからマネージドサービスへ〜 hatenablog://entry/26006613445727400 2019-10-07T01:39:57+09:00 2019-10-07T01:44:12+09:00 動画・スライド:なし ハムディ サミール グーグル・クラウド・ジャパン合同会社 ※ スライドが公開されてないためメモ書き程度の内容になっています 学んだ知見 agones k8sを活用したサービスの場合スケールアウトをより負担なくできる open match リアルタイムマッチング機能開発を新しくする場合に使える 講演概要 フォーカスしていること ゲームサーバホスティング ゲームサーバをクラウド化 プラットフォームサービス マッチメイキング、アイテム管理など ゲーム分析 googleだからこそ クロスプラットフォーム オープンソース ML&データ分析 One Google 次世代マルチプレイヤ… <p>動画・スライド:なし</p> <p>ハムディ サミール グーグル・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>・ジャパン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%E7%C6%B1%B2%F1%BC%D2">合同会社</a></p> <p>※ スライドが公開されてないためメモ書き程度の内容になっています</p> <hr /> <h3>学んだ知見</h3> <ul> <li>agones <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>を活用したサービスの場合スケールアウトをより負担なくできる</li> </ul> </li> <li>open match <ul> <li>リアルタイムマッチング機能開発を新しくする場合に使える</li> </ul> </li> </ul> <hr /> <h2>講演概要</h2> <p>フォーカスしていること</p> <ul> <li>ゲームサーバ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a> <ul> <li>ゲームサーバを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>化</li> </ul> </li> <li>プラットフォームサービス <ul> <li>マッチメイキング、アイテム管理など</li> </ul> </li> <li>ゲーム分析</li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>だからこそ</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">クロスプラットフォーム</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9">オープンソース</a></li> <li>ML&データ分析</li> <li>One <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a></li> </ul> <p>次世代<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4%A5%E4%A1%BC">マルチプレイヤー</a>ゲーム</p> <ol> <li>real-time multiplayer experiences</li> <li>planet-scale matchmaking</li> </ol> <h2>1.real-time multiplayer experiences</h2> <p>ゲームサーバとは?</p> <ul> <li>イベントを受け持つサーバ</li> <li>正しいゲーム世界を表示するためにゲームの状態に関するデータを送受信</li> <li>リアルタイムかつ信頼できる方法で完了しなければならない</li> </ul> <p>クライアント</p> <ul> <li>PC, コンソール、モバイル</li> <li>単一プレイヤー サーバ</li> <li>Host, <a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a></li> <li>対戦プレイヤー</li> </ul> <p>ゲームサーバが行うこと</p> <ul> <li>入力を受信</li> <li>位置トラック</li> <li>衝突、異動管理</li> <li>物理演算</li> <li>ゲーム状態をプレイヤーに送信</li> </ul> <p>毎秒120回にも及んで処理をしている!</p> <p>よく使う<a class="keyword" href="http://d.hatena.ne.jp/keyword/P2P">P2P</a>モデル<br/> なぜ専用サーバが必要か?</p> <ul> <li>すでに<a class="keyword" href="http://d.hatena.ne.jp/keyword/P2P">P2P</a>があるし、無料</li> </ul> <p>しかし、マルチスケールしない、チート対策できない<br/> 平均以下の体験になってしまう</p> <p>専用サー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%E2">バモ</a>デル</p> <ul> <li>一貫性</li> <li>スケーラブル</li> <li>セキュア<br/> ワールドクラスの体験<br/> 最近はこちらが主流(fort night, apexなど)</li> </ul> <p>→ Dedicated Game Server</p> <p><strong>典型的な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a></strong><br/> クライアント → Matchmaker ←→ Server Manager ←→ 複数のDedicated Game Server<br/> ↓<br/> Dedicated Game Server</p> <p>自前で作ると…</p> <ul> <li>外部依存なし</li> <li>コンテナ不要</li> <li>コーディング必須 <ul> <li>メンテの必要性</li> </ul> </li> </ul> <p>専用サーバのデプロイ<br/> Gameserverをたくさんよういしてやる</p> <p>もう1つのやり方、コンテナ化</p> <ul> <li>どの<a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>環境でも実行可能</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>でコミュニティが開発</li> <li>コンテナ化は必須 <ul> <li>OSの選定が必要になる</li> </ul> </li> </ul> <p>agonesを利用?</p> <p>Agonesについて</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9">オープンソース</a></li> <li>ゲームサーバの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>とスケーリング</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>上で動作</li> </ul> <p>ゲームサーバのあれこれをコンテナで正しく動作させるために作られた</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>の機能</p> <ul> <li>ゲームサーバのライフサイクル管理 <ul> <li>レディネス&停止</li> <li>ヘルスチェック</li> <li>アクセスと監視の設定</li> <li>構成値を設定</li> </ul> </li> </ul> <p>agonesを使うと、スケールダウンについて起動中のセッションを落とさずに実行できる!!<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a>だけだと起動中のものも落ちてしまう</p> <p>一般的にアロケートされたものを解除したいときは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>で解除のメソッドを呼べばallocated → readyになる</p> <p>Agonesの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a><br/> クライアント → Custom Matchmaker → <a class="keyword" href="http://d.hatena.ne.jp/keyword/k8s">k8s</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> ←→ Agones → Dedicated Game Server</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud Game Servers(agones + <a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloud)<br/> フルマネージドAgones</p> <ul> <li>シンプル</li> <li>柔軟</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a>と同じ<a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a></li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> Cloudで グローバル&リアルタイム&<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4%A5%E4%A1%BC">マルチプレイヤー</a><br/> ゲームをローンチする最もかんたんな方法</p> <p>高いパフォーマンスも発揮できる</p> <h2>2. planet-scale matchmaking</h2> <p>open match</p> <ul> <li>マッチメイク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a></li> <li>柔軟性、スケーラビリティ、拡張性にフォーカス</li> </ul> <p>doodle ハロウィンで初めて利用された</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a><br/> player ←→ Game Frontend → Hosted Environment(open match) ← director → Servers</p> <p>Game Frontend: チート対策のために、open matchを直セスアクセスさせない(ロビーでプレイヤー情報を確認する)<br/> director: マッチングをトリガーするプロセス</p> <p>fake player0/1 → create ticket<br/> match<br/> return assignment to open match by director<br/> return assignment to fake player0/1 by open match</p> <p>ticker: 試合をリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トしているプレイヤー<br/> assignment: open matchからチケット作成者に情報が返る</p> <p>現状のopen matchはv0.7</p> <p>open matchの事例</p> <ul> <li>kick flight <ul> <li>360ど空中対戦アクションゲーム</li> <li>4vs4のリアルタイムバトル</li> </ul> </li> </ul> turgure [Unite2019] AWS for Unity Developers hatenablog://entry/26006613445726987 2019-10-07T01:37:45+09:00 2019-10-07T01:43:59+09:00 動画・スライド:https://learning.unity3d.jp/3248/ 下田 純也 アマゾンウェブサービスジャパン株式会社 Fan Liang アマゾンウェブサービスジャパン株式会社 学んだ知見 1.ビルド時間の調査 アセットバンドルビルド プロセスを並列化してビルドが効果大 ゲーム本体のビルド スケールアップが効果大 2.Amazon GameLift セッションベースのマルチプレイヤーゲーム用サービス サーバの運用、デプロイ、スケーリングをサポート マッチング管理が楽 ロジック作成に専念 講演概要 AWSの活用例 ゲームサーバとしてマルチプレイヤーゲームでの利用 問題点 リアル… <p>動画・スライド:<a href="https://learning.unity3d.jp/3248/">https://learning.unity3d.jp/3248/</a></p> <p>下田 純也 アマゾン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%A7%A5%D6%A5%B5%A1%BC%A5%D3%A5%B9">ウェブサービス</a>ジャパン株式会社<br/> Fan Liang アマゾン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A6%A5%A7%A5%D6%A5%B5%A1%BC%A5%D3%A5%B9">ウェブサービス</a>ジャパン株式会社</p> <hr /> <h2>学んだ知見</h2> <p>1.ビルド時間の調査</p> <ul> <li>アセットバンドルビルド <ul> <li>プロセスを並列化してビルドが効果大</li> </ul> </li> <li>ゲーム本体のビルド <ul> <li>スケールアップが効果大</li> </ul> </li> </ul> <p>2.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a> GameLift</p> <ul> <li>セッションベースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4%A5%E4%A1%BC">マルチプレイヤー</a>ゲーム用サービス</li> <li>サーバの運用、デプロイ、スケーリングをサポート <ul> <li>マッチング管理が楽</li> <li>ロジック作成に専念</li> </ul> </li> </ul> <hr /> <h2>講演概要</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>の活用例</p> <ul> <li>ゲームサーバとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4%A5%E4%A1%BC">マルチプレイヤー</a>ゲームでの利用</li> </ul> <p>問題点</p> <ul> <li>リアルタイムな通信の確保</li> <li>マッチメイキングの実装</li> </ul> <p>→ <a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a> GameLift</p> <ul> <li>セッションベースのゲームサーバ構築</li> <li>メリット <ul> <li>手間がかからない</li> <li>低レイテンシの実現</li> <li>ローコスト、ハイスケール</li> <li>相手のスペックに応じた適切なメイキングシステム(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Flex">Flex</a> Match)</li> </ul> </li> </ul> <p><img src="https://image.slidesharecdn.com/09251330roomdjunyashimoda-190925063331/95/unite-tokyo-2019aws-for-unity-developers-37-638.jpg?cb=1569393959" width="600"></p> <p>サンプルデモとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a> GameLiftを用いた対戦型の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%C8%A5%EA%A5%B9">テトリス</a>の紹介がありました<br/> 例として以下のように「クライアント - ゲームサーバ - <a class="keyword" href="http://d.hatena.ne.jp/keyword/Amazon">Amazon</a> GameLift」の接続が行われています<br/> <img src="https://image.slidesharecdn.com/09251330roomdjunyashimoda-190925063331/95/unite-tokyo-2019aws-for-unity-developers-54-638.jpg?cb=1569393959" width="600"></p> <h3>tips</h3> <ul> <li>開発環境はローカルで作れない <ul> <li>スポット<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を使うと料金の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%B9%A5%D1">コスパ</a>がいい</li> </ul> </li> <li>ログ確認はLogErrorをみるとよい</li> </ul> <hr /> <h2>所感</h2> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>の利用説明はざっくりとで、主にGameliftの説明が主だった</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>サーバの構築例なども軽く紹介されていたので、<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/AWS">AWS</a>活用のノウハウがない場合のスライドとしては有用な資料だと思う</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%D7%A5%EC%A5%A4">マルチプレイ</a>ゲームの知見がない場合にはこの資料を参考にすればとっかかりにはよい</li> </ul> turgure [Unite2019] Game Server Services ではじめる サーバー開発運用しないゲーム開発 hatenablog://entry/26006613445726127 2019-10-07T01:34:04+09:00 2019-10-07T01:43:47+09:00 動画・スライド:https://learning.unity3d.jp/3241/ 丹羽 一智 Game Server Services 株式会社 学んだ知見 Game Server Services(GS2)が目指すもの → 汎用ゲームサーバー 初期費用・運用費用なし 料金は0.02円/API 秒間10万アクセスにも耐えられる SINoALICEのピーク時アクセスの2倍以上 改ざん・チート対策も完備 github, excelを用いたマスタ管理 環境をyaml形式で管理、サーバのオートスケールも可能 AWZ, GCPの機能を利用 DeNA, KLab, ワンダープラネットでの採用実績あり サ… <p>動画・スライド:<a href="https://learning.unity3d.jp/3241/">https://learning.unity3d.jp/3241/</a></p> <p>丹羽 一智 Game Server Services 株式会社</p> <hr /> <h2>学んだ知見</h2> <ul> <li>Game Server Services(GS2)が目指すもの → 汎用ゲームサーバー</li> <li>初期費用・運用費用なし <ul> <li>料金は0.02円/<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></li> </ul> </li> <li>秒間10万アクセスにも耐えられる <ul> <li>SINoALICEのピーク時アクセスの2倍以上</li> </ul> </li> <li>改ざん・チート対策も完備</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/excel">excel</a>を用いたマスタ管理</li> <li>環境を<a class="keyword" href="http://d.hatena.ne.jp/keyword/yaml">yaml</a>形式で管理、サーバのオートスケールも可能 <ul> <li>AWZ, <a class="keyword" href="http://d.hatena.ne.jp/keyword/GCP">GCP</a>の機能を利用</li> </ul> </li> </ul> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/DeNA">DeNA</a>, KLab, ワンダープラネットでの採用実績あり</p> <p>サンプル<br/> <a href="https://github.com/gs2io/gs2-sample">https://github.com/gs2io/gs2-sample</a></p> <p>公式HP<br/> <a href="https://gs2.io">https://gs2.io</a></p> <hr /> <h2>講演概要</h2> <h3>なぜGS2か?</h3> <p>開発者を追うべき責任<br/> ○ おもしろさ<br/> × 動くことの担保</p> <p>クライアントにはUnity, <a class="keyword" href="http://d.hatena.ne.jp/keyword/UE4">UE4</a>がある<br/> サーバーには汎用エンジンが存在しないのでは?</p> <h3>GS2が提供する<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></h3> <ul> <li>アカウント管理(作成、引継ぎ)</li> <li>経験値・レベル</li> <li>プレゼントボックス</li> <li>所持品</li> <li>回数制限</li> <li>抽選処理</li> <li>マッチメイキング</li> <li>課金通貨</li> <li>ク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト</li> <li>リアルタイム対戦</li> <li>ミッション</li> <li>イベントスケジュール</li> <li>ゲーム内ストア</li> <li>スタミナ</li> <li>編成(パーティ、装備)</li> <li>チャット機能</li> <li>フレンド</li> <li>バージョン管理</li> </ul> <p><strong>用例1:イベント期間1回だけ買える商品</strong><br/> イベントスケジュール → 販売期間を設定<br/> 回数制限       → 購入回数を設定</p> <p><img src="https://image.slidesharecdn.com/09251200roomdkazutomoniwa-190925035047/95/unite-tokyo-2019game-server-services-22-638.jpg?cb=1569383973" width="600"></p> <p><strong>用例2:ログインボーナス</strong><br/> ク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト        → ログインボーナスを「1日1回進行できるク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>ト」として定義<br/> 回数制限        → ク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トの進行回数<br/> イベントスケジュール  → 公開中のログインボーナス<br/> 所持品         → ログインボーナスを獲得して追加</p> <p>サー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%B9%A5%AF">バスク</a>リプトに記述 → ク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トの終端に達したら進行状況をリセット</p> <p><img src="https://image.slidesharecdn.com/09251200roomdkazutomoniwa-190925035047/95/unite-tokyo-2019game-server-services-23-638.jpg?cb=1569383973" width="600"></p> <h3>チート対策</h3> <p>「報酬」と「対価」をセットにしたスタンプシートで管理<br/> 報酬と対価の両方が支払われた場合スタンプシートを永久に破棄<br/> 以下のようなチートを確実に防げる</p> <ul> <li>対価を支払っていないのに報酬を支払う</li> <li>対価・報酬を改ざんして請求</li> </ul> <p><img src="https://image.slidesharecdn.com/09251200roomdkazutomoniwa-190925035047/95/unite-tokyo-2019game-server-services-35-638.jpg?cb=1569383973" width="600"></p> <h2>所感</h2> <ul> <li>よさそう <ul> <li>これから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D5%A5%A1%A5%AF%A5%C8%A5%B9%A5%BF%A5%F3%A5%C0%A1%BC%A5%C9">デファクトスタンダード</a>になっていくかも?</li> </ul> </li> <li>会社で複数ゲームを取り扱うときに、基盤機能の共通プラットフォームとして利用できるのでは <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%D6%CE%D8%A4%CE%BA%C6%B3%AB%C8%AF">車輪の再開発</a>がいらなくなる</li> </ul> </li> <li>ゲーム特有でサーバ処理が必要な場合はどうなるのか? <ul> <li>独自のフックを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>で書いて対応可能 <ul> <li>リザルトの理論値計算、不正チェック</li> <li>パーティ編成の不正チェックなど(コストオーバー検知)</li> </ul> </li> </ul> </li> </ul> turgure [Unite2019] 中の人がいない!? 音声対話型AIサービスを使ったバーチャルキャラクターの作り方 hatenablog://entry/26006613445725440 2019-10-07T01:31:59+09:00 2019-10-07T01:43:34+09:00 動画・スライド:https://learning.unity3d.jp/3235/ 秋永 和計 株式会社NTTドコモ 尾崎 竜二 だるまジャパン合同会社 北川 正義 だるまジャパン合同会社 AI セバスちゃん 学んだ知見 音声認識、自然言語処理、音声合成をすべて内部で行うことで 中の人がいない対話AIを作成している AIは対話ログから頻出ワードをマッチさせることで人間が学習させている セバスちゃんはツンデレ属性 → 特別に学習データを作ることで特有の表現は学習可能 中の人がいなくても魂は込めることができる 講演概要 AIの内部構成 このプロジェクトで利用しているSDKは公開されています htt… <p>動画・スライド:<a href="https://learning.unity3d.jp/3235/">https://learning.unity3d.jp/3235/</a></p> <p>秋永 和計 株式会社<a class="keyword" href="http://d.hatena.ne.jp/keyword/NTT%A5%C9%A5%B3%A5%E2">NTTドコモ</a><br/> 尾崎 竜二 だるまジャパン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%E7%C6%B1%B2%F1%BC%D2">合同会社</a><br/> 北川 正義 だるまジャパン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%E7%C6%B1%B2%F1%BC%D2">合同会社</a><br/> AI セバスちゃん</p> <hr /> <h2>学んだ知見</h2> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%C0%BC%C7%A7%BC%B1">音声認識</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%AB%C1%B3%B8%C0%B8%EC%BD%E8%CD%FD">自然言語処理</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%C0%BC%B9%E7%C0%AE">音声合成</a>をすべて内部で行うことで<br/> 中の人がいない対話AIを作成している</li> <li>AIは対話ログから頻出ワードをマッチさせることで人間が学習させている</li> <li>セバスちゃんは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C4%A5%F3%A5%C7%A5%EC">ツンデレ</a>属性<br/> → 特別に学習データを作ることで特有の表現は学習可能</li> </ul> <p>中の人がいなくても魂は込めることができる</p> <hr /> <h2>講演概要</h2> <p><img src="https://image.slidesharecdn.com/09251100roomdyoshikazuakinaga-190925033902/95/unite-tokyo-2019-ai-9-638.jpg?cb=1569383237" width="600"></p> <p>AIの内部構成<br/> <img src="https://image.slidesharecdn.com/09251100roomdyoshikazuakinaga-190925033902/95/unite-tokyo-2019-ai-5-638.jpg?cb=1569383237" width="600"></p> <p>このプロジェクトで利用している<a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>は公開されています<br/> <a href="https://dev.smt.docomo.ne.jp/?p=common_page&p_name=sebastien_teaser">https://dev.smt.docomo.ne.jp/?p=common_page&p_name=sebastien_teaser</a> <img src="https://image.slidesharecdn.com/09251100roomdyoshikazuakinaga-190925033902/95/unite-tokyo-2019-ai-66-638.jpg?cb=1569383237" width="600"></p> <p>資料の後半は<a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>の使いかたの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A5%E5%A1%BC%A5%C8%A5%EA%A5%A2%A5%EB">チュートリアル</a>となっているので、<br/> 音声対話の実装の参考になると思います</p> <hr /> <h2>所感</h2> <ul> <li>ゲームとの連携は難しそう(音声対話という点から)</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/web%A5%B5%A1%BC%A5%D3%A5%B9">webサービス</a>との相性は良さそう <ul> <li>ただしシナリオ作成まわりの整備が必要になりそう</li> <li>そもそもUnityを使わないで利用できるのかという点も要確認</li> </ul> </li> </ul> turgure [Unite2019] Unityで手軽に使えるAIエンジンailia SDK hatenablog://entry/26006613445724934 2019-10-07T01:29:32+09:00 2019-10-07T01:43:08+09:00 動画・スライド:なし 品部 仁志 株式会社アクセル 学んだ知見 ailia SDKを利用することでクロスプラットフォームでのMLモデル開発が可能 モデルをエッジ機器(PC、スマートフォン)に保持できるため、 ネットワークに接続していなくてもモデルの利用が可能 補足 clip studioで採用事例あり https://prtimes.jp/main/html/rd/p/000000027.000004053.html 講演概要 ailia SDKを使わない場合のフロー 1.従来のフロー1 よくある問題 モデルをエッジ機器で持ちにくい モデル構築がpythonベース 常時インターネット接続が必要… <p>動画・スライド:なし</p> <p>品部 仁志 株式会社アクセル</p> <hr /> <h2>学んだ知見</h2> <ul> <li>ailia <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>を利用することで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">クロスプラットフォーム</a>でのMLモデル開発が可能</li> <li>モデルをエッジ機器(PC、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A1%BC%A5%C8%A5%D5%A5%A9%A5%F3">スマートフォン</a>)に保持できるため、<br/> ネットワークに接続していなくてもモデルの利用が可能</li> </ul> <h4>補足</h4> <p>clip studioで採用事例あり<br/> <a href="https://prtimes.jp/main/html/rd/p/000000027.000004053.html">https://prtimes.jp/main/html/rd/p/000000027.000004053.html</a></p> <hr /> <h2>講演概要</h2> <h3>ailia <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>を使わない場合のフロー</h3> <p>1.従来のフロー1<br/> <img src="https://image.slidesharecdn.com/09251000roomloungehitoshishinabe-190925024048/95/unite-tokyo-2019unityaiailia-sdk-14-638.jpg?cb=1569379443" width="600" border="2"></p> <p>よくある問題</p> <ul> <li>モデルをエッジ機器で持ちにくい <ul> <li>モデル構築が<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>ベース</li> </ul> </li> <li>常時インターネット接続が必要 <ul> <li>通信量の問題</li> <li>ネットワークが切れたときの動作の担保</li> </ul> </li> <li>サーバーでのコスト大</li> </ul> <p>2.従来のフロー2<br/> <img src="https://image.slidesharecdn.com/09251000roomloungehitoshishinabe-190925024048/95/unite-tokyo-2019unityaiailia-sdk-16-638.jpg?cb=1569379443" width="600" border="2"></p> <p>よくある問題</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>向けのDNN<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>がない <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>, core MLなどを使うことがおおいので、モデル変換に失敗する</li> </ul> </li> <li>モデル自体の容量が大きすぎる <ul> <li>VGGだと数百MB</li> </ul> </li> <li>特定の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU">GPU</a>しか動かない</li> <li>実行が重い、実機でしか動作確認できない</li> </ul> <p>3.ailia <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>を使った場合<br/> <img src="https://image.slidesharecdn.com/09251000roomloungehitoshishinabe-190925024048/95/unite-tokyo-2019unityaiailia-sdk-18-638.jpg?cb=1569379443" width="600" border="2"></p> <p>エクスポートに<code>caffe model</code>, <code>ONNX</code>というものを使う</p> <ul> <li>すべての<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF">フレームワーク</a>で共通で動く</li> <li>統一フォーマットで管理</li> <li>圧縮、難読化ができる</li> <li>ailia <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>だけで実行可能</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">クロスプラットフォーム</a></li> </ul> <h3>ailia <a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>が提供する価値</h3> <p>1.高速、世界一を目指す<br/> tensorflow liteの3倍の性能</p> <p>2.ハードウェアの選択肢を提供<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>, <a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>などに対応<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/FPGA">FPGA</a>も視野に入れる</p> <p>3.快適・安心・効率的</p> <hr /> <h2>所感</h2> <ul> <li>知識がある場合は、基本的に学習済みモデルがサンプルとしてあるだけなので別に利用しなくてもいいと思った <ul> <li>自分で作成したモデルを使うことも可能</li> </ul> </li> <li>ただ、手間をかけずに利用できる点は便利</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">クロスプラットフォーム</a>開発のコストが高い場合は利用価値がありそう</li> </ul> turgure [Unite2019] レポートリンクまとめ hatenablog://entry/26006613445724451 2019-10-07T01:26:54+09:00 2019-10-07T01:57:47+09:00 今年もUniteに参加したので講演のレポートを上げようと思います 去年のはこちら turgure.hatenablog.com 公式サイト:Unite Tokyo 2019 - Unity DAY1 Unityで手軽に使えるAIエンジンailia SDK 中の人がいない!? 音声対話型AIサービスを使ったバーチャルキャラクターの作り方 Game Server Services ではじめる サーバー開発運用しないゲーム開発 AWS for Unity Developers Google Cloud for Games 〜オープンソースからマネージドサービスへ〜 DAY2 『SINoALICE -… <p>今年もUniteに参加したので講演のレポートを上げようと思います<br/> 去年のはこちら <iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fturgure.hatenablog.com%2Fentry%2F2018%2F05%2F25%2F112824" title=" [Unite2018] レポートリンクまとめ - しがないエンジニアのブログ" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://turgure.hatenablog.com/entry/2018/05/25/112824">turgure.hatenablog.com</a></cite></p> <p>公式サイト:<a href="https://events.unity3d.jp/unitetokyo/">Unite Tokyo 2019 - Unity</a></p> <hr /> <p>DAY1</p> <ul> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/012932">Unityで手軽に使えるAIエンジンailia SDK</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/013159">中の人がいない!? 音声対話型AIサービスを使ったバーチャルキャラクターの作り方</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/013404">Game Server Services ではじめる サーバー開発運用しないゲーム開発</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/013745">AWS for Unity Developers</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/013957">Google Cloud for Games 〜オープンソースからマネージドサービスへ〜</a></li> </ul> <p>DAY2</p> <ul> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/014226">『SINoALICE -シノアリス- 』〜 それは最速のゲーム起動 〜</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/014635">大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/014844">Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~</a></li> <li><a href="http://turgure.hatenablog.com/entry/2019/10/07/015014">「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック</a></li> </ul> turgure mysqlのストレージエンジンの種類について hatenablog://entry/17680117127076283848 2019-04-24T16:22:34+09:00 2019-04-24T16:22:34+09:00 mysqlのengineってなんだろうと思ったのでまとめてみた。 現在使っているのはInnoDBというものだが、実はいろいろ種類があるらしい。 mysql> show engines; +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +---------… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/mysql">mysql</a>のengineってなんだろうと思ったのでまとめてみた。<br/> 現在使っているのは<code>InnoDB</code>というものだが、実はいろいろ種類があるらしい。</p> <pre class="code" data-lang="" data-unlink>mysql&gt; show engines; +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+</pre> <p>公式リファレンスはこちら<br/> <a href="https://dev.mysql.com/doc/refman/5.6/ja/storage-engines.html">MySQL :: MySQL 5.6 &#x30EA;&#x30D5;&#x30A1;&#x30EC;&#x30F3;&#x30B9;&#x30DE;&#x30CB;&#x30E5;&#x30A2;&#x30EB; :: 15 &#x4EE3;&#x66FF;&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;</a></p> <p>それらを1つずつざっくりと説明する。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/InnoDB">InnoDB</a></h1> <p>mysql5.5以降はデフォルトでこれが指定される。<br/> とりあえずこちらを利用しておけばいいと思う。<br/> 以下のような特徴がある。</p> <ul> <li>行ロック</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%F3%A5%B6%A5%AF%A5%B7%A5%E7%A5%F3">トランザクション</a>機能がある(<a class="keyword" href="http://d.hatena.ne.jp/keyword/InnoDB">InnoDB</a>のみ)</li> <li>堅牢性が高い</li> </ul> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/MyISAM">MyISAM</a></h1> <p><code>InnoDB</code>と比較されるもう一つのストレージエンジン。<br/> <code>InnoDB</code>を使う理由がない場合は<code>MyISAM</code>を使う。<br/> 以下のような特徴がある。</p> <ul> <li>テーブルロック</li> <li>アクセスが早い</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%F3%A5%B6%A5%AF%A5%B7%A5%E7%A5%F3">トランザクション</a>機能がない</li> <li><code>InnoDB</code>よりテーブルサイズが小さい</li> </ul> <p>参考</p> <ul> <li><a href="https://thinkit.co.jp/free/article/0608/1/1/">[ThinkIT] &#x7B2C;1&#x56DE;&#xFF1A;MySQL&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x306E;&#x6982;&#x8981; (1/3)</a></li> </ul> <h1>MEMORY</h1> <p>名前の通り、データをメモリ上に展開して保存する。<br/> そのため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/mysql">mysql</a>を再起動するとデータが消えてしまう。<br/> メモリ上にあるため、アクセスが非常に高速。<br/> インデックスの種類として、b treeとhashの2種類が存在する(基本的にはb tree)</p> <p>参考</p> <ul> <li><a href="https://qiita.com/hirose-ma/items/c4a10d31a47a5421bb9c">MEMORY&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x3067;MySQL&#x306E;&#x30D1;&#x30D5;&#x30A9;&#x30FC;&#x30DE;&#x30F3;&#x30B9;&#x3092;&#x3042;&#x3052;&#x3088;&#x3046; - Qiita</a></li> <li><a href="http://cordea.hatenadiary.com/entry/2014/07/09/221545">MySQL&#x306E;MEMORY&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x3092;&#x8A66;&#x3057;&#x3066;&#x307F;&#x308B; - CORDEA blog</a></li> <li><a href="https://thinkit.co.jp/free/article/0608/1/3/">[ThinkIT] &#x7B2C;3&#x56DE;&#xFF1A;Memory&#x3068;Archive (1/3)</a></li> </ul> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSV">CSV</a></h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/sql">sql</a>のデータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>ファイルとして扱うことができる。<br/> <code>my.cnf</code>に設定した<code>datadir</code>以下に、<code>.frm</code>の他に、<code>.CSM</code>、<code>.CSV</code>の計3種類のファイルが作られる。<br/> その中の<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>ファイルを変更することで、DBのデータも一緒に変更することができる。<br/> 変更したあとは<code>FLUSH TABLE;</code>を忘れずに。</p> <p>参考</p> <ul> <li><a href="https://blog.kcg.ne.jp/s2node/2009/04/22/mysql%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF%E4%BF%9D%E5%AD%98%E5%BD%A2%E5%BC%8F%E3%81%8Ccsv%E5%BD%A2%E5%BC%8F%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92%E4%BD%BF%E3%81%A3/">MySQL&#x3067;&#x30C7;&#x30FC;&#x30BF;&#x4FDD;&#x5B58;&#x5F62;&#x5F0F;&#x304C;CSV&#x5F62;&#x5F0F;&#x306E;&#x30C7;&#x30FC;&#x30BF;&#x30D9;&#x30FC;&#x30B9;&#x3092;&#x4F7F;&#x3063;&#x3066;&#x307F;&#x308B; | &#x4E0D;&#x5B9A;&#x671F;&#x30BD;&#x30D5;&#x30C8;&#x30A6;&#x30A7;&#x30A2;&#x958B;&#x767A;</a></li> <li><a href="https://tech-blog.fancs.com/entry/%3Fp%3D1312">MySQL&#x306E;CSV&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3; - F@N Ad-Tech Blog</a></li> </ul> <h1>ARCHIVE</h1> <p>データの登録、参照のみ可能で、変更ができない。<br/> つまり、<code>SELECT</code>, <code>INSERT</code>のみの操作しけ受け付けず、<code>UPDATE</code>, <code>DELETE</code>, <code>REPLACE</code>などは利用できない。<br/> データは圧縮して保存されているため、容量が小さく済む。<br/> また、インデックスを付与することができない。(AUTO INCREMENTのカラムは除く)</p> <p>参考</p> <ul> <li><a href="https://thinkit.co.jp/cert/article/0608/1/3/2.htm">[ThinkIT] &#x7B2C;3&#x56DE;&#xFF1A;Memory&#x3068;Archive (2/3)</a></li> </ul> <h1>BLACKHOLE</h1> <p><code>SELECT</code>や<code>INSERT</code>などの<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>を発行しても、すべてemptyが返ってくるような形式。<br/> 主に試運転時や、マスター-スレーブ構成のときに使うらしい(よくわかってないです)。<br/> これについては参考サイトを確認してください。</p> <p>参考</p> <ul> <li><a href="https://heartbeats.jp/hbblog/2010/07/mysqlblackhole.html">MySQL&#x3067;Blackhole&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x3092;&#x6D3B;&#x7528;&#x3059;&#x308B;&#x306E;&#x30AA;&#x30DE;&#x30B1; - &#x30A4;&#x30F3;&#x30D5;&#x30E9;&#x30A8;&#x30F3;&#x30B8;&#x30CB;&#x30A2;way - Powered by HEARTBEATS</a></li> <li><a href="https://el.jibun.atmarkit.co.jp/decolog_tech/2011/03/decologmysql-bl-e26a.html">DECOLOG&#x3067;&#x306E;MySQL BlackHole&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x306E;&#x4F7F;&#x3044;&#x65B9;&#xFF1A;DECOLOG TECH BLOG annex&#xFF1A;&#x30A8;&#x30F3;&#x30B8;&#x30CB;&#x30A2;&#x30E9;&#x30A4;&#x30D5;</a></li> </ul> <h1>MERGE</h1> <p>複数のテーブルを結合し、あたかも1つのテーブルで処理しているかのようにできる。<br/> <code>INSERT</code>や<code>UPDATE</code>,<code>DELETE</code>をした場合、merge元とmerge先のテーブルの両方のデータが更新される。<br/> merge先のテーブルがインデックスをもつ場合、merge元のテーブルも必ず同じインデックスを有している必要がある。<br/> merge先のテーブルに<code>INSERT</code>する場合、<code>INSERT_METHOD</code>オプションでどのテーブルに挿入するかを決定する。</p> <p>例</p> <pre class="code lang-mysql" data-lang="mysql" data-unlink><span class="synStatement">CREATE</span> <span class="synStatement">TABLE</span> t1 ( a <span class="synType">INT</span> <span class="synStatement">NOT</span> <span class="synSpecial">NULL</span> <span class="synStatement">AUTO_INCREMENT</span> <span class="synStatement">PRIMARY</span> <span class="synStatement">KEY</span>, message <span class="synType">CHAR(</span><span class="synConstant">20</span><span class="synType">)</span>) ENGINE=<span class="synStatement">MyISAM</span>; <span class="synStatement">CREATE</span> <span class="synStatement">TABLE</span> t2 ( a <span class="synType">INT</span> <span class="synStatement">NOT</span> <span class="synSpecial">NULL</span> <span class="synStatement">AUTO_INCREMENT</span> <span class="synStatement">PRIMARY</span> <span class="synStatement">KEY</span>, message <span class="synType">CHAR(</span><span class="synConstant">20</span><span class="synType">)</span>) ENGINE=<span class="synStatement">MyISAM</span>; <span class="synStatement">INSERT</span> <span class="synStatement">INTO</span> t1 (message) <span class="synStatement">VALUES</span> (<span class="synConstant">'Testing'</span>),(<span class="synConstant">'table'</span>),(<span class="synConstant">'t1'</span>); <span class="synStatement">INSERT</span> <span class="synStatement">INTO</span> t2 (message) <span class="synStatement">VALUES</span> (<span class="synConstant">'Testing'</span>),(<span class="synConstant">'table'</span>),(<span class="synConstant">'t2'</span>); <span class="synStatement">CREATE</span> <span class="synStatement">TABLE</span> total ( a <span class="synType">INT</span> <span class="synStatement">NOT</span> <span class="synSpecial">NULL</span> <span class="synStatement">AUTO_INCREMENT</span>, message <span class="synType">CHAR(</span><span class="synConstant">20</span><span class="synType">)</span>, <span class="synStatement">INDEX</span>(a)) ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST; </pre> <p>参考</p> <ul> <li><a href="https://dev.mysql.com/doc/refman/5.6/ja/merge-storage-engine.html">MySQL :: MySQL 5.6 &#x30EA;&#x30D5;&#x30A1;&#x30EC;&#x30F3;&#x30B9;&#x30DE;&#x30CB;&#x30E5;&#x30A2;&#x30EB; :: 15.7 MERGE &#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;</a></li> </ul> <h1>FEDERATED</h1> <p>別のネットワークの<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>データにアクセスし、あたかもローカルがDBを持っているかのように振る舞うことができる。<br/> これによって、簡易的なマスター-スレーブ構成が作れる。</p> <p>参考</p> <ul> <li><a href="https://thinkit.co.jp/free/article/0608/1/5/">[ThinkIT] &#x7B2C;5&#x56DE;&#xFF1A;Federated&#x30A8;&#x30F3;&#x30B8;&#x30F3; (1/3)</a></li> <li><a href="https://qiita.com/toshiro3/items/bea579b86ca53803fc28">MySQL&#x306E;FEDERATED&#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x3092;&#x5229;&#x7528;&#x3059;&#x308B; - Qiita</a></li> </ul> <h1>EXAMPLE</h1> <p>自作のストレージエンジンを作成するための例として存在する。<br/> クエリを発行できるが、<code>SELECT</code>や<code>INSERT</code>はできない。</p> <p>参考</p> <ul> <li><a href="https://dev.mysql.com/doc/refman/5.6/ja/example-storage-engine.html">MySQL :: MySQL 5.6 &#x30EA;&#x30D5;&#x30A1;&#x30EC;&#x30F3;&#x30B9;&#x30DE;&#x30CB;&#x30E5;&#x30A2;&#x30EB; :: 15.9 EXAMPLE &#x30B9;&#x30C8;&#x30EC;&#x30FC;&#x30B8;&#x30A8;&#x30F3;&#x30B8;&#x30F3;</a></li> </ul> turgure XMLHttpRequestと後継のfetch APIについて hatenablog://entry/17680117126993962332 2019-03-15T19:59:10+09:00 2019-03-15T19:59:10+09:00 XMLHttpRequest XMLHttpRequestは、urlを指定してリクエストを送信することができる機能である。 基本的な使い方は以下の様になっている const xhr = new XMLHttpRequest(); xhr.open('GET', 'http://~~~'); xhr.send(); xhr.onload = () => { console.log(xhr.response); }); xhr.onerror = () => { console.log('error'); } open()で対象urlを指定する。このとき、POSTとGETの2種類から選択する se… <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/XMLHttpRequest">XMLHttpRequest</a></h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/XMLHttpRequest">XMLHttpRequest</a>は、urlを指定してリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを送信することができる機能である。<br/> 基本的な使い方は以下の様になっている</p> <pre class="code" data-lang="" data-unlink>const xhr = new XMLHttpRequest(); xhr.open(&#39;GET&#39;, &#39;http://~~~&#39;); xhr.send(); xhr.onload = () =&gt; { console.log(xhr.response); }); xhr.onerror = () =&gt; { console.log(&#39;error&#39;); }</pre> <p><code>open()</code>で対象urlを指定する。このとき、POSTとGETの2種類から選択する<br/> <code>send()</code>が実際に実行する部分<br/> <code>onload</code>は、実行が完了したあとに処理される部分</p> <p>ただし、この処理のあとに、onloadした結果を使いたいとなった場合、その処理が完了するのを待たなくてはいけない<br/> なにも考えずに使うとonloadの処理中に次にいってしまうため扱いづらい</p> <h1>fetch <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></h1> <p>fetch <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>は、よりシンプルに記述できるようになったもの<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>では使えなさそう(Edgeは使えそう)<br/> <a href="https://caniuse.com/#search=fetch">https://caniuse.com/#search=fetch</a></p> <p>使い方は以下の様になる</p> <pre class="code" data-lang="" data-unlink>fetch(&#39;http://~~~&#39;).then((response) =&gt; { console.log(response.status); }).catch(() =&gt; { console.log(&#39;error&#39;); });</pre> <p>メソッドチェーンを作って記述できるので、確実に処理の流れをつかんで記述できる<br/> メソッドチェーンを作らずに <code>async/await</code>を使うことで、よりきれいに書くことができる</p> <pre class="code" data-lang="" data-unlink>(async() =&gt; { try { const response = await fetch(&#39;http://~~~&#39;); console.log(response.status); } catch (e) { console.log(e); } })();</pre> <p>外部から関数化して呼び出す場合は以下のようにする</p> <pre class="code" data-lang="" data-unlink>const func = async() =&gt; { try { const response = await fetch(&#39;http://~~~&#39;); console.log(response.status); } catch (e) { console.log(e); } }</pre> <p><code>async/await</code>を使うことで、よりスマートに書くことができる</p> <p><br /></p> <p>参考文献</p> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/XMLHttpRequest">XMLHttpRequest</a></h4> <ul> <li><a href="https://gihyo.jp/dev/serial/01/crossbrowser-javascript/0012">&#x7B2C;12&#x56DE; XMLHttpRequest&#x5165;&#x9580;&#xFF1A;&#x3053;&#x308C;&#x3067;&#x3067;&#x304D;&#x308B;&#xFF01; &#x30AF;&#x30ED;&#x30B9;&#x30D6;&#x30E9;&#x30A6;&#x30B6;JavaScript&#x5165;&#x9580;&#xFF5C;gihyo.jp &hellip; &#x6280;&#x8853;&#x8A55;&#x8AD6;&#x793E;</a></li> <li><a href="http://webos-goodies.jp/archives/50548720.html">XMLHttpRequest &#x306E;&#x4F7F;&#x3044;&#x65B9; - WebOS Goodies</a></li> </ul> <h4>fetch <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a></h4> <ul> <li><a href="https://www.atatus.com/blog/fetch-api">Fetch API - Replacement for XMLHttpRequest (XHR)</a></li> <li><a href="https://qiita.com/uhyo/items/91649e260165b35fecd7">&#x307E;&#x3060;XMLHttpRequest&#x3092;&#x4F7F;&#x3063;&#x3066;&#x308B;&#x306E;&#xFF1F; fetch&#x306E;&#x3059;&#x3059;&#x3081; - Qiita</a></li> </ul> <h4>fetch <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a> + async/await</h4> <ul> <li><a href="https://blog.toshimaru.net/new-xhr-fetch-asyncawait">JavaScript&#x306E;XHR&#x306E;&#x9001;&#x308A;&#x65B9;&#x3044;&#x308D;&#x3044;&#x308D;: XMLHttpRequest, fetch, async/await - Hack Your Design!</a></li> </ul> turgure javascriptのPromiseやasync/awaitについて hatenablog://entry/17680117126993961513 2019-03-15T19:56:55+09:00 2019-03-15T19:56:55+09:00 Promise Promiseはjs側で用意されている非同期処理である。 Promise.resolve().then(() => { console.log('1'); return '1'; }).then((result) => { console.log('2'); return result + '2'; }).then((result) => { console.log('3'); return result + '3'; }).then((result) => { console.log('4'); return result + '4'; }).then((result) =>… <h1>Promise</h1> <p>Promiseはjs側で用意されている非同期処理である。</p> <pre class="code" data-lang="" data-unlink>Promise.resolve().then(() =&gt; { console.log(&#39;1&#39;); return &#39;1&#39;; }).then((result) =&gt; { console.log(&#39;2&#39;); return result + &#39;2&#39;; }).then((result) =&gt; { console.log(&#39;3&#39;); return result + &#39;3&#39;; }).then((result) =&gt; { console.log(&#39;4&#39;); return result + &#39;4&#39;; }).then((result) =&gt; { console.log(&#39;5&#39;); return result + &#39;5&#39;; }).then((result) =&gt; { console.log(result); }); /* =&gt; output 1 2 3 4 5 12345 */</pre> <p>メソッドチェーンによって、段階的に処理を記述できる</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>.Deferred</h1> <p>Deferredは<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>側のPromiseである。<br/> 例として、以下のサンプルを示す</p> <pre class="code" data-lang="" data-unlink>const deferred = new $.Deferred(); setTimeout(() =&gt; { console.log(&#39;timeout 1000&#39;); deferred.resolve(&#39;resolved&#39;); }, 1000); deferred.promise().then((result) =&gt; { console.log(result); }); /* =&gt; output timeout 1000 promise */</pre> <p>となる。</p> <p><code>deferred.resolve()</code>で処理が終了したことを知らせて、<br/> <code>deferred.promise()</code>で終了したデータを取得する。<br/> <code>resolve()</code>に引数を渡すことで、<code>promise()</code>側でそのデータを利用できる</p> <h1>async/await</h1> <p>今風の一番いい書き方がこれ<br/> <code>async/await</code>を使うことで、非同期をシーケンスに書くことができるようになる。<br/> <code>async</code>を定義した関数内で、<code>await</code>を使用することができる。<br/> <code>await</code>は、<code>Promise</code>の結果を受け取る。<code>await</code>の指定した関数が終了するまで、処理が一時停止する。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>ではサポートされていないなど、ブラウザに制限がある(2019.3現在)<br/> 確認は<a href="https://caniuse.com/#feat=async-functions">こちら</a>から</p> <p>以下に例を示す</p> <pre class="code" data-lang="" data-unlink>async function func(){ const res1 = await afunc1(); const res2 = await afunc2(); const res3 = await afunc3(); console.log(&#39;sum: &#39; + (res1 + res2 + res3)); } // そのまま結果を返す(resolveされる) function afunc1() { console.log(100); return 100; } // Promiseを宣言し、内部でresolveする function afunc2() { return new Promise((resolve) =&gt; { setTimeout(() =&gt; { console.log(200); resolve(200); }, 1000); }); } // asyncを組み合わせてresolveする async function afunc3() { await new Promise((resolve) =&gt; setTimeout(resolve, 2000)); console.log(300); return 300; } func(); /* =&gt; output 100 200 300 sum: 600 */</pre> <p>ちなみに、<code>Promise.all</code>というものを利用すれば、複数の処理を並列に行うことができる</p> <pre class="code" data-lang="" data-unlink>async function func() { let promises = []; promises.push(subfunc(&#39;promise1&#39;, 1000)); promises.push(subfunc(&#39;promise2&#39;, 2000)); promises.push(subfunc(&#39;promise3&#39;, 500)); const result = await Promise.all(promises); } function subfunc(name, ms) { console.log(name + &#39; start&#39;); return new Promise((resolve) =&gt; { setTimeout(() =&gt; { console.log(name + &#39; resolve&#39;); resolve(name); }, ms); }); } /* =&gt; output promise1 start promise2 start promise3 start promise3 resolve promise1 resolve promise2 resolve */</pre> <p><br /></p> <p>参考文献</p> <h4>Promise</h4> <ul> <li><a href="https://qiita.com/toshihirock/items/e49b66f8685a8510bd76#promiserace">Promise&#x306B;&#x3064;&#x3044;&#x3066;0&#x304B;&#x3089;&#x52C9;&#x5F37;&#x3057;&#x3066;&#x307F;&#x305F; - Qiita</a></li> </ul> <h4>Deferred</h4> <ul> <li><a href="https://qiita.com/opengl-8080/items/6eba7922be168edfc439">jQuery&#x306E;Deferred&#x306E;&#x57FA;&#x672C;&#x7684;&#x306A;&#x4F7F;&#x3044;&#x65B9;&#x30E1;&#x30E2; - Qiita</a></li> <li><a href="https://qiita.com/yuku_t/items/3d1cf51d7ae91305eaaa">jQuery.Deferred&#x3092;&#x4F7F;&#x3063;&#x3066;&#x697D;&#x3057;&#x3044;&#x975E;&#x540C;&#x671F;&#x751F;&#x6D3B;&#x3092;&#x9001;&#x308B;&#x65B9;&#x6CD5; - Qiita</a></li> </ul> <h4>async/await</h4> <ul> <li><a href="https://qiita.com/soarflat/items/1a9613e023200bbebcb3#promise%E3%82%92%E8%BF%94%E3%81%99">async/await &#x5165;&#x9580;&#xFF08;JavaScript&#xFF09; - Qiita</a></li> <li><a href="https://chaika.hatenablog.com/entry/2019/01/24/090000">JavaScript &#x4ECA;&#x66F4;&#x306E; async / await - &#x304B;&#x3082;&#x30E1;&#x30E2;</a></li> </ul> turgure mysqlで指定したtableを削除する方法 hatenablog://entry/17680117126991963881 2019-03-12T10:51:54+09:00 2019-03-12T10:51:54+09:00 mysql -h ホスト名 -u ユーザ名 -pパスワード -D test_database -e 'show tables' -s | egrep 'test' | xargs -I '@@' echo mysql -h ホスト名 -u ユーザ名 -pパスワード -D "test_database -e 'DROP TABLE @@'" 参考 mysql - MySQLでテーブルを全て、または正規表現で指定して削除する方法 - スタック・オーバーフロー <pre class="code" data-lang="" data-unlink>mysql -h ホスト名 -u ユーザ名 -pパスワード -D test_database -e &#39;show tables&#39; -s | egrep &#39;test&#39; | xargs -I &#39;@@&#39; echo mysql -h ホスト名 -u ユーザ名 -pパスワード -D &#34;test_database -e &#39;DROP TABLE @@&#39;&#34;</pre> <p>参考<br/> <a href="https://ja.stackoverflow.com/questions/11980/mysql%E3%81%A7%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E5%85%A8%E3%81%A6-%E3%81%BE%E3%81%9F%E3%81%AF%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%A7%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95">mysql - MySQL&#x3067;&#x30C6;&#x30FC;&#x30D6;&#x30EB;&#x3092;&#x5168;&#x3066;&#x3001;&#x307E;&#x305F;&#x306F;&#x6B63;&#x898F;&#x8868;&#x73FE;&#x3067;&#x6307;&#x5B9A;&#x3057;&#x3066;&#x524A;&#x9664;&#x3059;&#x308B;&#x65B9;&#x6CD5; - &#x30B9;&#x30BF;&#x30C3;&#x30AF;&#x30FB;&#x30AA;&#x30FC;&#x30D0;&#x30FC;&#x30D5;&#x30ED;&#x30FC;</a></p> turgure キャッシュについてのあれこれ hatenablog://entry/98012380859465118 2019-02-06T14:50:10+09:00 2019-02-06T14:51:49+09:00 弊プロジェクトでは3種類のキャッシュを利用していて、違いがわからなかったので調査したものをまとめました memcached key-value store型のキャッシュ 主にRDBMSにおけるクエリの結果などを保存しておく 揮発性が高い? from: http://gihyo.jp/dev/feature/01/memcached/0001 キャッシュクリア方法 /etc/init.d/memcached restart CDN(Content Delivery Network) 様々なところにサーバを配置して、ネットワーク的に(≒物理的に)距離が近いサーバからキャッシュを取得する これによっ… <p>弊プロジェクトでは3種類のキャッシュを利用していて、違いがわからなかったので調査したものをまとめました</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/memcached">memcached</a></h1> <p>key-<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a> store型のキャッシュ<br/> 主に<a class="keyword" href="http://d.hatena.ne.jp/keyword/RDBMS">RDBMS</a>におけるクエリの結果などを保存しておく<br/> 揮発性が高い?</p> <p><img src="https://image.gihyo.co.jp/assets/images/dev/feature/01/memcached/0001/0001-01.png" alt="0001-01.png" /><br/> from: <a href="http://gihyo.jp/dev/feature/01/memcached/0001">http://gihyo.jp/dev/feature/01/memcached/0001</a></p> <h3>キャッシュクリア方法</h3> <pre class="code lang-sh" data-lang="sh" data-unlink>/etc/init.d/memcached <span class="synStatement">restart</span> </pre> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/CDN">CDN</a>(Content Delivery Network)</h1> <p>様々なところにサーバを配置して、ネットワーク的に(≒物理的に)距離が近いサーバからキャッシュを取得する<br/> これによって、</p> <ul> <li>地域によってレスポンスが遅くなるような状況を防ぐ</li> <li>処理の負荷分散</li> </ul> <p>を実現する</p> <h3>キャッシュクリア方法</h3> <p>webページで操作して削除<br/> 弊pjでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/curl">curl</a>コマンドを叩くことで<a class="keyword" href="http://d.hatena.ne.jp/keyword/cui">cui</a>上で操作している</p> <h1>APCU(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Alternative">Alternative</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Php">Php</a> Cache(<a class="keyword" href="http://d.hatena.ne.jp/keyword/APC">APC</a>) User cache)</h1> <p><a href="https://qiita.com/nntsugu/items/63099b829befb57859d7">APCがAPCuとZend OPcacheに取って代わられたワケ - Qiita</a><br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>のキャッシュ<br/> webサーバ(<a class="keyword" href="http://d.hatena.ne.jp/keyword/apache">apache</a>, nginxなど)にキャッシュが保存される</p> <h3>キャッシュクリア方法</h3> <p>gracefulをする</p> <pre class="code lang-sh" data-lang="sh" data-unlink><span class="synComment"># apache</span> service httpd graceful /etc/init.d/httpd graceful <span class="synComment"># nginx</span> service nginx graceful /etc/init.d/nginx graceful </pre> <p><a href="https://qiita.com/ngyuki/items/fdeae87cee5d60f6698e">「/etc/init.d/xxx start」と「service xxx start」の違い</a><br/> <code>service xxx</code>を使ったほうがよさげ?</p> <p>APCUはwebサーバ上にあるので、<code>restart</code>すると一時的にサーバに接続できなくなってしまう<br/> なので、かわりに<code>graceful</code>を利用する</p> <h4>※gracefulの仕組み</h4> <p>すべての子プロセスの処理後に、再起動命令を走らせる<br/> その後、親プロセスは設定ファイルの再読込を実行<br/> これにより、サーバーがダウンすることなく、あたかも生きたまま設定の反映ができるようになる</p> <h1>補足:<a class="keyword" href="http://d.hatena.ne.jp/keyword/apache">apache</a>, nginx </h1> <p>webサーバの<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSS">OSS</a><br/> webサーバとして利用するマシンにインストールして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A5%B9%A5%C6%A5%A3%A5%F3%A5%B0">ホスティング</a>を行う<br/> 昔は<a class="keyword" href="http://d.hatena.ne.jp/keyword/apache">apache</a>が主流だったが、最近(2016くらいから?)はnginxも主流になりつつある<br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/apache">apache</a>, nginxを再起動したら、apucキャッシュは削除される</p> <p><a href="https://qiita.com/kamihork/items/49e2a363da7d840a4149">ApacheとNginxについて比較 - Qiita</a></p> turgure twitterのOAuth認証ではまったこと hatenablog://entry/10257846132623368809 2018-09-07T22:28:09+09:00 2018-09-07T22:28:09+09:00 最近twitter APIを使ってOAuth認証しようとしたら、以下のようなエラーが出てハマった。 Callback URL not approved for this client application. これは、callback URLが間違ってるよみたいなこと 2018.6.13以降はちゃんと対応させないとだめになった なので、アプリ登録したページから、以下のcallback URLを設定 https://developer.twitter.com/en/apps その後、ソースを変更 twitter.getOAuthRequestToken("app://"); AndroidMan… <p>最近<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/OAuth%C7%A7%BE%DA">OAuth認証</a>しようとしたら、以下のようなエラーが出てハマった。</p> <pre class="code" data-lang="" data-unlink>Callback URL not approved for this client application.</pre> <p>これは、callback URLが間違ってるよみたいなこと<br/> 2018.6.13以降はちゃんと対応させないとだめになった<br/> なので、アプリ登録したページから、以下のcallback URLを設定<br/> <a href="https://developer.twitter.com/en/apps">https://developer.twitter.com/en/apps</a></p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180907/20180907222004.png" alt="f:id:turgure:20180907222004p:plain" title="f:id:turgure:20180907222004p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>その後、ソースを変更</p> <pre class="code lang-java" data-lang="java" data-unlink>twitter.getOAuthRequestToken(<span class="synConstant">&quot;app://&quot;</span>); </pre> <p><code>AndroidManifest.xml</code>も設定してたら変更</p> <pre class="code" data-lang="" data-unlink>&lt;intent-filter&gt; &lt;action android:name=&#34;android.intent.action.VIEW&#34; /&gt; &lt;category android:name=&#34;android.intent.category.DEFAULT&#34; /&gt; &lt;category android:name=&#34;android.intent.category.BROWSABLE&#34; /&gt; &lt;data android:scheme=&#34;app&#34; /&gt; &lt;/intent-filter&gt;</pre> <p>これでヨシ</p> <p><br /></p> <p>参考URL</p> <ul> <li><a href="https://qiita.com/non0311/items/48a6b25097d1783eab23">Twitter&#x306E;API&#x3067;callbackURL&#x3092;&#x30C1;&#x30A7;&#x30C3;&#x30AF;&#x3059;&#x308B;&#x3088;&#x3046;&#x306B;&#x306A;&#x3063;&#x305F;</a></li> <li><a href="https://qiita.com/gyamoto/items/f8473f2274e27f33987a">Android&#x3067;Deep Link&#x3092;&#x4F7F;&#x3046;&#x3068;&#x304D;&#x306E;intent-filter&#x3068;data&#x306E;&#x66F8;&#x304D;&#x65B9;</a></li> </ul> turgure Google Cloud Messaging(GCM)からFirebase Cloud Messaging(FCM)への移行(android) hatenablog://entry/10257846132620192697 2018-09-04T18:43:22+09:00 2018-09-04T18:53:07+09:00 GCM/FCMとは GCMとは、android端末のpush通知をサポートするクラウドサービスのこと しかし、GCMは2019.4.11でサポートが完全に停止する そのかわり、googleは新しくFCMの利用を呼びかけている またFCMはandroidだけでなく、iOSもサポート対応のクロスプラットフォームである 移行のきっかけ なぜ移行しようという話になったのかだが、サポート終了するっていうのは調べ始めてから発覚したこと。 そもそもの理由としては、targetSdkVersion 26以上じゃないとだめだよっていうgoogleのお達しがあったので、バージョンあげたことが発端だった。 2018… <h1>GCM/FCMとは</h1> <p>GCMとは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/android">android</a>端末のpush通知をサポートする<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%A6%A5%C9">クラウド</a>サービスのこと<br/> しかし、GCMは2019.4.11でサポートが完全に停止する</p> <p>そのかわり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>は新しくFCMの利用を呼びかけている<br/> またFCMは<a class="keyword" href="http://d.hatena.ne.jp/keyword/android">android</a>だけでなく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>もサポート対応の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%ED%A5%B9%A5%D7%A5%E9%A5%C3%A5%C8%A5%D5%A5%A9%A1%BC%A5%E0">クロスプラットフォーム</a>である</p> <h1>移行のきっかけ</h1> <p>なぜ移行しようという話になったのかだが、サポート終了するっていうのは調べ始めてから発覚したこと。<br/> そもそもの理由としては、targetSdkVersion 26以上じゃないとだめだよっていう<a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>のお達しがあったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A1%BC">バー</a>ジョンあげたことが発端だった。<br/> <a href="https://qiita.com/oya-t/items/d52e97aea20b2f20ad44">2018&#x5E74;8&#x6708;&#x304B;&#x3089;targetSdkVersion&#x3092;API&#x30EC;&#x30D9;&#x30EB;26&#xFF08;Android 8.0&#xFF09;&#x4EE5;&#x4E0A;&#x306B;&#x3059;&#x308B;&#x5FC5;&#x8981;&#x304C;&#x3042;&#x308B;</a></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A1%BC">バー</a>ジョンアップをしたところ、バックグラウンドでの通知が届かなくなってしまったのである。<br/> アプリが開いている状態なら問題なく通知が届くのだが、アプリを終了すると以下のようにエラーがでて落ちてしまっていた。</p> <div style="text-align: center;"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180904/20180904182731.png" alt="f:id:turgure:20180904182731p:plain:w300" title="f:id:turgure:20180904182731p:plain:w300" class="hatena-fotolife" style="width:300px" itemprop="image"></span> </div> <p>そしてログもめっちゃ吐かれてた</p> <pre class="code" data-lang="" data-unlink>09-03 16:30:23.564 27698-27698/your-package E/AndroidRuntime: FATAL EXCEPTION: main Process: your-package, PID: 27698 java.lang.RuntimeException: Unable to start receiver com.google.android.gcm.GCMBroadcastReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=your-package cmp=your-package/.GCMIntentService (has extras) }: app is in background uid UidRecord{a11f8da u0a520 RCVR idle procs:1 seq(0,0,0)} at android.app.ActivityThread.handleReceiver(ActivityThread.java:3267) ...</pre> <p>社内の人に相談したところ、「FCM使ってますけどそんなの見たことないですよ?」って言われたので、FCMに移行することにした。</p> <h1>移行の手順</h1> <p>基本的には以下のURLの通りに進めれば問題ない<br/> <a href="https://developers.google.com/cloud-messaging/android/android-migrate-fcm">Migrate a GCM Client App for Android to Firebase Cloud Messaging &nbsp;|&nbsp; Cloud Messaging &nbsp;|&nbsp; Google Developers</a></p> <p>1 . 以下のURLからfirebaseプロジェクトの作成<br/>   <a href="https://console.firebase.google.com">https://console.firebase.google.com</a></p> <p><code>google-services.json</code>をプロジェクトに追加する必要があるため、その手順</p> <p>1.1. 対象のプラットフォームを選ぶ(この記事では<a class="keyword" href="http://d.hatena.ne.jp/keyword/android">android</a>を扱う)<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180904/20180904174238.png" alt="f:id:turgure:20180904174238p:plain:w400" title="f:id:turgure:20180904174238p:plain:w400" class="hatena-fotolife" style="width:400px" itemprop="image"></span></p> <p>1.2. 必要事項の入力<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180904/20180904171149.png" alt="f:id:turgure:20180904171149p:plain:w400" title="f:id:turgure:20180904171149p:plain:w400" class="hatena-fotolife" style="width:400px" itemprop="image"></span></p> <p>証明書の確認は以下のように行う</p> <pre class="code" data-lang="" data-unlink>$ keytool -v -list -alias androiddebugkey -keystore ~/.android/debug.keystore $ keytool -v -list -alias &lt;your-key-name&gt; -keystore &lt;path-to-production-keystore&gt;</pre> <p><a href="https://developers.google.com/android/guides/client-auth">https://developers.google.com/android/guides/client-auth</a></p> <p>1.3. <code>google-services.json</code>をダウンロード<br/>   <code>app/</code>直下に配置する<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180904/20180904171615.png" alt="f:id:turgure:20180904171615p:plain:w400" title="f:id:turgure:20180904171615p:plain:w400" class="hatena-fotolife" style="width:400px" itemprop="image"></span></p> <p>1.4. それぞれのbuild.gradeに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%C9%B5%AD">追記</a>してsync<br/>   最新の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A1%BC">バー</a>ジョンがあれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/android%20studio">android studio</a>が教えてくれるのでそれに合わせる<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180904/20180904171857.png" alt="f:id:turgure:20180904171857p:plain:w400" title="f:id:turgure:20180904171857p:plain:w400" class="hatena-fotolife" style="width:400px" itemprop="image"></span></p> <p>1.5. アプリを実行、同期確認<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180904/20180904172228.png" alt="f:id:turgure:20180904172228p:plain:w400" title="f:id:turgure:20180904172228p:plain:w400" class="hatena-fotolife" style="width:400px" itemprop="image"></span></p> <p>2 . build.gradleの変更<br/> 3 . AndroidManifest.<a class="keyword" href="http://d.hatena.ne.jp/keyword/xml">xml</a>の変更</p> <p>自分が行ったものをdiff形式でぺたり</p> <p><script src="https://gist.github.com/90bbfe52b1d77587b31a083b3f70dab8.js"> </script></p> <p><script src="https://gist.github.com/a2454155f5c6df2c3684c54c8d45c243.js"> </script></p> <p><script src="https://gist.github.com/54d4024c4c516ca7340447b385908fd5.js"> </script></p> <p>4 . server endpointsの変更</p> <pre class="code" data-lang="" data-unlink>https://android.googleapis.com/gcm/send</pre> <p>を</p> <pre class="code" data-lang="" data-unlink>http://fcm.googleapis.com/fcm/send</pre> <p>に変更</p> <p>5 . その他設定<br/>   それぞれの実装状況に合わせて対応部分を修正</p> <p>自分の所属プロジェクトでは、真ん中の<br/> <a href="https://developers.google.com/cloud-messaging/android/android-migrate-gcmlistener">Optional: migrate your GcmListenerService</a><br/> が修正対象でした</p> <p>簡単に説明すると、AndroidManifest.<a class="keyword" href="http://d.hatena.ne.jp/keyword/xml">xml</a>の変更と、serviceの変更</p> <p>remoteMessageからデータを取得するとき、一般的な記事では<code>getNotification()</code>とかを使ったら値がnullになっていた<br/> そこで、従来どおりintent経由で取得する方法として、<code>toIntent()</code>というまさに求めていた機能があったのでこれを利用<br/> (あとで確認したら<code>getData()</code>の方にはデータが入ってたのでこっち使ったほうがいいかも?)</p> <pre class="code lang-java" data-lang="java" data-unlink>Bundle extras = intent.getExtras(); </pre> <p>を</p> <pre class="code lang-java" data-lang="java" data-unlink>Bundle extras = remoteMessage.toIntent().getExtras(); </pre> <p><script src="https://gist.github.com/fbad45e1810fb9347c56059b04317377.js"> </script></p> <p><script src="https://gist.github.com/0f78b4cd0449b7661a6dfde68d4e28ae.js"> </script></p> <p>認証まわりは<a class="keyword" href="http://d.hatena.ne.jp/keyword/PHP">PHP</a>を使ってたので元から特に書いてなかった</p> <p>これで無事に今までどおり通知が届くようになった</p> <p><br /></p> <p>参考URL</p> <ul> <li><a href="https://www.notice.co.jp/archives/2554">&#x30A2;&#x30F3;&#x30C9;&#x30ED;&#x30A4;&#x30C9;&#x30A2;&#x30D7;&#x30EA;&#x304B;&#x3089;Google Cloud Messaging&#x3092;&#x4F7F;&#x3046;&#x65B9;&#x6CD5;&#xFF08;&#x7B2C;1&#x56DE;&#xFF09; &laquo; &#x5927;&#x962A;&#x306E;&#x30A2;&#x30F3;&#x30C9;&#x30ED;&#x30A4;&#x30C9;/iOS&#xFF65; Web&#x30A2;&#x30D7;&#x30EA;&#x958B;&#x767A;&#x4F1A;&#x793E; &#x30CE;&#x30FC;&#x30C6;&#x30A3;&#x30B9;</a></li> <li><a href="http://blog.kotemaru.org/2016/05/28/android-fcm-sample.html">Android&#x306E;&#x65B0;&#x30D7;&#x30C3;&#x30B7;&#x30E5;&#x901A;&#x77E5;FCM&#x3078;&#x306E;&#x79FB;&#x884C; : &#x6642;&#x3005;&#x3001;&#x5931;&#x696D;SE&#x306E;&#x958B;&#x767A;&#x65E5;&#x8A8C;</a></li> <li><a href="https://qiita.com/Sert/items/1fbdbf68dd087201a57b">Android Firebase Authentication (Google&#x8A8D;&#x8A3C;) &#x30E1;&#x30E2;</a></li> </ul> turgure claspを使ったGoogle App Scriptのローカル開発・自動コンパイル hatenablog://entry/10257846132612695262 2018-08-20T17:47:23+09:00 2018-12-18T12:05:25+09:00 claspとは claspは、Google App Script(GAS)をローカル環境で開発するためのgoogle製ツールである ローカルで作業できる一番のメリットは、やはりgitとの連携が可能になることだろう しかし、gasはES6には対応しておらず、イマドキのjsのコーディングスタイルは使えない そこで本記事では、本ブログの前回の記事を利用して、 ES6対応のjsコードで開発 babelを使ってECMAScript5へコンパイル claspを使ってコンパイルしたファイルをgas上のスクリプトと同期(push) をすべて自動で行えるようにする claspのセットアップ 1 . claspの… <h1>claspとは</h1> <p><a href="https://github.com/google/clasp">clasp</a>は、<a href="https://developers.google.com/apps-script">Google App Script(GAS)</a>をローカル環境で開発するための<a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>製ツールである<br/> ローカルで作業できる一番のメリットは、やはりgitとの連携が可能になることだろう</p> <p>しかし、gasはES6には対応しておらず、イマドキのjsのコーディングスタイルは使えない<br/> そこで本記事では、<a href="http://turgure.hatenablog.com/entry/2018/08/17/190128">&#x672C;&#x30D6;&#x30ED;&#x30B0;&#x306E;&#x524D;&#x56DE;&#x306E;&#x8A18;&#x4E8B;</a>を利用して、</p> <ol> <li>ES6対応のjsコードで開発</li> <li>babelを使ってECMAScript5へ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a></li> <li>claspを使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>したファイルをgas上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>と同期(push)</li> </ol> <p>をすべて自動で行えるようにする</p> <h1>claspのセットアップ</h1> <p>1 . claspのインストール</p> <pre class="code" data-lang="" data-unlink>npm install -g @google/clasp</pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/google">google</a>アカウントをプロジェクトごとに使い分ける場合はローカルにインストールし、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>のscriptにloginみたいなのを作ればいいと思う</p> <p>2 . 以下のサイトで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%20Apps">Google Apps</a> Script <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>をオンにする<br/>   <a href="https://script.google.com/home/usersettings">https://script.google.com/home/usersettings</a></p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180820/20180820145215.png" alt="f:id:turgure:20180820145215p:plain" title="f:id:turgure:20180820145215p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>3 . ログインする</p> <pre class="code" data-lang="" data-unlink>clasp login</pre> <p>ここまでの作業は最初の一度だけ行えばよい</p> <h1>ローカル環境の構築</h1> <h3>claspの設定</h3> <ul> <li>gasや<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>を新規作成する場合</li> </ul> <pre class="code" data-lang="" data-unlink>clasp create &lt;project_name&gt;</pre> <p>とすれば、gasが連携したアカウントの<a class="keyword" href="http://d.hatena.ne.jp/keyword/google%20drive">google drive</a>上に作成され、ローカルに<code>.clasp.json</code>と<code>appsscript.json</code>の2つのファイルが生成される</p> <p>それぞれ以下のようなファイルになっている</p> <p><script src="https://gist.github.com/098b712752cc77554ba8a19f721b12ce.js"> </script> <script src="https://gist.github.com/6d91a624954bc44586625420dfe1d1b6.js"> </script></p> <p><br /></p> <ul> <li>gasや<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%D7%A5%EC%A5%C3%A5%C9%A5%B7%A1%BC%A5%C8">スプレッドシート</a>がすでに存在する場合</li> </ul> <p>.clasp.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>に記述するscript idを取得し、手動で作成する<br/> idの場所は<br/>   ・ gasのURL<br/>   ・ ファイル > プロジェクトのプロパティの「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>ID」<br/> のいずれかから取得する(どちらも同じid)</p> <p>前まではプロジェクトキーを使っていたが、現在は変わったらしい<br/> 古いプロジェクトだとurlがプロジェクトキーのものになっていて使えないので要注意</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180820/20180820155836.png" alt="f:id:turgure:20180820155836p:plain" title="f:id:turgure:20180820155836p:plain" class="hatena-fotolife" itemprop="image"></span><br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180820/20180820170546.png" alt="f:id:turgure:20180820170546p:plain" title="f:id:turgure:20180820170546p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>そして</p> <pre class="code" data-lang="" data-unlink>clasp pull</pre> <p>を実行することで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/google%20drive">google drive</a>上のgasファイルをローカルに同期することができる</p> <h3>.claspignoreの追加</h3> <p>基本的に、ローカルのファイルをgas上に同期(push)しようとすると、すべてのファイルが同期されてしまう<br/> そのため、<code>.claspignore</code>ファイルを作成することで、どのファイルをpushするかを決める(<code>.gitignore</code>と同じ役割)<br/> このとき、pushするファイルには<code>appsscript.json</code>が必ず含まれていなくてはいけない<br/> 以下のようなファイルを作成するとよい(main.jsはgas上に同期するファイル)</p> <p><script src="https://gist.github.com/332f9f828a7686de4cef6bea3ab426ef.js"> </script></p> <p><b>(余談)</b><br/> 本来なら、<code>.claspignore</code>など作らずとも、<code>.clasp.json</code>のプロパティにrootDirなるものが存在し、それを指定すれば自動的にその<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ内のファイルのみをターゲットとしてpushするファイルを決めてくれるはず、だった。<br/> しかし、<code>appsscript.json</code>がどう頑張ってもignoreされてしまい、2018/08/20現在まだその問題が続いている</p> <pre class="code" data-lang="" data-unlink>$ clasp status Not ignored files: └─ dist/main.js Ignored files: └─ dist/appsscript.json</pre> <p>なので、今は諦めて<code>.claspignore</code>を使おう<br/> <a href="https://github.com/google/clasp/issues/281">Command Failed: clasp push &middot; Issue #281 &middot; google/clasp &middot; GitHub</a></p> <h3>babelの設定</h3> <p><a href="http://turgure.hatenablog.com/entry/2018/08/17/190128">&#x524D;&#x56DE;&#x306E;&#x8A18;&#x4E8B;</a>を参考に構築<br/> そして、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>を以下のように書き換える</p> <pre class="code lang-json" data-lang="json" data-unlink>&quot;<span class="synStatement">scripts</span>&quot;: <span class="synSpecial">{</span> &quot;<span class="synStatement">start</span>&quot;: &quot;<span class="synConstant">watch 'npm run build' src/</span>&quot;, &quot;<span class="synStatement">build</span>&quot;: &quot;<span class="synConstant">node index.js &amp;&amp; npm run push</span>&quot;, &quot;<span class="synStatement">push</span>&quot;: &quot;<span class="synConstant">clasp push</span>&quot; <span class="synSpecial">}</span> </pre> <p>build後に<code>clasp push</code>を実行するコマンドを追加</p> <p><br /></p> <p>これで、前回同様</p> <pre class="code" data-lang="" data-unlink>$ npm start</pre> <p>を実行すれば、自動的にgas上のファイルの変更まで行うことができる</p> <p>gasのファイルを変更しても、ブラウザ更新しないと反映されないので一瞬ドキッとする…<br/> なにか組み合わせてできないものだろうか</p> <hr /> <p>追記:20181218</p> <p>20181218時点でclaspの最新版が <code>1.7.0</code>だったので、それに移行した。</p> <pre class="code" data-lang="" data-unlink>$ npm info @google/clasp versions [ &#39;1.0.0&#39;, &#39;1.0.1&#39;, &#39;1.0.2&#39;, &#39;1.0.3&#39;, &#39;1.0.4&#39;, &#39;1.0.5&#39;, &#39;1.0.6&#39;, &#39;1.0.7&#39;, &#39;1.1.0&#39;, &#39;1.1.1&#39;, &#39;1.1.2&#39;, &#39;1.1.3&#39;, &#39;1.1.4&#39;, &#39;1.1.5&#39;, &#39;1.3.0&#39;, &#39;1.3.1&#39;, &#39;1.3.2&#39;, &#39;1.3.3&#39;, &#39;1.4.0&#39;, &#39;1.4.1&#39;, &#39;1.5.0&#39;, &#39;1.5.1&#39;, &#39;1.5.2&#39;, &#39;1.5.3&#39;, &#39;1.6.0&#39;, &#39;1.6.1&#39;, &#39;1.6.2&#39;, &#39;1.6.3&#39;, &#39;1.7.0&#39; ] $ npm install @google/clasp@1.7.0 -g /usr/local/bin/clasp -&gt; /usr/local/lib/node_modules/@google/clasp/src/index.js + @google/clasp@1.7.0 added 16 packages from 11 contributors, removed 4 packages and updated 32 packages in 8.627s $ npm list --depth=0 -g /usr/local/lib ├── @google/clasp@1.7.0 ├── npm@6.4.0 ├── npm-check-updates@2.15.0 └── pure-prompt@1.7.0</pre> <p>また、このときに、このまま使おうとすると、以下のエラーが発生する</p> <pre class="code" data-lang="" data-unlink>$ clasp push Error retrieving access token: TypeError: Cannot read property &#39;expiry_date&#39; of undefined</pre> <p>そのため、再度ログインし直す</p> <pre class="code" data-lang="" data-unlink>$ clasp logout $ clasp login</pre> <p>1.7.0に移行したことで、 <code>.clasp.json</code>のrootDirを指定してpushする<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを選べるようになった。</p> <p><br /></p> <p>参考サイト</p> <ul> <li><a href="https://qiita.com/howdy39/items/0e799a9bfc1d3bccf6e5">Google Apps Script &#x3092;&#x30ED;&#x30FC;&#x30AB;&#x30EB;&#x74B0;&#x5883;&#x3067;&#x5FEB;&#x9069;&#x306B;&#x958B;&#x767A;&#x3059;&#x308B;&#x305F;&#x3081;&#x306E;&#x30C6;&#x30F3;&#x30D7;&#x30EC;&#x30FC;&#x30C8;&#x3092;&#x4F5C;&#x308A;&#x307E;&#x3057;&#x305F; - Qiita</a></li> <li><a href="https://qiita.com/suin/items/b264092eab3ce553f16a">5&#x5206;&#x3067;&#x4F5C;&#x308B;clasp&#x3092;&#x4F7F;&#x3063;&#x305F;Google Apps Script&#x306E;&#x958B;&#x767A;&#x74B0;&#x5883; - Qiita</a></li> <li><a href="https://qiita.com/HeRo/items/4e65dcc82783b2766c03">GAS &#x306E;Google&#x8B39;&#x88FD;CLI&#x30C4;&#x30FC;&#x30EB; clasp - Qiita</a></li> </ul> turgure babelを使ったjavascriptの自動コンパイル hatenablog://entry/10257846132611718969 2018-08-17T19:01:28+09:00 2018-08-27T15:29:57+09:00 Babel ECMAScript2015 (ES6)やECMAScript7などで書かれたソースコードを一般的なブラウザがサポートしているECMAScript5の形式に出力することができます。 つまり、新しい言語仕様を昔の仕様に落としてトランスコンパイルしてくれるコンパイラ セットアップ babel v6.0以降、pluginまたはpresetの指定が必要になっている 基本的には.babelrcというファイルに記述するのだが、設定が少ないため、package.jsonに合わせて記述する "babel": { "presets": [ "env" ] } envというのは、コンパイル環境を自動で… <h1>Babel</h1> <blockquote><p>ECMAScript2015 (ES6)やECMAScript7などで書かれた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を一般的なブラウザがサポートしているECMAScript5の形式に出力することができます。</p></blockquote> <p>つまり、新しい言語仕様を昔の仕様に落としてトランス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>してくれる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a></p> <h1>セットアップ</h1> <p>babel v6.0以降、pluginまたはpresetの指定が必要になっている<br/> 基本的には<code>.babelrc</code>というファイルに記述するのだが、設定が少ないため、<code>package.json</code>に合わせて記述する</p> <pre class="code lang-json" data-lang="json" data-unlink>&quot;<span class="synStatement">babel</span>&quot;: <span class="synSpecial">{</span> &quot;<span class="synStatement">presets</span>&quot;: <span class="synSpecial">[</span> &quot;<span class="synConstant">env</span>&quot; <span class="synSpecial">]</span> <span class="synSpecial">}</span> </pre> <p><code>env</code>というのは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>環境を自動で決定してくれるすぐれもの</p> <ul> <li><a href="https://www.key-p.com/blog/staff/archives/105449">babel-preset-env&#x3067;&#x74B0;&#x5883;&#x306B;&#x5408;&#x308F;&#x305B;&#x3066;JavaScript&#x3092;&#x30C8;&#x30E9;&#x30F3;&#x30B9;&#x30D1;&#x30A4;&#x30EB;&#x3059;&#x308B; | KEYPOINT &ndash; &#x30AD;&#x30FC;&#x30FB;&#x30DD;&#x30A4;&#x30F3;&#x30C8;&#x682A;&#x5F0F;&#x4F1A;&#x793E; &#x958B;&#x767A;&#x65E5;&#x8A8C;</a></li> <li><a href="https://babeljs.io/docs/en/babel-preset-env#docsNav">babel-preset-env &middot; Babel</a></li> </ul> <p><strong> 【<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%C9%B5%AD">追記</a> 20180827】 </strong><br/> <code>index.js</code>(下記参照)にenvの設定をして、そこを参照していたので、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>に追加する必要はありませんでした。</p> <hr /> <p>あわせて、次の2つのパッケージをインストール</p> <pre class="code" data-lang="" data-unlink>npm install babel-cli npm install babel-preset-env</pre> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>の作成</h1> <p>実際に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>するためには、babelコマンドが必要になってくる<br/> それをjs側で管理して実行できるようにする<br/> ファイル名は、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>のmainタグで管理されているファイル名に設定(デフォルトは<code>index.js</code>)</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synStatement">const</span> babel = require(<span class="synConstant">'babel-core'</span>) <span class="synStatement">const</span> fs = require(<span class="synConstant">'fs'</span>) <span class="synStatement">const</span> srcFile = <span class="synConstant">'src/test.js'</span> <span class="synStatement">const</span> distFile = <span class="synConstant">'dist/test.js'</span> <span class="synStatement">const</span> options = <span class="synIdentifier">{</span><span class="synConstant">&quot;presets&quot;</span>: <span class="synIdentifier">[</span><span class="synConstant">&quot;env&quot;</span><span class="synIdentifier">]}</span> <span class="synStatement">const</span> code = fs.readFileSync(srcFile, <span class="synConstant">'utf-8'</span>) <span class="synStatement">const</span> newCode = babel.transform(code, options).code fs.writeFileSync(distFile, newCode) console.log(<span class="synConstant">'babel build finished!'</span>) </pre> <p>サンプルとして、ここでは<br/> <code>src/test.js</code>の内容を、<br/> <code>dist/test.js</code>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>して出力するようにしている</p> <p>例えば、</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synStatement">class</span> Hoge <span class="synIdentifier">{</span> constructor() <span class="synIdentifier">{</span> <span class="synIdentifier">this</span>.x = 3; <span class="synIdentifier">this</span>.y = 2; <span class="synIdentifier">}</span> add() <span class="synIdentifier">{</span> <span class="synStatement">return</span> <span class="synIdentifier">this</span>.x + <span class="synIdentifier">this</span>.y; <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> <span class="synStatement">const</span> exp = (x, y) =&gt; x ** y; <span class="synStatement">const</span> hoge = <span class="synStatement">new</span> Hoge(); console.log(exp(hoge.x, hoge.y)); console.log(hoge.add()); </pre> <p>を変換する。<br/> <code>$ node index.js</code>を実行すると、</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synConstant">&quot;use strict&quot;</span>; <span class="synIdentifier">var</span> _createClass = <span class="synIdentifier">function</span> () <span class="synIdentifier">{</span> <span class="synIdentifier">function</span> defineProperties(target, props) <span class="synIdentifier">{</span> <span class="synStatement">for</span> (<span class="synIdentifier">var</span> i = 0; i &lt; props.length; i++) <span class="synIdentifier">{</span> <span class="synIdentifier">var</span> descriptor = props<span class="synIdentifier">[</span>i<span class="synIdentifier">]</span>; descriptor.enumerable = descriptor.enumerable || <span class="synConstant">false</span>; descriptor.configurable = <span class="synConstant">true</span>; <span class="synStatement">if</span> (<span class="synConstant">&quot;value&quot;</span> <span class="synStatement">in</span> descriptor) descriptor.writable = <span class="synConstant">true</span>; <span class="synType">Object</span>.defineProperty(target, descriptor.key, descriptor); <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> <span class="synStatement">return</span> <span class="synIdentifier">function</span> (Constructor, protoProps, staticProps) <span class="synIdentifier">{</span> <span class="synStatement">if</span> (protoProps) defineProperties(Constructor.prototype, protoProps); <span class="synStatement">if</span> (staticProps) defineProperties(Constructor, staticProps); <span class="synStatement">return</span> Constructor; <span class="synIdentifier">}</span>; <span class="synIdentifier">}</span>(); <span class="synIdentifier">function</span> _classCallCheck(instance, Constructor) <span class="synIdentifier">{</span> <span class="synStatement">if</span> (!(instance <span class="synStatement">instanceof</span> Constructor)) <span class="synIdentifier">{</span> <span class="synStatement">throw</span> <span class="synStatement">new</span> TypeError(<span class="synConstant">&quot;Cannot call a class as a function&quot;</span>); <span class="synIdentifier">}</span> <span class="synIdentifier">}</span> <span class="synIdentifier">var</span> Hoge = <span class="synIdentifier">function</span> () <span class="synIdentifier">{</span> <span class="synIdentifier">function</span> Hoge() <span class="synIdentifier">{</span> _classCallCheck(<span class="synIdentifier">this</span>, Hoge); <span class="synIdentifier">this</span>.x = 3; <span class="synIdentifier">this</span>.y = 2; <span class="synIdentifier">}</span> _createClass(Hoge, <span class="synIdentifier">[{</span> key: <span class="synConstant">&quot;add&quot;</span>, value: <span class="synIdentifier">function</span> add() <span class="synIdentifier">{</span> <span class="synStatement">return</span> <span class="synIdentifier">this</span>.x + <span class="synIdentifier">this</span>.y; <span class="synIdentifier">}</span> <span class="synIdentifier">}]</span>); <span class="synStatement">return</span> Hoge; <span class="synIdentifier">}</span>(); <span class="synIdentifier">var</span> exp = <span class="synIdentifier">function</span> exp(x, y) <span class="synIdentifier">{</span> <span class="synStatement">return</span> Math.pow(x, y); <span class="synIdentifier">}</span>; <span class="synIdentifier">var</span> hoge = <span class="synStatement">new</span> Hoge(); console.log(exp(hoge.x, hoge.y)); console.log(hoge.add()); </pre> <p>になる。ちゃんと実行もできる</p> <h1>自動<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>環境の構築</h1> <p>今のままだと、変更・保存して毎回<code>node index.js</code>を叩かなくてはいけない<br/> そのため、ファイルを変更したら自動で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>してくれるようにする<br/> gulpやgruntは使わない</p> <p>まず、ファイルの変更を監視する<a class="keyword" href="http://d.hatena.ne.jp/keyword/watch">watch</a>というパッケージがあるので、それをインストールする</p> <pre class="code" data-lang="" data-unlink>npm install watch</pre> <p>次に、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>のscriptを変更する</p> <pre class="code lang-json" data-lang="json" data-unlink>&quot;<span class="synStatement">scripts</span>&quot;: <span class="synSpecial">{</span> &quot;<span class="synStatement">start</span>&quot;: &quot;<span class="synConstant">watch 'npm run build' src/</span>&quot;, &quot;<span class="synStatement">build</span>&quot;: &quot;<span class="synConstant">node index.js</span>&quot; <span class="synSpecial">}</span> </pre> <p>これは、<code>src/</code>下のファイルが変更されたら、<code>npm run build</code>を実行するということ<br/> そして、buildには、先程も実行していた<code>node index.js</code>を記述している</p> <p>これで、</p> <pre class="code" data-lang="" data-unlink>$ npm start</pre> <p>を実行するだけ<br/> あとは、変更を加えるたびに自動で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>してくれるようになる</p> <p><br /></p> <p>参考サイト</p> <ul> <li><a href="https://oshiro-lab.com/blog/archives/46">2018&#x5E74;&#x306E;Javascript&#x8003;&#x5BDF; &ndash; &#x30AA;&#x30AA;&#x30B7;&#x30ED;&#x30DE;&#x30F3;&#x306E;&#x3054;&#x3063;&#x305F;&#x716E;</a></li> <li><a href="https://html5experts.jp/kyo_ago/16979/">Babel&#x3067;&#x59CB;&#x3081;&#x308B;&#xFF01;&#x30E2;&#x30C0;&#x30F3;JavaScript&#x958B;&#x767A; | HTML5Experts.jp</a></li> </ul> turgure Node.jsとかnpmについての基礎的な部分 hatenablog://entry/10257846132609428132 2018-08-17T17:41:42+09:00 2018-08-17T17:41:42+09:00 Node.jsとは Node.jsとは、サーバサイド用のjavascript シングルスレッドとか、ノンブロッキングI/Oとか、細かいところは省く(というかそこまで理解してない) じゃあクライアントサイド用のjavascriptは?といえば、それが今まで使ってきていたjsなのだろう(多分) サーバサイドで使えるようになったからそういう風に言われているのでは npmとは Node Package Managerの略 Node.jsのパッケージ管理ツール gulpとかbrowserifyとか色々ある Node.jsの機能の利用は、基本的にnpmを通して使うことが多い npmの使い方 $ npm i… <h1>Node.jsとは</h1> <p>Node.jsとは、サーバサイド用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a></p> <p>シングルスレッドとか、ノン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%ED%A5%C3%A5%AD%A5%F3%A5%B0">ブロッキング</a>I/Oとか、細かいところは省く(というかそこまで理解してない)</p> <p>じゃあクライアントサイド用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a>は?といえば、それが今まで使ってきていたjsなのだろう(多分)<br/> サーバサイドで使えるようになったからそういう風に言われているのでは</p> <h1>npmとは</h1> <p>Node Package Managerの略<br/> Node.jsのパッケージ管理ツール</p> <p>gulpとかbrowserifyとか色々ある</p> <p>Node.jsの機能の利用は、基本的にnpmを通して使うことが多い</p> <h2>npmの使い方</h2> <ul> <li><p><code>$ npm init</code><br/>   package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>を作成    <div style="font-size: medium;">    ※ package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>とは<br />     その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ内の環境についての設定ファイル<br />     プロジェクト名や、実行可能コマンド、依存パッケージなどの情報が入っている    </div></p></li> <li><p><code>$ npm install</code><br/>   package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>が存在する場合、その構成に従ったパッケージのインストールを行う</p></li> <li><p><code>$ npm install -g &lt;package_name&gt;</code><br/>   グローバル環境にパッケージをインストール<br/>   インストールしたパッケージ(コマンド)を、どこからでも利用可能になる<br/>   <b>※ よほど汎用的なものでない限り非推奨</b><br/>   <a href="https://qiita.com/Mic-U/items/cd456d6bea72937464f8">&#x50D5;&#x304C;npm install&#x306B;-g&#x3092;&#x3064;&#x3051;&#x306A;&#x3044;&#x308F;&#x3051;</a></p></li> <li><p><code>$ npm install --save/--save-dev/--save-optional &lt;package_name&gt;</code><br/>   ローカル(現在のパスの下)にパッケージをインストール<br/>   node_modulesというフォルダが作成される<br/>   そしてpackage.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>にパッケージ情報が追加される<br/>   一緒にpackage-lock.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>も追加される   <div style="font-size: medium;">   ※ package-lock.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>とは<br />    node_modulesやpackage.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>が変更されたときに自動生成される<br />    パッケージのバージョンログなどが含まれている<br />    開発者間のパッケージバージョンの同一性を担保する<br />    <a href="http://kakts-tec.hatenablog.com/entry/2017/06/05/020037">npm5&#x304B;&#x3089;&#x5C0E;&#x5165;&#x3055;&#x308C;&#x305F; package-lock.json&#x306B;&#x3064;&#x3044;&#x3066; - kakts-log</a>   </div></p></li> </ul> <p>  引数によって、package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>の以下3種類のどこかに割り当てられる<br/>    ・ dependencies<br/>    ・ devDependencies<br/>    ・ optinonalDependencies<br/>   なにも書かない場合はdependencies<br/>   <a href="https://qiita.com/msakamoto_sf/items/a1ae46979a42d6948ebd">&#x52C9;&#x5F37;&#x30E1;&#x30E2;/npm&#x306E;&#x4F7F;&#x3044;&#x65B9;(node.js=v0.11.16, npm=2.3.0, 2015-03&#x6642;&#x70B9;)</a></p> <p>   ・ dependencies<br/>      他の人が共有する際にインストールされる場所<br/>      <code>npm install</code>でdependencies下のパッケージがインストールされる<br/>    ・ devDependencies<br/>      開発者専用のパッケージ群<br/>    ・ optinonalDependencies<br/>      <code>npm install</code>でインストールされるが、失敗しても無視される(らしい)</p> <p>  インストールしたものはjsファイルで利用することができるようになる<br/>   例えば、<code>npm install hoge</code>とした場合、</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synStatement">const</span> hoge = require(<span class="synConstant">'hoge'</span>) </pre> <p>  として利用できる</p> <ul> <li><p><code>$npm uninstall/rm -g &lt;package_name&gt;</code><br/>   グローバルのパッケージのアンインストール</p></li> <li><p><code>$ npm uninstall/rm &lt;package_name&gt;</code><br/>   ローカルのパッケージのアンインストール</p></li> <li><p><code>$ npm update -g &lt;package_name&gt;</code><br/>   グローバルのパッケージのアップデート</p></li> <li><p><code>$ npm update &lt;package_name&gt;</code><br/>   ローカルのパッケージのアップデート</p></li> </ul> <h2>package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>のscript設定</h2> <p>package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>には、scriptタグがある<br/> ここに色々追加することで、コマンド上でパッケージを実行することが可能となる<br/> デフォルトでは、以下のようになっている</p> <pre class="code lang-json" data-lang="json" data-unlink>&quot;<span class="synStatement">scripts</span>&quot;: <span class="synSpecial">{</span> &quot;<span class="synStatement">test</span>&quot;: &quot;<span class="synConstant">echo </span><span class="synSpecial">\&quot;</span><span class="synConstant">Error: no test specified</span><span class="synSpecial">\&quot;</span><span class="synConstant"> &amp;&amp; exit 1</span>&quot; <span class="synSpecial">}</span> </pre> <p>このとき、<code>npm run test --silent</code>を実行することで</p> <pre class="code" data-lang="" data-unlink>Error: no test specified</pre> <p>が表示される(<code>--silent</code>をつけたのはエラーログを出さないため)<br/> <a href="https://qiita.com/frost_star/items/83d58072374d61de9e10">npm run test&#x3059;&#x308B;&#x3068;&#x304D;&#x306F;npm&#x30ED;&#x30B0;&#x3092;&#x5207;&#x3063;&#x305F;&#x307B;&#x3046;&#x304C;&#x3044;&#x3044;</a></p> <p>このscriptタグ内を設定して自由にコマンドを追加できる<br/> また、<code>start</code>コマンドは特殊なコマンドとして登録されており、<code>npm start</code>で実行できるようになっている</p> <p>package.<a class="keyword" href="http://d.hatena.ne.jp/keyword/json">json</a>の詳しい中身について:<a href="https://qiita.com/dondoko-susumu/items/cf252bd6494412ed7847">package.json&#x306E;&#x4E2D;&#x8EAB;&#x3092;&#x7406;&#x89E3;&#x3059;&#x308B;</a></p> <p><br /></p> <p>参考サイト</p> <ul> <li><a href="http://www.atmarkit.co.jp/ait/articles/1501/09/news040.html">&#x3044;&#x307E;&#x3055;&#x3089;&#x805E;&#x3051;&#x306A;&#x3044;Node.js&#x306E;&#x57FA;&#x790E;&#x77E5;&#x8B58;&#x3068;npm&#x3001;Gulp&#x306E;&#x30A4;&#x30F3;&#x30B9;&#x30C8;&#x30FC;&#x30EB; (1/2)&#xFF1A;MEAN&#x30B9;&#x30BF;&#x30C3;&#x30AF;&#x3067;&#x59CB;&#x3081;&#x308B;Web&#x30A2;&#x30D7;&#x30EA;&#x958B;&#x767A;&#x5165;&#x9580;&#xFF08;2&#xFF09; - &#xFF20;IT</a></li> <li><a href="https://qiita.com/megane42/items/2ab6ffd866c3f2fda066">npm &#x3068;&#x304B; bower &#x3068;&#x304B;&#x4E00;&#x4F53;&#x4F55;&#x306A;&#x3093;&#x3060;&#x3088;&#xFF01;Javascript &#x754C;&#x9688;&#x306E;&#x6587;&#x8108;&#x3092;&#x7406;&#x89E3;&#x3057;&#x3088;&#x3046;</a></li> <li><a href="https://qiita.com/hshimo/items/1ecb7ed1b567aacbe559">Node.js &#x3092;5&#x5206;&#x3067;&#x5927;&#x96D1;&#x628A;&#x306B;&#x7406;&#x89E3;&#x3059;&#x308B;</a></li> </ul> turgure はてなブログのサイドバーを横に表示する part2 hatenablog://entry/10257846132611160723 2018-08-16T01:19:02+09:00 2018-08-16T01:50:45+09:00 前回の記事で、うまくいかなかったので、その2 gridを使った書き方 #content-inner { display: grid; grid-template-columns: 800px 1fr; } でok ただ、IE(とEdge)に対応させるためには以下のように修正しなければならなかった #content-inner { display: grid; display: -ms-grid; grid-template-columns: 800px 1fr; -ms-grid-columns: 800px 1fr; } #wrapper { -ms-grid-column: 1; } #b… <p><a href="http://turgure.hatenablog.com/entry/2018/08/15/224310">&#x524D;&#x56DE;&#x306E;&#x8A18;&#x4E8B;</a>で、うまくいかなかったので、その2</p> <p>gridを使った書き方</p> <pre class="code" data-lang="" data-unlink>#content-inner { display: grid; grid-template-columns: 800px 1fr; }</pre> <p>でok</p> <p>ただ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IE">IE</a>(とEdge)に対応させるためには以下のように修正しなければならなかった</p> <pre class="code" data-lang="" data-unlink>#content-inner { display: grid; display: -ms-grid; grid-template-columns: 800px 1fr; -ms-grid-columns: 800px 1fr; } #wrapper { -ms-grid-column: 1; } #box2 { -ms-grid-column: 2; }</pre> <p>悲しいなあ</p> <p><br /></p> <p>参考サイト</p> <ul> <li><a href="https://www.itti.jp/web-staff/css-grid.php">CSS Grid&#x3092;IE11&#x3001;EDGE&#x306B;&#x5BFE;&#x5FDC;&#x3055;&#x305B;&#x308B;&#x305F;&#x3081;&#x306B;&#x6CE8;&#x610F;&#x3059;&#x308B;&#x70B9; &#x6771;&#x4EAC;&#x65B0;&#x5BBF;&#x306E;&#x30DB;&#x30FC;&#x30E0;&#x30DA;&#x30FC;&#x30B8;&#x5236;&#x4F5C;&#x4F1A;&#x793E;&#x30A4;&#x30C3;&#x30C6;&#x30A3;</a></li> <li><a href="http://neos21.hatenablog.com/entry/2018/03/10/080000">IE11 &#x3067; CSS Grid &#x3092;&#x4F7F;&#x3046;&#x306E;&#x304C;&#x5927;&#x5909;&#x3060;&#x3063;&#x305F; - Corredor</a></li> </ul> turgure はてなブログのサイドバーを横に表示する hatenablog://entry/10257846132611110231 2018-08-15T22:43:10+09:00 2018-08-16T01:39:48+09:00 【追記 2018/08/16】 次の記事で書いた方法がいいと思います。 この記事で書いた方法だと、ブログtopページでは正常に表示されましたが、 各記事のページに行くとレイアウトが崩れてしまっていました。 プレビューがおかしくなるのも同じ原因でした。 下の参考サイトで書いあったように、1次元レイアウトならflexの方がいいような気がするのですが仕方ないんですかねー #content-inner { display: flex; } デザインcssにこれを追加するだけ! でも記事のプレビューしたときに記事とサイドバーの横幅が1:1になってるのが気になる… 参考サイト はてなブログのidとかcla… <p><b>【<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%C9%B5%AD">追記</a> 2018/08/16】</b><br/> <a href="http://turgure.hatenablog.com/entry/2018/08/16/011902">&#x6B21;&#x306E;&#x8A18;&#x4E8B;</a>で書いた方法がいいと思います。<br/> この記事で書いた方法だと、ブログtopページでは正常に表示されましたが、</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180816/20180816013315.png" style="border: solid 1px #000000;" /></p> <p>各記事のページに行くとレイアウトが崩れてしまっていました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180816/20180816013320.png" style="border: solid 1px #000000;" /></p> <p>プレビューがおかしくなるのも同じ原因でした。<br/> 下の参考サイトで書いあったように、1次元レイアウトなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/flex">flex</a>の方がいいような気がするのですが仕方ないんですかねー</p> <hr /> <pre class="code" data-lang="" data-unlink>#content-inner { display: flex; }</pre> <p>デザイン<a class="keyword" href="http://d.hatena.ne.jp/keyword/css">css</a>にこれを追加するだけ!</p> <p>でも記事のプレビューしたときに記事とサイドバーの横幅が1:1になってるのが気になる…</p> <p><br /></p> <p>参考サイト</p> <ul> <li><a href="http://kyabana.hatenablog.jp/entry/2013/04/04/133728">&#x306F;&#x3066;&#x306A;&#x30D6;&#x30ED;&#x30B0;&#x306E;id&#x3068;&#x304B;class&#x3068;&#x304B; - kyabana&#39;s blog</a></li> <li><a href="https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet">&#x65E5;&#x672C;&#x8A9E;&#x5BFE;&#x5FDC;&#xFF01;CSS Flexbox&#x306E;&#x30C1;&#x30FC;&#x30C8;&#x30B7;&#x30FC;&#x30C8;&#x3092;&#x4F5C;&#x3063;&#x305F;&#x306E;&#x3067;&#x914D;&#x5E03;&#x3057;&#x307E;&#x3059; | Web&#x30AF;&#x30EA;&#x30A8;&#x30A4;&#x30BF;&#x30FC;&#x30DC;&#x30C3;&#x30AF;&#x30B9;</a></li> <li><a href="https://coliss.com/articles/build-websites/operation/css/flexbox-and-grid.html">[CSS]Web&#x30DA;&#x30FC;&#x30B8;&#x306E;&#x3053;&#x308C;&#x304B;&#x3089;&#x306E;&#x30EC;&#x30A4;&#x30A2;&#x30A6;&#x30C8;&#x30C6;&#x30AF;&#x30CB;&#x30C3;&#x30AF;&#xFF01;Flexbox&#x3068;CSS Grid&#x306F;&#x4E00;&#x7DD2;&#x306B;&#x4F7F;&#x7528;&#x3057;&#x3066;&#x3053;&#x305D;&#x4FA1;&#x5024;&#x304C;&#x3042;&#x308B; | &#x30B3;&#x30EA;&#x30B9;</a></li> </ul> turgure gmailで特定のメールのurlを取得する hatenablog://entry/10257846132610898764 2018-08-15T10:59:41+09:00 2018-08-15T10:59:41+09:00 このメール見て!ってことをやりたかったので 1 . 対象のメールを開く 2 . ポップアップする 3 . URLのth=xxxのth以下のidをコピー 4 . URLをhttps://mail.google.com/mail/u/0/#inbox/xxx (xxxはコピーしたid)にする このリンクを貼り付ければ対象のメールを開くことができる 参考サイト Gmail で特定のメールをあとで探せるようにしておく - Drafts <p>このメール見て!ってことをやりたかったので</p> <p>1 . 対象のメールを開く<br/> 2 . ポップアップする</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180815/20180815095946.png" alt="f:id:turgure:20180815095946p:plain" title="f:id:turgure:20180815095946p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>3 . URLの<code>th=xxx</code>のth以下のidをコピー</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180815/20180815105852.png" alt="f:id:turgure:20180815105852p:plain" title="f:id:turgure:20180815105852p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>4 . URLを<code>https://mail.google.com/mail/u/0/#inbox/xxx</code> (xxxはコピーしたid)にする</p> <p>このリンクを貼り付ければ対象のメールを開くことができる</p> <p>参考サイト</p> <ul> <li><a href="http://cm3.hateblo.jp/entry/2015/08/03/171510">Gmail &#x3067;&#x7279;&#x5B9A;&#x306E;&#x30E1;&#x30FC;&#x30EB;&#x3092;&#x3042;&#x3068;&#x3067;&#x63A2;&#x305B;&#x308B;&#x3088;&#x3046;&#x306B;&#x3057;&#x3066;&#x304A;&#x304F; - Drafts</a></li> </ul> turgure androidのpermission hatenablog://entry/10257846132609049824 2018-08-09T14:21:40+09:00 2018-09-27T01:14:36+09:00 android 6.0から、インストール時にまとめてpermissionを許可する方式から、最初は何も許可せずに使うタイミングで許可を求めさせる方式に変わった。 それについてのpermissionの求め方についてのメモ private final int REQUEST_CODE_WRITE_EXTERNAL_STORAGE = 1; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permiss… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/android">android</a> 6.0から、インストール時にまとめてpermissionを許可する方式から、最初は何も許可せずに使うタイミングで許可を求めさせる方式に変わった。<br/> それについてのpermissionの求め方についてのメモ</p> <pre class="code lang-java" data-lang="java" data-unlink><span class="synType">private</span> <span class="synType">final</span> <span class="synType">int</span> REQUEST_CODE_WRITE_EXTERNAL_STORAGE = <span class="synConstant">1</span>; <span class="synStatement">if</span>(Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) { <span class="synStatement">if</span>(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( <span class="synType">this</span>, <span class="synStatement">new</span> String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_WRITE_EXTERNAL_STORAGE); <span class="synStatement">return</span>; } } </pre> <p>許可の設定で、今後は表示しないなどとした場合は、<code>shouldShowRequestPermissionRationale(Activity activity, String permission)</code>を使う。<br/> むしろ積極的に使うべし</p> <pre class="code lang-java" data-lang="java" data-unlink><span class="synType">private</span> <span class="synType">final</span> <span class="synType">int</span> REQUEST_CODE_WRITE_EXTERNAL_STORAGE = <span class="synConstant">1</span>; <span class="synStatement">if</span>(Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) { <span class="synStatement">if</span>(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { <span class="synStatement">if</span>(ActivityCompat.shouldShowRequestPermissionRationale(<span class="synType">this</span>, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(<span class="synType">this</span>, <span class="synConstant">&quot;パーミッションがOFFになっています。&quot;</span>, Toast.LENGTH_SHORT).show(); } <span class="synStatement">else</span> { ActivityCompat.requestPermissions( <span class="synType">this</span>, <span class="synStatement">new</span> String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_WRITE_EXTERNAL_STORAGE); } <span class="synStatement">return</span>; } } </pre> <p><strong>追記 20180927</strong><br/> <code>shouldShowRequestPermissionRationale()</code>は、permissionを使う理由を説明するときに使うメソッドらしい。<br/> なので、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A1%BC%A5%DF%A5%C3%A5%B7%A5%E7%A5%F3">パーミッション</a>がOFFです」ではなく、「xxxの目的で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A1%BC%A5%DF%A5%C3%A5%B7%A5%E7%A5%F3">パーミッション</a>が必要です。」の説明の方が適切かも <br/> <a href="https://qiita.com/akitaika_/items/27c4eaeea6960ac9bb0d">Marshmallow &#x3067;&#x3084;&#x3063;&#x3066;&#x304D;&#x305F;&#x30D1;&#x30FC;&#x30DF;&#x30C3;&#x30B7;&#x30E7;&#x30F3;&#x8981;&#x6C42;&#x307E;&#x308F;&#x308A;&#x3092;&#xFF11;&#x3064;&#x306E;&#x30D5;&#x30E9;&#x30B0;&#x30E1;&#x30F3;&#x30C8;&#x306B;&#x307E;&#x3068;&#x3081;&#x3066;&#x307F;&#x305F;</a></p> <p><br /></p> <p><code>requirePermissions()</code>が走ると、通知許可をしたかどうかで処理が分かれる。<br/> そして、その結果を<code>onRequestPermissionResult()</code>で受け取る</p> <pre class="code lang-java" data-lang="java" data-unlink><span class="synPreProc">@Override</span> <span class="synType">public</span> <span class="synType">void</span> onRequestPermissionsResult(<span class="synType">int</span> requestCode, String permissions[], <span class="synType">int</span>[] grantResults){ <span class="synStatement">switch</span>(requestCode) { <span class="synStatement">case</span> REQUEST_CODE_WRITE_EXTERNAL_STORAGE: <span class="synStatement">if</span>(grantResults.length &gt; <span class="synConstant">0</span> &amp;&amp; grantResults[<span class="synConstant">0</span>] == PackageManager.PERMISSION_GRANTED) { <span class="synComment">// 許可したときの処理</span> } <span class="synStatement">else</span> { <span class="synComment">// 許可しなかったときの処理</span> } <span class="synStatement">break</span>; <span class="synStatement"> default</span>: <span class="synType">super</span>.onRequestPermissionsResult(requestCode, permissions, grantResults); <span class="synStatement">break</span>; } } </pre> <p><br /></p> <p>参考サイト</p> <ul> <li><a href="https://developer.android.com/training/permissions/requesting?hl=ja">&#x5B9F;&#x884C;&#x6642;&#x306E;&#x30D1;&#x30FC;&#x30DF;&#x30C3;&#x30B7;&#x30E7;&#x30F3; &#x30EA;&#x30AF;&#x30A8;&#x30B9;&#x30C8; &nbsp;|&nbsp; Android Developers</a></li> <li><a href="https://qiita.com/yamacraft/items/b1cfe43e52cf3c58a046">&#x3042;&#x3089;&#x305F;&#x3081;&#x3066;Runtime Permission&#x3068;&#x5B9F;&#x88C5;&#x65B9;&#x6CD5;&#x3092;&#x304A;&#x3055;&#x3089;&#x3044;&#x3059;&#x308B;</a></li> <li><a href="https://qiita.com/hotdrop_77/items/bb8c97a3c197ee4f44df">Android6.0&#x4EE5;&#x4E0A;&#x306E;&#x7AEF;&#x672B;&#x3067;&#x52D5;&#x4F5C;&#x3059;&#x308B;GoogleMaps&#x30A2;&#x30D7;&#x30EA;&#x3092;&#x4F5C;&#x6210;&#x308D;&#x3046;&#x3068;&#x3057;&#x3066;&#x3044;&#x304D;&#x306A;&#x308A;&#x30CF;&#x30DE;&#x3063;&#x305F;&#x3053;&#x3068;&#x307E;&#x3068;&#x3081;</a></li> <li><a href="https://qiita.com/imaizume/items/178cb540b697cd9419fd">Android&#x306E;&#x30D1;&#x30FC;&#x30DF;&#x30C3;&#x30B7;&#x30E7;&#x30F3;&#x3068;6.0&#x3067;&#x306E;&#x51E6;&#x7406;&#x306E;&#x6D41;&#x308C;&#x3092;&#x4ECA;&#x3055;&#x3089;&#x8AAC;&#x660E;&#x3057;&#x3066;&#x307F;&#x308B;</a></li> <li><a href="https://qiita.com/caad1229/items/35bab757217b204711df">&#x5C11;&#x3057;&#x89AA;&#x5207;&#x306A;Runtime Permission&#x5BFE;&#x5FDC;</a></li> <li><a href="https://qiita.com/LyricalMaestro0/items/4bb59762e586e3504f79">M Permissions&#x5BFE;&#x5FDC;&#x306B;&#x3064;&#x3044;&#x3066;&#x306E;&#x7C21;&#x5358;&#x306A;&#x8A18;&#x4E8B;</a></li> <li><a href="http://techbooster.org/android/application/17223/">&#x521D;&#x5FC3;&#x8005;&#x306E;&#x305F;&#x3081;&#x306E;M Permissions&#x5165;&#x9580; | TechBooster</a></li> <li><a href="https://stackoverflow.com/questions/34613002/the-method-checkselfpermissioncontext-string-is-undefined-for-the-type-contex">android - The method checkSelfPermission(Context, String) is undefined for the type ContextCompat - Stack Overflow</a></li> </ul> turgure androidでアプリの再起動を行う hatenablog://entry/10257846132608458540 2018-08-07T17:04:25+09:00 2018-08-07T17:04:25+09:00 AlarmManagerを使うとうまくいった Intent intent = getIntent(); PendingIntent appStarter = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE); alarmManager.set(AlarmManager.RTC_WAKEUP, System.curre… <p><code>AlarmManager</code>を使うとうまくいった</p> <pre class="code lang-java" data-lang="java" data-unlink>Intent intent = getIntent(); PendingIntent appStarter = PendingIntent.getActivity(getApplicationContext(), <span class="synConstant">0</span>, intent, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE); alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), appStarter); finish(); </pre> <p>参考サイト</p> <ul> <li><a href="https://akira-watson.com/android/app-restart.html">[Android] &#x30A2;&#x30D7;&#x30EA;&#x3092;&#x5F37;&#x5236;&#x7684;&#x306B; restart &#x3055;&#x305B;&#x308B;</a></li> <li><a href="https://gist.github.com/uphy/7857256">Android&#x3067;&#x3001;&#x30A2;&#x30AF;&#x30C6;&#x30A3;&#x30D3;&#x30C6;&#x30A3;&#x3067;&#x306F;&#x306A;&#x304F;&#x3001;&#x30A2;&#x30D7;&#x30EA;&#x30B1;&#x30FC;&#x30B7;&#x30E7;&#x30F3;&#x30EC;&#x30D9;&#x30EB;&#x306E;&#x518D;&#x8D77;&#x52D5;&#x3092;&#x884C;&#x3046;&#x3002; &middot; GitHub</a></li> </ul> turgure gradleやsdkのバージョンアップに伴う変更 hatenablog://entry/10257846132606951470 2018-08-02T18:45:31+09:00 2018-08-02T18:45:31+09:00 以下のようにバージョンアップをしたので、その時の変更点をメモ バージョン変更 gradle 2.2.1 -> 4.4 gradle plugin 1.3.0 -> 3.1.3 buildToolsVersion 23.0.0 -> 28.0.1 変更点 gradleとgradle pluginの対応 最新版にするならandroid studioがよしなにやってくれるはず 基本的な対応表はこちら 個別の対応が必要な場合はstack overflowとかで調べればでてくるんじゃないすかね ・Android のビルドについて(Gradle) - mixi-inc/AndroidTraining ・G… <p>以下のようにバージョンアップをしたので、その時の変更点をメモ</p> <h3>バージョン変更</h3> <ul> <li>gradle <ul> <li>2.2.1 -> 4.4</li> </ul> </li> <li>gradle plugin <ul> <li>1.3.0 -> 3.1.3</li> </ul> </li> <li>buildToolsVersion <ul> <li>23.0.0 -> 28.0.1</li> </ul> </li> </ul> <h3>変更点</h3> <ul> <li>gradleとgradle pluginの対応</li> </ul> <p>最新版にするなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/android%20studio">android studio</a>がよしなにやってくれるはず<br/> 基本的な対応表はこちら<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180802/20180802182332.png" alt="f:id:turgure:20180802182332p:plain" title="f:id:turgure:20180802182332p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>個別の対応が必要な場合はstack overflowとかで調べればでてくるんじゃないすかね</p> <p>  ・<a href="http://mixi-inc.github.io/AndroidTraining/introductions/1.05.how-to-build-for-gradle.html">Android &#x306E;&#x30D3;&#x30EB;&#x30C9;&#x306B;&#x3064;&#x3044;&#x3066;(Gradle) - mixi-inc/AndroidTraining</a><br/>   ・<a href="https://qiita.com/izuki_y/items/3c20cd1c655fc4fc6127">Gradle &#x3068; Gradle Plugin &#x306E;&#x30D0;&#x30FC;&#x30B8;&#x30E7;&#x30F3;&#x306B;&#x3064;&#x3044;&#x3066;</a></p> <p><br /></p> <ul> <li>compile -> implementation</li> </ul> <p><code>compile</code>じゃなくて<code>implementation</code>を使えっていうエラーが出てたので修正</p> <p>  ・<a href="https://teratail.com/questions/119882">Android Studio - Android Studio Gradle &#x30A8;&#x30E9;&#x30FC;(119882)&#xFF5C;teratail</a></p> <p><br /></p> <ul> <li>flavor dimensionの設定</li> </ul> <p><code>productFlavors</code>を利用する場合、<code>flavorDimensions</code>に設定した<code>dimension</code>を利用しなくてはいけなくなったので追加<br/> 分けたいものに対して、同じ<code>dimension</code>を割り振る(↓の例など)</p> <pre class="code" data-lang="" data-unlink>flavorDimensions &#39;environment&#39; productFlavors { develop { dimension &#39;environment&#39; // } staging { dimension &#39;environment&#39; // } product { dimension &#39;environment&#39; // } }</pre> <p>  ・<a href="https://developer.android.com/studio/build/build-variants?hl=ja">&#x30D3;&#x30EB;&#x30C9; &#x30D0;&#x30EA;&#x30A2;&#x30F3;&#x30C8;&#x306E;&#x8A2D;&#x5B9A; &nbsp;|&nbsp; Android Developers</a><br/>   ・<a href="https://android.benigumo.com/20171026/flavor-dimension/">&#x3010;AndroidStudio 3.0&#x3011;&#x300C;flavor dimension&#x300D;&#x3068;&#x306F;&#x4F55;?</a></p> <p><br /></p> <ul> <li>lint-gradleの対応</li> </ul> <p>なんか足りないって言われるので、<code>build.gradle</code>に<code>google()</code>を追加</p> <pre class="code" data-lang="" data-unlink>allprojects { repositories { google() jcenter() } }</pre> <p>  ・<a href="https://stackoverflow.com/questions/46972122/could-not-find-com-android-tools-lintlint-gradle-android-studio-3">Could not find com.android.tools.lint:lint-gradle Android Studio 3 - Stack Overflow</a></p> <p>これで無事にビルドが通りました。</p> turgure .ideaフォルダの.gitignore hatenablog://entry/10257846132606914211 2018-08-02T16:40:21+09:00 2018-08-02T16:40:40+09:00 調べる機会があったのでここにまとめておきます .ideaフォルダはandroid studioの設定について記述されたもので、ほぼ自動生成されます チーム開発する際には、いくつか共有するのを推奨するファイルもあるため、自分が最終的に作った.ideaに関するignoreについてまとめておきます # User-specific configurations .idea/caches/build_file_checksums.ser .idea/codeStyles/ .idea/compiler.xml .idea/copyright/profiles_settings.xml .idea/dic… <p>調べる機会があったのでここにまとめておきます<br/> .ideaフォルダは<a class="keyword" href="http://d.hatena.ne.jp/keyword/android%20studio">android studio</a>の設定について記述されたもので、ほぼ自動生成されます</p> <p>チーム開発する際には、いくつか共有するのを推奨するファイルもあるため、自分が最終的に作った.ideaに関するignoreについてまとめておきます</p> <pre class="code" data-lang="" data-unlink># User-specific configurations .idea/caches/build_file_checksums.ser .idea/codeStyles/ .idea/compiler.xml .idea/copyright/profiles_settings.xml .idea/dictionaries/ .idea/libraries/ .idea/misc.xml .idea/modules.xml .idea/tasks.xml .idea/scopes/scope_settings.xml .idea/workspace.xml .idea/.name *.iml</pre> <p>参考URL</p> <ul> <li><a href="https://qiita.com/kgmyshin/items/5d92915b3d0b8c69cfd4">&#x3010;Android&#x3011;&#x3082;&#x3063;&#x3068;&#x5148;&#x3078;&#x300C;&#x52A0;&#x901F;&#x300D;&#x3057;&#x305F;&#x304F;&#x306F;&#x306A;&#x3044;&#x304B;&#x3001;&#x5C11;&#x5E74; &#x301C;gitignore&#x7DE8;&#x301C;</a></li> <li><a href="http://gihyo.jp/dev/serial/01/android_studio/0034?page=1">&#x7B2C;34&#x56DE; &#x30D0;&#x30FC;&#x30B8;&#x30E7;&#x30F3;&#x7BA1;&#x7406; &#x2500;&#x30D7;&#x30ED;&#x30B8;&#x30A7;&#x30AF;&#x30C8;&#x7BA1;&#x7406;&#x30D5;&#x30A1;&#x30A4;&#x30EB;&#x306B;&#x3064;&#x3044;&#x3066;&#xFF3B;&#x4E2D;&#x7DE8;&#xFF3D;&#xFF1A;Android Studio&#x6700;&#x901F;&#x5165;&#x9580;&#xFF5E;&#x52B9;&#x7387;&#x7684;&#x306B;&#x30B3;&#x30FC;&#x30C7;&#x30A3;&#x30F3;&#x30B0;&#x3059;&#x308B;&#x305F;&#x3081;&#x306E;&#x4F7F;&#x3044;&#x65B9;&#xFF5C;gihyo.jp &hellip; &#x6280;&#x8853;&#x8A55;&#x8AD6;&#x793E;</a></li> <li><a href="http://gihyo.jp/dev/serial/01/android_studio/0035?page=1">&#x7B2C;35&#x56DE; &#x30D0;&#x30FC;&#x30B8;&#x30E7;&#x30F3;&#x7BA1;&#x7406; &#x2500;&#x30D7;&#x30ED;&#x30B8;&#x30A7;&#x30AF;&#x30C8;&#x7BA1;&#x7406;&#x30D5;&#x30A1;&#x30A4;&#x30EB;&#x306B;&#x3064;&#x3044;&#x3066;&#xFF3B;&#x5F8C;&#x7DE8;&#xFF3D;&#xFF1A;Android Studio&#x6700;&#x901F;&#x5165;&#x9580;&#xFF5E;&#x52B9;&#x7387;&#x7684;&#x306B;&#x30B3;&#x30FC;&#x30C7;&#x30A3;&#x30F3;&#x30B0;&#x3059;&#x308B;&#x305F;&#x3081;&#x306E;&#x4F7F;&#x3044;&#x65B9;&#xFF5C;gihyo.jp &hellip; &#x6280;&#x8853;&#x8A55;&#x8AD6;&#x793E;</a></li> <li><a href="https://stackoverflow.com/questions/49557737/should-i-add-idea-caches-build-file-checksums-ser-to-gitignore">android - Should I add .idea/caches/build_file_checksums.ser to .gitignore? - Stack Overflow</a></li> <li><a href="https://qiita.com/takahirom/items/4302c65e864a2aee956a">Android Studio 3.0&#x304B;&#x3089;3.1&#x3078;&#x306E;&#x30DE;&#x30A4;&#x30B0;&#x30EC;&#x30FC;&#x30B7;&#x30E7;&#x30F3;</a></li> </ul> turgure はてなブログで数式を表示させる hatenablog://entry/17391345971652786920 2018-07-04T09:08:12+09:00 2018-07-04T09:11:57+09:00 色々調べても全然わからんかったのでここにメモ 自分の場合は「プレビューしたときに一瞬だけ表示されて消える」という現象だった。 おそらくフォーマットは合っているのだが、 「消える」という部分に対する解決方法の記事がなかった。 解決策としては、「設定 > デザイン > カスタマイズ > ヘッダ」に、以下を加える <script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML"> </script> これで… <p>色々調べても全然わからんかったのでここにメモ<br/> 自分の場合は「プレビューしたときに一瞬だけ表示されて消える」という現象だった。<br/> おそらくフォーマットは合っているのだが、 「消える」という部分に対する解決方法の記事がなかった。</p> <p>解決策としては、「設定 > デザイン > カスタマイズ > ヘッダ」に、以下を加える</p> <pre class="code lang-css" data-lang="css" data-unlink>&lt;<span class="synStatement">script</span> type=<span class="synConstant">&quot;text/javascript&quot;</span> async src=<span class="synConstant">&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML&quot;</span><span class="synSpecial">&gt;</span> &lt;/<span class="synStatement">script</span><span class="synSpecial">&gt;</span> </pre> <p>これで問題なく表示されるようになった。</p> <p>あとは参考サイト様のように書けば表示された。</p> <pre class="code lang-tex" data-lang="tex" data-unlink><span class="synSpecial">$$</span> <span class="synSpecial">e^{</span><span class="synStatement">j\pi</span><span class="synSpecial">} + 1 </span><span class="synStatement">=</span><span class="synSpecial"> 0 </span> <span class="synSpecial">$$</span> </pre> <div style="text-align: center;">↓</div> <p>$$ e^{j\pi} + 1 = 0 $$</p> <p>参考URL</p> <ul> <li><a href="http://cartman0.hatenablog.com/entry/2016/11/13/034412">hatena&#x30D6;&#x30ED;&#x30B0;&#x306B;mathjax &#x3092;&#x57CB;&#x3081;&#x8FBC;&#x3080; - &#x306F;&#x3057;&#x304F;&#x308C;&#x30A8;&#x30F3;&#x30B8;&#x30CB;&#x30A2;&#x3082;&#x3069;&#x304D;&#x306E;&#x30E1;&#x30E2;</a></li> <li><a href="http://docs.mathjax.org/en/latest/start.html#using-the-mathjax-content-delivery-network-cdn">Mathjan&#x516C;&#x5F0F;</a></li> </ul> turgure [Unite2018] Unityにおける疎結合設計 ~UIへの適用事例から学ぶ、テクニックとメリット~ hatenablog://entry/10257846132597274816 2018-07-04T09:05:31+09:00 2018-07-04T09:05:31+09:00 公式サイト http://events.unity3d.jp/unitetokyo2018/session-lineup.html#session84 講演者 Florian Andreas Gantzert (KLab株式会社) SlideShare https://www.slideshare.net/UnityTechnologiesJapan002/unite-2018-tokyounity-ui 概要 UI 結合 UIアゲイン おさらい 内容 UI ビジュアルでUIを作れる(uGUI) にも関わらずプログラマがUIを作るケースが多い よくするための鍵は? → 結合 結合 定義 一方の… <h4>公式サイト</h4> <p><a href="http://events.unity3d.jp/unitetokyo2018/session-lineup.html#session84">http://events.unity3d.jp/unitetokyo2018/session-lineup.html#session84</a></p> <h4>講演者</h4> <p>Florian Andreas Gantzert (KLab株式会社)</p> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/SlideShare">SlideShare</a></h4> <p><a href="https://www.slideshare.net/UnityTechnologiesJapan002/unite-2018-tokyounity-ui">https://www.slideshare.net/UnityTechnologiesJapan002/unite-2018-tokyounity-ui</a></p> <h4>概要</h4> <ul> <li>UI</li> <li>結合</li> <li>UIアゲイン</li> <li>おさらい</li> </ul> <hr /> <h4>内容</h4> <ul> <li>UI <ul> <li>ビジュアルでUIを作れる(uGUI)</li> <li>にも関わらず<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>がUIを作るケースが多い</li> <li>よくするための鍵は? → 結合<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702091757.jpg" alt="f:id:turgure:20180702091757j:plain" title="f:id:turgure:20180702091757j:plain" class="hatena-fotolife" itemprop="image"></span><br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702091806.jpg" alt="f:id:turgure:20180702091806j:plain" title="f:id:turgure:20180702091806j:plain" class="hatena-fotolife" itemprop="image"></span></li> </ul> </li> </ul> <p><br /></p> <ul> <li>結合 <ul> <li>定義 <ul> <li>一方の偏光によって他方の変更が必要になる</li> <li>Aを変更したらBも変更しなくてはいけない</li> </ul> </li> <li>密結合 <ul> <li>結合している状態</li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a> <ul> <li>結合していない状態</li> </ul> </li> <li>結合レベル <ul> <li>結合はコードの話だけではない</li> <li>コードの結合が、データとワークフローの結合につながる<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180704/20180704085842.jpg" alt="f:id:turgure:20180704085842j:plain" title="f:id:turgure:20180704085842j:plain" class="hatena-fotolife" itemprop="image"></span></li> </ul> </li> <li>結合と抽象化 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>は<span style="color: #ff0000"><b>抽象化</b></span>で実現させる</li> <li>抽象化 <ul> <li>× 汎用化、一般化</li> <li>縛りのないシンプルな抽象化が望ましい</li> </ul> </li> </ul> </li> <li>結合バランス <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>にバランスがある</li> <li>結合のバランスがプロジェクト規模に依存する</li> <li>問題点 <ul> <li>孤立しているタスクのはずが <ul> <li>巨大化</li> <li>副作用が発生</li> <li>対応が複雑化</li> </ul> </li> </ul> </li> <li>バランスがずれてもまだ手遅れじゃない</li> <li>バランスの鍵は分野相互間コミュニケーション</li> </ul> </li> </ul> </li> </ul> <p><br /></p> <ul> <li>UIアゲイン <ul> <li>ワークフロー <ul> <li>同時作業によるコンフリクトはありえる</li> <li>ワークフロー上でそのコンフリクトを阻止できない <ul> <li>違うレベルで阻止する必要</li> </ul> </li> <li>データを分割してコンフリクトを阻止</li> <li>コード上でその分割に対応</li> </ul> </li> <li>データ分割 <ul> <li>UI専用のシーンを用意</li> <li>UIシーンは他のゲームと連携<br/> ↓</li> <li>Unityの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%EA%A5%A2%A5%E9%A5%A4%A5%BA">シリアライズ</a>機能が使えない</li> <li>UIシーンと他のシーンはどうやって連携させる? <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/MVC">MVC</a>・MVVM <ul> <li>参照:<a href="http://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Dilly_Data%20Binding%20Architectures.pdf">GDC 2017 “Data Binding Architectures for Rapid UI Creation in Unity”</a></li> </ul> </li> <li><code>UnityEngine.ExposedReference&lt;T&gt;?</code> <ul> <li>Timelineで利用される</li> <li>ランタイム時にIDで参照を解決</li> <li><code>ExposedReference&lt;T&gt;</code>本体側でもルックアップテーブルIDを管理する必要</li> </ul> </li> <li>メッセージ・バス <ul> <li>必要な情報だけメッセージとして抽象化、バスに飛ばす</li> <li>バスの接続先でメッセージを処理</li> <li>発信元、接続先は互いの情報を知らなくていい</li> <li>どのような情報を扱うか、どういうルールにするか <ul> <li>デザイナと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>が話し合って決める</li> </ul> </li> <li>発信源、接続先の差し替えでデザイナ向けの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>機能の追加が容易</li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> <p><br /></p> <ul> <li>おさらい <ul> <li>結合はコードの話だけではない <ul> <li>データとワークフローでも発生する</li> </ul> </li> <li>規模とともに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>が必要になる</li> <li>コードの結合はデータとワークフローの結合につながる</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>の道は抽象化で開く</li> <li>コードとデータの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>はよりよいワークフローにつながる</li> <li>シーンを分けることでUnityにおける同時作業がやりやすくなる</li> <li>メッセージ・バスで複数のシーンやロジックなどを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C2%B7%EB%B9%E7">疎結合</a>的につなげる</li> </ul> </li> </ul> <p><br /></p> <ul> <li>おまけ <ul> <li>roll a ballの改造 中上級者向け <ul> <li>テストしたい</li> <li>ML(Machine Learning)で動かしたい <ul> <li>→入力の抽象化</li> <li>入力情報を管理するinterfaceを作る</li> </ul> </li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a>における抽象化 <ul> <li>インターフェース化 ←ゲームはこっちのほうがいい? <ul> <li>処理側がタイミングを決める</li> </ul> </li> <li>イベント化 <ul> <li>情報元がタイミングを決める</li> </ul> </li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/c%23">c#</a>におけるイベント化 <ul> <li>言語レベルで対応している <ul> <li><code>delegate</code>, <code>event</code></li> </ul> </li> <li>Unity <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>でも使われている <ul> <li><code>hierarchyChanged</code>など</li> </ul> </li> </ul> </li> </ul> </li> </ul> turgure [Unite2018] Unity 2D機能のアップデートとその周辺 hatenablog://entry/10257846132597274314 2018-07-02T09:15:23+09:00 2018-07-02T09:15:23+09:00 公式サイト http://events.unity3d.jp/unitetokyo2018/session-lineup.html#session79 講演者 山村 達彦 (ユニティ・テクノロジーズ・ジャパン合同会社) 京野 光平 a.k.a. ntny (ユニティ・テクノロジーズ・ジャパン合同会社) SlideShare https://www.slideshare.net/UnityTechnologiesJapan/unite-2018-tokyounity-2d 概要 ステージを作りやすく もっと高度なキャラクター表現 その周辺 UI パフォーマンス アセット 内容 ステージを作りやす… <h4>公式サイト</h4> <p><a href="http://events.unity3d.jp/unitetokyo2018/session-lineup.html#session79">http://events.unity3d.jp/unitetokyo2018/session-lineup.html#session79</a></p> <h4>講演者</h4> <p>山村 達彦 (ユニティ・テク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CE%A5%ED">ノロ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A1%BC">ジー</a>ズ・ジャパン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%E7%C6%B1%B2%F1%BC%D2">合同会社</a>)<br/> 京野 光平 <a class="keyword" href="http://d.hatena.ne.jp/keyword/a.k.a.">a.k.a.</a> ntny (ユニティ・テク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CE%A5%ED">ノロ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A1%BC">ジー</a>ズ・ジャパン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B9%E7%C6%B1%B2%F1%BC%D2">合同会社</a>)</p> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/SlideShare">SlideShare</a></h4> <p><a href="https://www.slideshare.net/UnityTechnologiesJapan/unite-2018-tokyounity-2d">https://www.slideshare.net/UnityTechnologiesJapan/unite-2018-tokyounity-2d</a></p> <h4>概要</h4> <ul> <li>ステージを作りやすく</li> <li>もっと高度なキャラクター表現</li> <li>その周辺 <ul> <li>UI</li> <li>パフォーマンス</li> <li>アセット</li> </ul> </li> </ul> <hr /> <h4>内容</h4> <ul> <li>ステージを作りやすく <ul> <li>TileMap <ul> <li>Unity 2017.2から <ul> <li>タイルベースでステージを作る仕組み</li> <li>タイルを塗るようにステージを作成</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/RPG%A5%C4%A5%AF%A1%BC%A5%EB">RPGツクール</a>みたいな</li> </ul> </li> <li>Unity2018.2から <ul> <li>六角形タイルもサポート</li> </ul> </li> <li>Tile &emsp;&emsp;&emsp; タイルのアセット</li> <li>Palette &emsp;&emsp; タイルを塗る際に使用するパレット</li> <li>Brush &emsp;&emsp; タイルをタイルマップに塗る</li> <li>Tilemap &emsp; タイルをセットするグリッド<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702090943.jpg" alt="f:id:turgure:20180702090943j:plain" title="f:id:turgure:20180702090943j:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>実装例 <ul> <li>隠し通路</li> <li>家の裏に行くと影</li> <li>当たり判定処理</li> </ul> </li> </ul> </li> <li>2D Sprite Shape <ul> <li>Unity 2018 Package Managerで提供</li> <li>伸縮するスプライトでステージを作る</li> <li>フレキシブルなマップ</li> <li>Spriteの面に応じて表示するものを設定できる</li> <li><code>MeshCollider2D</code>や<code>EdgeCollider2D</code>の当たり判定とも連携<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702091102.jpg" alt="f:id:turgure:20180702091102j:plain" title="f:id:turgure:20180702091102j:plain" class="hatena-fotolife" itemprop="image"></span></li> </ul> </li> <li>Cinemachine <ul> <li>カメラ移動制御</li> <li>必要なのはColliderのポリゴン情報 <ul> <li>Colliderだが当たり判定は必要ない</li> <li><code>Rigidbody2D</code>のSimulatedをOffにする<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702091140.jpg" alt="f:id:turgure:20180702091140j:plain" title="f:id:turgure:20180702091140j:plain" class="hatena-fotolife" itemprop="image"></span></li> </ul> </li> </ul> </li> </ul> </li> </ul> <p><br /></p> <ul> <li>高度なキャラクター表現 <ul> <li>ボーンベースのアニメーション <ul> <li>スケルタルアニメーション</li> <li>スプライトの回転や移動でアニメーションを実現</li> </ul> </li> <li>2D Animation <ul> <li>2D IK &emsp;&emsp;&emsp;&emsp;&emsp; IK実現</li> <li>2D Animation &emsp; Spriteの変形に対応<br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702091250.jpg" alt="f:id:turgure:20180702091250j:plain" title="f:id:turgure:20180702091250j:plain" class="hatena-fotolife" itemprop="image"></span><br/> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/t/turgure/20180702/20180702091257.jpg" alt="f:id:turgure:20180702091257j:plain" title="f:id:turgure:20180702091257j:plain" class="hatena-fotolife" itemprop="image"></span></li> </ul> </li> <li>Simple Animation <ul> <li>アニメーションクリップを登録してPlay()するだけ</li> <li>ステートマシンは不要</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D4%A5%AF%A5%BB%A5%EB">ピクセル</a>パーフェクトなアニメ(開発中)</li> </ul> </li> <li>Timeline <ul> <li>Timelineは「タイミングを制御する」機能</li> <li>時間指定で処理を実行</li> <li>ゲームを再生せずプレビュー</li> <li>4つのポイント <ul> <li>動かすキャラとターゲット指定はTimeline再生前にバインド</li> <li>演出で使用する内容はPrefabにまとめておく</li> <li>移動はAnimation ClipではなくTween</li> <li>対象独自の動作はイベントを活用 <ul> <li>敵側、ダメージエフェクト</li> <li>Timelineはタイミングだけ管理</li> </ul> </li> </ul> </li> <li>Timelineは重い? <ul> <li>意外と軽い</li> <li>重い場合はPlayable Assetを分ける</li> <li>エディタとビルドで負荷がぜんぜん違う <ul> <li>ビルド前はとても遅い</li> <li>Timelineウィンドウがとても遅い</li> <li>ビルド前はロードも遅い</li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> <p><br /></p> <ul> <li>周辺 <ul> <li>パフォーマンス <ul> <li>Rigidbody 2Dのマルチスレッド化</li> <li>テンプレートの設定が少し変化</li> <li><code>Dynamic Batching</code>がデフォルトでoff <ul> <li><code>Instancing</code>を使う</li> </ul> </li> <li>Scriptable Render Pipeline <ul> <li>いくつかの機能が使えなくなる</li> </ul> </li> </ul> </li> <li>UI <ul> <li>新しい機能はない</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a> LayerはCameraに標準で組み込まれなくなった</li> <li>UIはPackage Managerに移行するかも</li> </ul> </li> <li>アセット <ul> <li>新しい縮小<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a> <ul> <li>Mitchell</li> </ul> </li> <li>テクスチャ <ul> <li>ETC2 8bit / ASTC 4x4</li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>サポート <ul> <li>ズームしてもくっきり</li> </ul> </li> </ul> </li> </ul> </li> </ul> turgure