• 当初スライドはGameObjectだった

    • AttayList<GameObject> slidesで管理されていた
    • 物理演算を実装するにあたって更新ベクトルを Dictionary<GameObject, Vector3> updateVecで作った
    • 赤枠ハイライトのために赤枠オブジェクト GameObject highlighter と、それがハイライトすべき対象を指し示す GameObject to_highlight を作った
    • 複数選択可能にしたことでハイライト対象が複数になった
    • 赤枠オブジェクトがスライドの個数と同量発生する
  • そろそろきな臭いのでリファクタリングする

  • public class Slideを作る

  • MonoBehaviourを継承しないことにした

    • 正解かどうかはわからない
  • これがスライド自体のGameObjectとハイライト用の赤枠GameObjectの2つを生成

  • GameObjectに”Slide”タグを付与

  • 物理演算の更新ベクトルはSlideのメンバに。

  • レイキャストのヒット対象はGameObjectが取れてくるが、この設計ではそのGameObjectからSlideオブジェクトを得たい

    • なんかより良い設計がありそうな気がするが…
    • こんなのを作ってAddComponentした cs
public class GetSlide : MonoBehaviour
{
    public Slide slide;
}
- Slide自体をAddComponentする選択肢はなかった
    - AddComponentは型引数を取ってインスタンス化するため
  • スライドの管理をしていたMakeSlide.csの中のエラーは全部解消した

  • LaserPointer.csの中のエラーを確認

    • 複数選択を実装したときに突貫工事で作られたDictionary<GameObject, bool> is_selected = null;が問題。
    • これは小手先で直すよりも今回のリファクタリングでしっかり吸収されるべき
    • なので、まずは複数選択関連の処理を丸ごとコメントアウトしてコンパイルを通す。
  • 実行時エラー: highlighterが単一オブジェクトとして存在していると思って呼びに行ってNullPointerException

    • もはや使われない単一オブジェクト用のメンバは削るべき
    • コンパイルエラーによって直すべきところが明確になる
  • 従来の単一選択のコードを単純に置き換えるならobj.GetComponent<GetSlide>().slide.highlited = true;

    • だがそんなスライドの内部構造がレーザーポインター側に露出しているのはおかしいので単一選択用のメソッドを用意してそれを呼ぶようにする
  • ハイライトの色を変えるコードはいったんコメントアウト

  • ハイライト赤枠の縮尺などで若干手間取ったが、単一選択は元通り動くようになった

  • 複数選択は、単に今回のオブジェクト統合の変更に追従させるだけではなくしっかり考えるべき

  • 選択状態に「単一選択」しかないところに後付けで「複数選択」を足したのでこんなことになっている cs

GameObject selected;
Dictionary<GameObject, bool> is_selected = null;
  • selectedがnot nullの時には単一選択、is_selectedがnot nullの時には複数選択、という状況。

  • とりあえず現状どういうコンパイルエラーが起きるのか確認しようとコメントアウトを戻してみたら、単にSlideとGameObjectの違いだけだったので簡単に治った

  • 予想外に、あっさり動くぞ

  • 複数選択時にハイライトがされない(もとから)

    • is_selected[y] = true;してるところでs.highlited = true;したらあっさり動いた
    • 選択解除時に元に戻らないなどを修正
    • 移動時にis_selectedを確認して選択されているものだけを動かしているので、これをhighlightedなものだけ動かすように変更したら見た目と挙動が一致してよいかもしれない
      • is_selectedを削除して問題なく動いている
  • ハイライト色の変更

    • 以前は単一選択しかなかったので、単一のオブジェクトのマテリアルを変更するだけだった
    • 複数選択時に色を変更するか?
      • マテリアルを共通化すべきか?
    • 確認したらそもそも単一選択時にレーザーポインターをテレポートポータルに一定以上近づけた場合にだけ色が変わる
    • 単一選択時にハイライトの色を変えるメソッドを追加したが、これ将来的に複数選択時に呼んで「色が変わらないぞ」とか言いそうだな…
  • 単一選択時のドラッグの挙動が絶対位置移動

    • 複数選択の方は実装が新しいのでクオータニオンで変換している

    • 挙動の共通化、複数選択ハイライトの常時表示、複数選択モードで1つだけ選ばれた場合に単一選択モードにフォールバック

    • 常時ハイライトをして速度的に大丈夫か?

      • 物理演算なしで57FPS、発生中が37で、終了後が48ぐらい
      • 常時ハイライトをしたら38ぐらい
      • Unity Editor 上での話なので実機だとどうなのかわからないけど…まあ減少比率的には即座にダメというほどではなさそう
    • 究極的にはこの2行の差

    • single selected.transform.position = ray.origin + ray.direction * distance;

    • multiple x.transform.position = diff * (start_positions[x.gameObject] - eye) + eye;

      • Quaternion diff = Quaternion.FromToRotation(start_direction, ray.direction);
    • あっ、まだGameObjectをキーにしたDictionaryがいた

      • Dictionary<GameObject, Vector3> start_positions = new Dictionary<GameObject, Vector3>();
    • Slideオブジェクトにdrag_start_positionってメンバを持たせよう

      • startDraggingとendDraggingを作って、保留されてた「複数ドラッグ時に単一ドラッグ時と同様に物理演算オフ」も兼ねた
  • まあすんなり動かないこともある

    • 雰囲気的に物理演算に何か不調が起こってそう
    • 非選択状態でなぜかColliderがdisabledされている
    • disableしそうなところをコメントアウトしていく
    • startDraggingの中のをコメントアウトしたら、Colliderはdisableされなくなったが、一歩進んでやはり止まる
    • ああ、なるほど。複数選択の対象確定時に、当初はマウスダウンで対象探索を開始していたのでハイライト対象にすると同時にドラッグ開始をしていたが、常時ハイライトすることにしたためマウスダウンをしてないのにドラッグ開始されてしまうバグ
  • 単一ドラッグ開始時にgetSlideが引数nullで呼ばれている

    • うーむ、これは時間帯的に、今日解決しようとしない方が早く解決しそうだ。次回のタスクにしよう