本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
今回は Dictionary 型で保持する視認オブジェクトのキーに InstanceID を利用するメモです。
Object.GetInstanceID
オブジェクトの InstanceID を返します
オブジェクトの InstanceID は常にユニークです。
docs.unity3d.com
視認オブジェクトを保持する
以下の記事で書き留めた通り、ホロモンは自身の周囲のオブジェクトに対して視野判定を行い、視認オブジェクトを検出します。
bluebirdofoz.hatenablog.com
検出したオブジェクトは Dictionary 型で管理し、その関連を取るためのキー値として Object.GetInstanceID を利用しました。
・FieldOfVisionCollection.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEditor; using System; // ToList使用のため using System.Linq; namespace HoloMonApp.FieldOfVisionSpace { /// <summary> /// 視界内の視界オブジェクトコレクション /// </summary> public class FieldOfVisionCollection : MonoBehaviour { /// <summary> /// 視界内の視認オブジェクトリスト /// </summary> private Dictionary<int, VisionObjectWrap> p_VisionObjectDictionary = new Dictionary<int, VisionObjectWrap>(); [SerializeField, Tooltip("視界内の視認オブジェクトリスト(Editor確認用)")] private List<VisionObjectWrap> p_FieldOfVisionWrapList; /// <summary> /// 視界内の特徴ハッシュ値リスト /// </summary> private Dictionary<int, int> p_VisionObjectFeatureHashDictionary = new Dictionary<int, int>(); [SerializeField, Tooltip("視界内の特徴ハッシュ値リスト(Editor確認用)")] private List<int> p_VisionObjectFeatureHashList; /// <summary> /// 発見イベント /// </summary> public Action<VisionObjectWrap> FindObjectWrapEvent; /// <summary> /// ロストイベント /// </summary> public Action<int> LostObjectNameEvent; /// <summary> /// 状態アップデートイベント /// </summary> public Action<VisionObjectWrap> UpdateStatusObjectWrapEvent; private void UpdateList() { # if UNITY_EDITOR // Editor確認用 if (EditorApplication.isPlaying) { p_FieldOfVisionWrapList = p_VisionObjectDictionary.Values.ToList(); p_VisionObjectFeatureHashList = p_VisionObjectFeatureHashDictionary.Values.ToList(); } # endif } /// <summary> /// オブジェクト追加 /// </summary> public void Add(VisionObjectWrap a_VisionObjectWrap) { p_VisionObjectDictionary.Add(a_VisionObjectWrap.Object.GetInstanceID(), a_VisionObjectWrap); p_VisionObjectFeatureHashDictionary.Add(a_VisionObjectWrap.Object.GetInstanceID(), a_VisionObjectWrap.CurrentStatusHash()); UpdateList(); FindObjectWrapEvent.Invoke(a_VisionObjectWrap); } /// <summary> /// オブジェクト削除 /// </summary> public bool Remove(GameObject a_Object) { bool result = Remove(a_Object.GetInstanceID()); return result; } /// <summary> /// 状態の更新チェック /// </summary> public bool CheckStatusUpdate() { bool isUpdated = false; foreach(int key in p_VisionObjectDictionary.Keys) { int currentStatusHash = p_VisionObjectDictionary[key].CurrentStatusHash(); if (currentStatusHash != p_VisionObjectFeatureHashDictionary[key]) { p_VisionObjectFeatureHashDictionary[key] = currentStatusHash; UpdateList(); UpdateStatusObjectWrapEvent.Invoke(p_VisionObjectDictionary[key]); isUpdated = true; } } return isUpdated; } /// <summary> /// VisionObjectの取得 /// </summary> public VisionObjectWrap GetVisionObject(GameObject a_Object) { return p_VisionObjectDictionary[a_Object.GetInstanceID()]; } /// <summary> /// 値の存在チェック /// </summary> public bool ContainsKey(GameObject a_Object) { return p_VisionObjectDictionary.ContainsKey(a_Object.GetInstanceID()); } /// <summary> /// キー一覧の取得 /// </summary> public List<int> KeyList() { return p_VisionObjectDictionary.Keys.ToList(); } /// <summary> /// 値一覧の取得 /// </summary> public List<VisionObjectWrap> ValueList() { return p_VisionObjectDictionary.Values.ToList(); } /// <summary> /// 指定リストに含まれないオブジェクトをコレクションから除去する /// </summary> public bool RemoveWithoutList(List<GameObject> a_CheckObjectList) { bool isRemoved = false; // オブジェクトInstanceIDのリストに全て変換する List<int> checkIdList = a_CheckObjectList.ConvertAll(obj => obj.GetInstanceID()); foreach (int key in p_VisionObjectDictionary.Keys.ToList()) { if (!checkIdList.Contains(key)) { // 検出されていなければコレクションから削除する Remove(key); isRemoved = true; } } return isRemoved; } /// <summary> /// オブジェクト削除(ID指定) /// </summary> private bool Remove(int a_InstanceID) { bool removed = p_VisionObjectDictionary.Remove(a_InstanceID); if (removed) { p_VisionObjectFeatureHashDictionary.Remove(a_InstanceID); UpdateList(); LostObjectNameEvent.Invoke(a_InstanceID); } return removed; } } }
動作確認
シーンを再生して動作を確認します。
ハンドオブジェクトやボールオブジェクトを視認すると、検出リストにオブジェクトが追加されます。
視界から外れたオブジェクトは InstanceID チェックによる除去処理によって削除されます。