読者です 読者をやめる 読者になる 読者になる

チワの備忘録

個人的にやっていることの技術メモ

Unityでカレンダー作ったメモ


Unityでこんな感じのカレンダーを作りました。
(WPFでやれとは言わない)
作ってみて、C#のDateTimeについて知らないことが思ったより沢山あったのでそれのメモ。
あと、UniRxを久しぶりにちょろっと使ってみて、結構忘れてたのでメモ。

作り方

まず、カレンダーの日付のマスをHierarchyのCreate->UI->Buttonで作ります。
7×6行で42個あれば十分です。
あとはこれらのButtonの親に空オブジェクトを設定しておきます。
また、カレンダーの月を変えるためのNext、Prevボタンも適当な場所に配置しておきます。
f:id:tiwaluna:20170217211911p:plain
Hierarchyはこんな感じになります。
Calendar、Row0~5が空オブジェクトになります。それぞれのRowオブジェクトの子にButtonオブジェクトが7つ入ります。この親子関係を利用して、Calendarにスクリプトを設定します。
f:id:tiwaluna:20170217231858p:plain

ソースコード

  1. カレンダーの管理スクリプト
    Calendarオブジェクトにアタッチします。

  2. 日付マスのスクリプト
    各Buttonにアタッチします。(数が多いのでCalendarManagerから動的にアタッチする。)

解説

  1. CalendarManager.cs

    • 初期設定

    まず、Unity上でnextButtonとprevButtonに先ほど作ったNext、PrevのButtonオブジェクトを指定しておきます。

    • 流れ

    Startメソッド内の処理を順に説明していきます。
    とりあえず、current変数にDateTime.Todayより現在日時を入れます。

    1. InitCalendarComponent
       InitCalendarComponentメソッドで各ButtonにCalendarButtonをアタッチします。ついでにオブジェクトとコンポーネントを保存しておきます。
       各Buttonの取得はGetChildを使って取得します。このスクリプトがアタッチしている空オブジェクトがrootオブジェクトなので、先ほどのHierarchyの構造を活用して取得します。
       何番目のRowオブジェクトのColumnであるかでそのButtonが何行目の何列目かわかります。このカレンダーは1行あたり7列で固定されているので、7×行数 + 列数で左上のButtonから数えて何番目なのかが分かります。これを利用してobjDays配列およびDays配列に保存しておきます。
    2. SetCalendar
       SetCalendarメソッドで各CalendarButtonオブジェクトに対応した日付を指定していきます。 
       first変数はSystem.DateTime型で、今月の1日目の日付を表します。DateTimeは(年, 月, 日)をint型で指定して作れるのでcurrentの年月を指定して、日にちに1を入れます。
       また、先月、来月の取得はcurrent.AddMonths()を使います。current.AddMonths(1)で来月、current.AddMonths(-1)で先月を取得します。
       このカレンダーでは空いたマスに先月、今月の日にちを表示したいので、そのための変数を用意します。来月の分は1から数えますが、先月の場合はまず、DateTime.DaysInMonthメソッドで先月の日数を取得します。その日数から空いたマスの日数分を減らします。空いたマスは今月の一日の曜日から計算します。曜日の取得はfirst.DayOfWeekから取得します。DayOfWeekは列挙型なのでint型にキャストします。DateTimeの曜日は日曜~土曜の間で(0~6)となっているので、先月の日数 - 今月の1日の曜日 + 1で空いたマスを計算できます。
       あとは条件に合ったマスに日時を指定していきます。
    3. UniRx部分について
       まず、自分が深い理解ができてないので、非常にざっくりとした説明しかできないので申し訳ないですorz。
       nextButton.onClick.AsObservable()という部分でNextボタンが押されたかどうかを常に監視します。もし押された場合、.Subscribe内の処理が行われます。Prevボタンも同様です。
      完璧に使い方を忘れていたので参考のリンク
      【OnClickAsObservable】UniRxでボタンのクリック回数をテキストに表示する【SubscribeToText】 - Qiita

  2. CalendarButton.cs
     UniRxで値の変動を監視します。各マスの設定された日付はDateValueに保存されていて、CalendarManagerから変更されます。UniRxのObserveEveryValueChangedを使ってDateValueの値の変動を取得します。ここではDateValueの値が変更された場合、.Subscribe内の処理が行われます。
    【UniRx】ObserveEveryValueChangedでフレーム間での値の変動を監視する - Qiita
     値が変動したらテキストの値を変えて、土日などは色を変えたいので、DateValueの値を使って色の判定をGetColorDayOfWeekメソッドでします。


以上のスクリプトを踏まえて、他にも年や月を表示する処理を作れば冒頭のgifみたいなカレンダーができます。(たぶん)
 わざわざUnityで作らなくても良かった気もしますが、一応、Unityのオブジェクトとしてカレンダーを作ったのでここから更にカレンダーを他のUnityのアプリに組み込み易いかもです(こなみ)。
あと傾けたりとか。
f:id:tiwaluna:20170217234902p:plain

おわり

とりあえず実質的な初めてのブログ記事。
正直誰に向けて書いてんだか良く分からない感じになってしまいました。(必要なUnityの前提知識が多い)
あと、普段は感覚的になんとなくの理解でプログラミングしているので(UniRx関係とか)、ブログ記事で文章にしてみて、人に説明するのが難しいというか説明できないのをすごく実感したので精進したいと思います。
こんな記事で書くのに3時間かかってしまったのでこれからは無駄な説明は省いていかないときつそう。

はじめ

ブログの目的

趣味のプログラミングでやったことを忘れないようにメモしていきたい。

ついでに文章を書く練習もする。