freee Developers Advent Calendar 2018の3日目、会計 freee のUI設計とかプロダクトマネジメントとかを担当している @toofu__ です。業務と関係ない話を書きます。
気持ちを高める打刻
みなさん、打刻していますか?私は正直「面倒だな〜〜~」とか思いながら、いち従業員の責務として毎日打刻しています。
みんな同じような気持ちなのでしょう、怠惰な人類はいかに手間をかけずに勤怠打刻するかに知恵を絞り、スマホアプリを使ったり、音声入力で打刻したりします。しかし個人的には「よし、頑張るぞ!」と、やる気が出る打刻方法があってもいいのでは?と考えています。
たとえば、打刻したらお気に入りのキャラクターが目の前で声をかけてくれるというのはどうでしょうか。気持ちが高ぶるのではないでしょうか。ちょうど手元にVR機器のOculus Goが転がっていたので、これを使ってやってみることにしました。
先に結果を載せておくとこんな感じです。
見つめ合うと勤怠打刻 pic.twitter.com/IRcHuDX6wv
— 人生 (@toofu__) 2018年11月28日
下準備
環境
- Unity 2018.2.8f1
- Oculus Go
- 人事労務freee
人事労務freeeでは勤怠打刻APIが提供されています。今回はそれを使ってやっていきます。
freee Developer Communityのガイドを読んでアプリを作成し、appIDとsecret、それからAuthorization Codeを発行しておきます。(コールバックURIはurn:ietf:wg:oauth:2.0:oob
で大丈夫です)
それからUnity側の下準備です。Unityの基本的な使い方の説明は省略しますが、まずはプロジェクトを新規作成し、アセットストアからOculus Integrationをインポートします。
インポートするとOculus
という名前のフォルダがプロジェクト内にできるので、その中にあるOVRCameraRig
という名前のプレハブをシーンに追加します(ついでに、はじめからあるMainCameraを削除します)。
これで準備完了です。ここから実装を始めていきます。
実装
いくつかクラスを作っていきます。クラス間の関係はこんな感じです。主なスクリプトはgistにも書いておきます。
Unityからfreee APIへの連携
簡単ですがこんなライブラリを作ったので、これでペイっと接続していきます。
コードをダウンロードして、Unityプロジェクト内にコピーしておきます。そこから、FreeeEventHandler
という名前のラッパークラスを作って、freee APIを叩いて行いたい操作を作っていきます。
using Freee; public class FreeeEventHandler : MonoBehaviour { private Client client; [SerializeField] private string appID; [SerializeField] private string secret; [SerializeField] private string redirectURL; [SerializeField] private string authorization_code; [SerializeField] private string company_name; private int company_id; [SerializeField] private int employee_id; // 認証 private void GenerateAccessToken() { string refresh_token = PlayerPrefs.GetString("refresh_token", ""); client = new Freee.Client(appID, secret, redirectURL); if (string.IsNullOrEmpty(refresh_token)) { client.authorizationCode = authorization_code; } else { client.refreshToken = refresh_token; } StartCoroutine(client.GenerateAccessToken(GenerateAccessTokenCallback)); } private void GenerateAccessTokenCallback(bool success, string response) { if (!success) return; GetCompanies(); // 認証が成功したら事業所IDを取りに行く } // 事業所ID取得 private void GetCompanies() { StartCoroutine(client.Get("https://api.freee.co.jp/api/1/companies", new Dictionary<string, string>(), GetCompaniesCallback)); } private void GetCompaniesCallback(bool success, string response) { if (!success) return; Company[] companies = JsonUtility.FromJson<Companies>(response).companies; var company = companies.First(c => c.display_name == company_name); company_id = company.id; // どの打刻が可能かを問い合わせて、結果をTimeClocksControllerに引き渡す処理 } // 打刻 public void PostTimeClocks(string type) { string endpoint = "https://api.freee.co.jp/hr/api/v1/employees/" + employee_id + "/time_clocks"; // 打刻処理 } }
で、このクラスを適当なGameObjectにアタッチして、次のように値を入れていきます。
App ID
Secret
Redirect URL
Authorization_code
にはさきほどのアプリケーション登録で取得したそれぞれの情報を、Company_name
には人事労務freeeの事業所名、Employee_id
には自分の従業員IDを記入します。これで打刻APIにリクエストを送るために必要な情報が揃います(従業員ID、gistでは取得用のスクリプトを書いていますが、めんどくさい人はこちらの記事を参考にして取得してください)。
打刻入力のUI
自分のお気に入りキャラクターは「ユニティちゃん」です。本名は「大鳥こはく」さんで、ユニティ・テクノロジーズ・ジャパン公式のキャラクターです。ライセンスに準拠する形であれば、3Dモデルデータ等が無償で利用できます。さらに素晴らしいことに、表情や基本的なアニメーションなどがはじめから作られているので、簡単な利用であれば自分で動きを作ったりする必要がありません。 ダウンロードページ
このユニティちゃんをお迎えしてUIを作っていきます。
「打刻したらお気に入りのキャラクターに教えてもらいたい」という動機ではじめましたが、どうせなら「出勤ボタンを押して出勤」とかではなく、キャラクターとのインタラクションによって打刻を実行したいという気持ちが湧いてきました。そこで「ユニティちゃんと数秒間見つめ合って打刻」というUIにしてみます。
まず、ダウンロードしたSDユニティちゃんアセットパッケージをUnityプロジェクト内にインポートし、SD_unitychan_humanoid
という名前のプレハブをシーン内に追加します。
ついでに、見つめ合っている時間を可視化するゲージを追加しました(見つめ合うとゲージがたまり、満タンになると打刻する)。これはuGUIの標準Sliderを調整して使っています。
肝心の「見つめ合う」判定ですが、まずSD_unitychan_humanoid
に初めからアタッチされているIKLookAt
コンポーネントを使って、自動でカメラの方を見続けてもらうことができます。下画像のように、LookAtObj
に、ユニティちゃんに見つめてほしいオブジェクト(ここではOVRCameraRig
のカメラなのでCenterEyeAnchor
)をアタッチします。これでカメラが動き回ってもユニティちゃんは常にカメラの方を見つめてくれます。あとはカメラがユニティちゃんの方を向いているのを検知すればOKです。*1
カメラがユニティちゃんを向いていることを検知するために、SD_unitychan_humanoid
に追加でSphereCollider
コンポーネントをアタッチします。ちょうどユニティちゃんの頭にくるように位置と大きさを調整します。
そして、カメラ側でものを見つめるGazePointer
クラスと、見つめられる側であるGazable
クラス、そしてGazable
クラスを継承した、私と見つめ合ってくれるGazableUnitychan
クラスを作成します(それぞれgist参照)。GazableUnitychan
クラスをSD_unitychan_humanoid
にアタッチします(gist)。
詳しくは長くなるので省略しますが、「カメラから飛ばしたRayがユニティちゃんの頭にあるSphereCollider
に数秒間ヒットしつづけたらTimeClocksController
のPostSimpleTimeClocks
メソッドを実行する」というアレです。
public class TimeClocksController { // (中略) public void PostSimpleTimeClocks() { _FreeeEventHandler.PostTimeClocks(simpleAvailableType(m_AvailableTypes)); // いまリクエストできる打刻の種類をm_AvailableTypesに格納しています } // 出勤が打刻できるなら出勤、退勤が打刻できるなら退勤のパラメータをつくる private string simpleAvailableType(string[] types) { if (Array.IndexOf(types, "clock_in") >= 0) { return "clock_in"; } else if (Array.IndexOf(types, "clock_out") >= 0) { return "clock_out"; } else { return ""; } } }
これで見つめ合ったら打刻のUIができました。この時点でだいぶ幸せではあるんですが、当初の目的である「打刻したらお気に入りのキャラクターが声をかけてくれる」の部分をつくっていきます。
打刻完了時のユニティちゃん反応UI
特に理由はありませんが出勤よりも退勤を喜んでほしいので、
- 出勤打刻時は微笑んでくれる
- 退勤打刻時は喜びのあまりジャンプしてくれる
という感じにします。
そのあたりの反応の処理をまとめるSystemMessageController
クラスを作ります。ユニティちゃんのリアクションやフキダシの動きなどはこのクラスに記載しています。詳細はgistを御覧ください。
public class SystemMessageController : MonoBehaviour { // 微笑みとともにフキダシが出る(引数によっては飛び跳ねてくれる) public void ShowMessageWithSmile(string message, bool Jumping = false, float remainTime = 5f) { if (Jumping) m_UnitychanAnimator.SetBool("Jump", true); ShowMessage(message, "smile@sd_hmd", 5f); } // 悲しそうな顔でフキダシが出る(エラーが出たときとか) public void ShowMessageWithSad(string message, float remainTime = 5f) { ShowMessage(message, "sad@sd_hmd", 5f); } // private関数諸々省略(gist参照) }
で、FreeeEventHandler
に書いていた打刻完了時の処理をこのように追記します。打刻が完了するとSystemMessageController
に処理を渡しつつ、また次の打刻可能種別を問い合わせしにいく、というやつです。
private void PostTimeClocksCallback(bool success, string response) { if (!success) return; TimeClock tc = JsonUtility.FromJson<PostTimeClocksResponse>(response).employee_time_clock; switch(tc.type) { case "clock_in": // 出勤打刻時 _SystemMessageController.ShowMessageWithSmile("出勤しました\n今日も一日頑張ろう!"); break; case "clock_out": // 退勤打刻時 _SystemMessageController.ShowMessageWithSmile("退勤しました\nおつかれさま!", true); // 退勤時は2番目の引数を入れてジャンプしてもらう break; } GetTimeClocksAvailableTypes(); // 次の打刻可能種別を問い合わせる }
こんな感じで打刻結果をユニティちゃんが通知してくれるUIができました。欲を言えば音声で通知してくれたりするとグッときますが、今回はフキダシです。
ビルド
UnityからOculusGoへビルドするには、Android SDKのインストールなど色々準備が必要です。参考になるページが色々あるのでそちらを御覧ください。気をつけることとしては、今回は簡易的にfreee APIのAuthorization codeをプロジェクト内に書き込んでいますが、Authorization codeの有効期限は10分間なので、ビルド前に発行して、すぐ書き込んでビルドする必要がある、ということでしょうか(いちどRefresh tokenが発行されたら端末に保存し、次回からはそちらを使うので、毎回発行する必要はありません)。
で、実際にビルドしたのが冒頭の動画です。
再掲
見つめ合うと勤怠打刻 pic.twitter.com/IRcHuDX6wv
— 人生 (@toofu__) 2018年11月28日
念のため、ブラウザでも確認してみます。
この実装により、
- Oculus Goを持って出社する
- Oculus Goをかぶる
- アプリを起動する
- ユニティちゃんと見つめ合って出勤打刻
- Oculus Goをはずす
- 作業開始
- 作業終了
- Oculus Goをかぶる
- アプリを起動する
- ユニティちゃんと見つめ合うと退勤打刻してユニティちゃんがジャンプ
- Oculus Goをはずす
という打刻フローが完成します。効率とは無縁の、やさしいやさしい世界が実現しました。
Oculus Riftの場合
さすがに上のフローだと自分以外にとって価値が無なので、もうちょっと利便性がないと厳しいかもしれません。そこで「普通にPCで作業をしていて、ふと、横を向いたらユニティちゃんがいて打刻できる」という感じでやっていこうと思います。その場合はOculusGoでは厳しいのですが、幸い手元にOculus RiftとWindowsPCが転がっていたので、これ用に調整を入れました。
デスクトップ画面を表示する
UnityにはuDesktopDuplicationというプラグインがあり、これを使うとWindows PCのデスクトップをサクッとVR上に表示することができます。一瞬で解決。すごい。
休憩とかもできるようにする
利便性を高めるという話なので、出退勤以外にも休憩も入れられるようにします。「見つめ合って打刻」というのをやめ、普通に出勤ボタンや退勤ボタン、休憩開始ボタン等を配置しました。
これにより、こんな感じになります。
VR退勤 #人事労務freee pic.twitter.com/eWCNqbVgh7
— 人生 (@toofu__) 2018年11月18日
これだと作業終了即退勤が実現でき、なおかつユニティちゃんからねぎらいの言葉をもらえる、ほどよいバランスなのではないでしょうか。
まとめ
こんな感じで、人事労務 freee の打刻APIを使って「お気に入りのキャラクターと触れ合いつつ、気がついたら打刻できていた」という状況を生み出すことができました。あまりの打刻したさにうっかり休日出勤してもいい。*2
途中から「これVRじゃなくてARのほうがいい感じになるのでは…?」という考えが頭をよぎったのですが、残念ながらHoloLensやMagicLeapは手元に転がっていなかったので、手元に来たときに試したいと思います。みなさんもぜひ freee APIを使って気持ちを高ぶらせてください。
明日の記事は機械学習のスペシャリスト、スモールビジネスAIラボのKenji Usuiさんです、お楽しみに。
ライセンス
この記事はユニティちゃんライセンス条項の元に提供されています