本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
今回はホロモンが満腹時や疲労時に特定の行動をしなくなるメモです。
体調パラメータの参照
ホロモンの空腹度や疲労度は以下で作成した内部パラメータを参照して取得します。
現在は Singleton パターンを利用して実装しているため、任意のスクリプトからパラメータが自由に参照できます。
bluebirdofoz.hatenablog.com
食事と遊び行動時の判定
視界の変化などにより、食事や遊び行動がキックされた際にこれらのパラメータを以下のように参照してチェックすることができます。
/// <summary> /// 現在満腹状態かチェックする /// </summary> /// <returns></returns> private bool CheckStatusIsFullStomach() { bool isCheckStatus = false; // 空腹度が100以上なら満腹と判定する if (HoloMonConditionLifeSingleton.Instance.IReadOnlyReactivePropertyHoloMonLifeStatus.Value.HungryPercent >= 100) { isCheckStatus = true; } return isCheckStatus; } /// <summary> /// 現在疲労状態かチェックする /// </summary> /// <returns></returns> private bool CheckStatusIsTired() { bool isCheckStatus = false; // 疲労度が0以下なら疲労と判定する if (HoloMonConditionLifeSingleton.Instance.IReadOnlyReactivePropertyHoloMonLifeStatus.Value.StaminaPercent <= 0) { isCheckStatus = true; } return isCheckStatus; }
満腹時は食事行動の開始がキャンセルされ、また疲労時は遊び行動の開始がキャンセルされるように改修しました。
・HoloMonAICenter.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using Cysharp.Threading.Tasks; using UniRx; using HoloMonApp.ActionSpace; using HoloMonApp.ConditionSpace; using HoloMonApp.SaveDataSpace; using HoloMonApp.FieldOfVisionSpace; using HoloMonApp.DataFormatSpace; namespace HoloMonApp.CommonSpace { /// <summary> /// ホロモンの目的行動を定義する /// </summary> public class HoloMonAICenter : MonoBehaviour { /// <summary> /// 現在の行動目的 /// </summary> [SerializeField, Tooltip("現在の行動目的")] private PurposeInformation p_CurrentPurposeInformation; /// <summary> /// ホロモンの行動コントローラの参照 /// </summary> [SerializeField, Tooltip("ホロモンの行動コントローラの参照")] private HoloMonPorposeController p_HoloMonPorpuseController; /// <summary> /// ホロモンのデータセーブコントローラの参照 /// </summary> [SerializeField, Tooltip("ホロモンのデータセーブコントローラの参照")] private HoloMonDataController p_HoloMonDataController; /// <summary> /// 開始処理 /// </summary> void Start() { // 最初の行動目的は待機状態とする p_CurrentPurposeInformation = new PurposeInformation(new PurposeStandbyData()); } /// <summary> /// 定期処理 /// </summary> void Update() { } /// <summary> /// 現在のホロモンの目的意識を返す /// </summary> /// <returns></returns> public HoloMonPurposeType PurposeType() { return p_CurrentPurposeInformation.HoloMonPurposeType; } /// <summary> /// アクションの完了チェック /// </summary> /// <param name="a_ActionResult"></param> private bool CheckActionComplete(HoloMonPurposeStatus a_ActionResult) { if(a_ActionResult == HoloMonPurposeStatus.Cancel) { // アクションがキャンセルで終了していた場合(割込みがあった場合) // 本スレッドを終了する return false; } switch(a_ActionResult) { case HoloMonPurposeStatus.Achievement: // TODO : 目標達成時の後処理を行う break; case HoloMonPurposeStatus.Missing: // TODO : 目標未達成時の後処理を行う break; default: break; } // アクションがキャンセル以外で完了していた場合は待機スレッドを開始する // TODO : 未達成の目的が残っていた場合はそちらの処理を再開する RequestStandby(); return true; } /// <summary> /// 待機状態の要求 /// </summary> public bool RequestStandby() { Debug.Log("RequestStandby"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // 待機行動を実行する ExecuteStandbyAsync(); return true; } /// <summary> /// プレイヤーに注目する要求 /// </summary> public bool RequestLookPlayer() { Debug.Log("RequestLookPlayer"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // プレイヤーへの注視を実行する ExecuteLookPlayerAsync(); return true; } /// <summary> /// プレイヤー追跡の要求 /// </summary> public bool RequestTrackingPlayer() { Debug.Log("RequestTrackingPlayer"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // プレイヤー追跡を実行する ExecuteTrackingPlayerAsync(); return true; } /// <summary> /// じゃんけん開始の要求 /// </summary> public bool RequestJanken() { Debug.Log("RequestJanken"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // じゃんけん行動を実行する ExecuteJankenAsync(); return true; } /// <summary> /// 眠り開始/停止の要求 /// </summary> public bool RequestSleep(bool onoff) { Debug.Log("RequestSleep"); if (onoff) { // 睡眠中でなければ眠る if (!CheckPurposeIsSleep()) { // 眠り行動を実行する ExecuteSleepAsync(); } else { Debug.Log("Cancel : Current Sleep"); return false; } } else { // 睡眠中なら目を覚ます if (CheckPurposeIsSleep()) { // 待機行動を実行する ExecuteStandbyAsync(); } else { Debug.Log("Cancel : Current Awake"); return false; } } return true; } /// <summary> /// ダンス開始の要求 /// </summary> public bool RequestDance() { Debug.Log("RequestDance"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // ダンス行動を実行する ExecuteDanceAsync(); return true; } /// <summary> /// 食事行動の要求 /// </summary> public bool RequestGiveFood(GameObject a_FoodObject) { Debug.Log("RequestGiveFood"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // 満腹中は反応はするが行動しない if (CheckStatusIsFullStomach()) { Debug.Log("Cancel : Current FullStomach"); return false; } // 食事行動を実行する ExecuteGiveFoodAsync(a_FoodObject); return true; } /// <summary> /// ボール遊び行動の要求 /// </summary> public bool RequestGiveBall(GameObject a_BallObject) { Debug.Log("RequestGiveBall"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // 疲労中は反応はするが行動しない if (CheckStatusIsTired()) { Debug.Log("Cancel : Current Tired"); return false; } // 待機行動を実行する ExecuteGiveBallAsync(a_BallObject); return true; } /// <summary> /// うんち行動の要求 /// </summary> public bool RequestPutoutShit() { Debug.Log("RequestPutoutShit"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // うんち行動を実行する ExecutePutoutShitAsync(); return true; } /// <summary> /// 待て行動の要求 /// </summary> public bool RequestStayWait() { Debug.Log("RequestStayWait"); // 睡眠中は行動しない if (CheckPurposeIsSleep()) { Debug.Log("Cancel : Current Sleep"); return false; } // 待て行動を実行する ExecuteStayWaitAsync(); return true; } /// <summary> /// 待機状態の実行 /// </summary> public async UniTask<bool> ExecuteStandbyAsync() { // 待機の行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeStandbyData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// プレイヤーへの注目行動の実行 /// </summary> public async UniTask<bool> ExecuteLookPlayerAsync() { // プレイヤーに注目する行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeLookFriendData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// プレイヤー追跡の実行 /// </summary> public async UniTask<bool> ExecuteTrackingPlayerAsync() { // プレイヤーを捜索して追跡する行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeMoveTrackingData(ObjectUnderstandType.FriendFace)); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// じゃんけん行動の実行 /// </summary> public async UniTask<bool> ExecuteJankenAsync() { // じゃんけんを行う行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeJankenData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// 眠り行動の実行 /// </summary> public async UniTask<bool> ExecuteSleepAsync() { // 睡眠をとる行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeSleepData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// ダンス行動の実行 /// </summary> public async UniTask<bool> ExecuteDanceAsync() { // ダンスを行う行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeDanceData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// 食事行動の実行 /// </summary> public async UniTask<bool> ExecuteGiveFoodAsync(GameObject a_FoodObject) { // 食事を取る行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeMealFoodData(a_FoodObject)); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// ボール遊び行動の実行 /// </summary> public async UniTask<bool> ExecuteGiveBallAsync(GameObject a_BallObject) { // ボールで遊ぶ行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeCatchBallData(a_BallObject)); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// うんち行動の実行 /// </summary> public async UniTask<bool> ExecutePutoutShitAsync() { // うんちをする行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposePutoutShitData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// 待て行動の実行 /// </summary> public async UniTask<bool> ExecuteStayWaitAsync() { // 待て(おすわり)を行う行動目的を設定する p_CurrentPurposeInformation = new PurposeInformation(new PurposeStayWaitData()); // 行動目的の処理を開始する HoloMonPurposeStatus result = await p_HoloMonPorpuseController.StartPorpuseAsync(p_CurrentPurposeInformation); // アクションの完了チェックを行う return CheckActionComplete(result); } /// <summary> /// 実行待機中のロジックに割込み通知を行う /// </summary> public bool TransmissionInterrupt(InterruptInformation a_InterruptInfo) { bool isProcessed = p_HoloMonPorpuseController .TransmissionInterrupt(a_InterruptInfo); return isProcessed; } /// <summary> /// データ書き込みの要求 /// </summary> public void RequestDataSave() { // 身体状態をデータに設定する HoloMonBodyStatus bodyStatus = HoloMonConditionBodySingleton. Instance.IReadOnlyReactivePropertyHoloMonBodyStatus.Value; p_HoloMonDataController.SetBodyStatus(bodyStatus); // 生活状態をデータに設定する HoloMonLifeStatus lifeStatus = HoloMonConditionLifeSingleton. Instance.IReadOnlyReactivePropertyHoloMonLifeStatus.Value; p_HoloMonDataController.SetLifeStatus(lifeStatus); // データを書き込む p_HoloMonDataController.ExecuteSave(); } /// <summary> /// データ読み込みの要求 /// </summary> public void RequestDataLoad() { // データを読み込む bool isLoaded = p_HoloMonDataController.ExecuteLoad(); // データを読み込めたか否か if (isLoaded) { // データから身体状態を設定する HoloMonConditionBodySingleton.Instance.SetHoloMonData(p_HoloMonDataController.GetSaveData()); // データから生活状態を設定する HoloMonConditionLifeSingleton.Instance.SetHoloMonData(p_HoloMonDataController.GetSaveData()); } } /// <summary> /// 現在の行動がスタンバイまたは注視待機中か否か /// </summary> /// <returns></returns> private bool CheckPurposeIsStanbyAndLooking() { bool isCheckPurpose = false; switch (p_CurrentPurposeInformation.HoloMonPurposeType) { // スタンバイまたは注視待機中 case HoloMonPurposeType.Standby: case HoloMonPurposeType.LookFriend: isCheckPurpose = true; break; default: break; } return isCheckPurpose; } /// <summary> /// 現在満腹状態かチェックする /// </summary> /// <returns></returns> private bool CheckStatusIsFullStomach() { bool isCheckStatus = false; // 空腹度が100以上なら満腹と判定する if (HoloMonConditionLifeSingleton.Instance.IReadOnlyReactivePropertyHoloMonLifeStatus.Value.HungryPercent >= 100) { isCheckStatus = true; } return isCheckStatus; } /// <summary> /// 現在疲労状態かチェックする /// </summary> /// <returns></returns> private bool CheckStatusIsTired() { bool isCheckStatus = false; // 疲労度が0以下なら疲労と判定する if (HoloMonConditionLifeSingleton.Instance.IReadOnlyReactivePropertyHoloMonLifeStatus.Value.StaminaPercent <= 0) { isCheckStatus = true; } return isCheckStatus; } /// <summary> /// 現在の行動が眠り行動中かチェックする /// </summary> /// <returns></returns> private bool CheckPurposeIsSleep() { bool isCheckPurpose = false; switch (p_CurrentPurposeInformation.HoloMonPurposeType) { // 眠り行動中 case HoloMonPurposeType.Sleep: isCheckPurpose = true; break; default: break; } return isCheckPurpose; } } }
動作確認
シーンを再生し、動作を確認します。
ホロモンに沢山お肉を与えていきます。
体調パネルを開いて空腹度が100%になり、満腹状態になったことを確認します。
満腹状態ではホロモンはお肉に視線こそ向けますが、受け取って食事することはしなくなりました。