¡¡NavMeshAgent ¥³¥ó¥Ý¡¼¥Í¥ó¥È¤òÍøÍѤ·¤¿ºÝ¤Î½èÍý¤ò¥Ù¡¼¥¹¤Ë½¤Àµ¤ò¹Ô¤¤¤Þ¤¹¡£
¡¡using ¤ÎÀë¸À¤ä¡¢¥¯¥é¥¹¤Î·Ñ¾µÉôʬ¤Ê¤É¤ËÃí°Õ¤·¤Ê¤¬¤éµ½Ò¤·¤Æ¤¯¤À¤µ¤¤¡£
¤É¤Î¤è¤¦¤Ê½èÍý¤ò¼ÂÁõ¤·¤Æ¤¤¤ë¤Î¤«¤òÍý²ò¤·¤Ê¤¬¤é³Ø½¬¤¹¤ë¤³¤È¤Ç¡¢¼«Ê¬¤Ç¥¹¥¯¥ê¥×¥È¤òºîÀ®¤¹¤ëºÝ¤ËÌòΩ¤Á¤Þ¤¹¡£
¡¡¼ç¤Ê½èÍý¤È¤·¤Æ¤Ï¡¢¿·¤·¤¯ SearchPlayer ¥¹¥¯¥ê¥×¥È¤Ë¤¢¤ë ReactiveProperty ¤Î IsSearch ¤ò¹ØÆɤ¹¤ë½èÍý¤òÄɲ䷤Ƥ¤¤Þ¤¹¡£
¤³¤ÎÃͤÎÊѲ½¤Ë±þ¤¸¤Æ¡¢¾ã³²Êª¤Î¥¹¥Æ¡¼¥È¤ò×Ñ×Ë¢ªÄÉÈø¡¢ÄÉÈø¢ªÂÔµ¡¢ª×Ñ×ˤ˼«Æ°Åª¤ËÀÚ¤êÂؤ¨¤Þ¤¹¡£
¡¡¸ÀÍդˤ¹¤ë¤È´Êñ¤Ç¤¹¤¬¡¢¼ÂºÝ¤Ë¤Ï¿·¤·¤¯£¶¤Ä¤Î¥á¥½¥Ã¥É¤òºîÀ®¤·¤Æ¡¢Ï¢Æ°¤µ¤»¤Æ¤¤¤Þ¤¹¡£
¤½¤Î¤¿¤á¡¢¤³¤³¤Ë¼ÂÁõ¤¹¤ë½èÍý¤¬°ìÈÖÊ£»¨¤«¤Ä¡¢½ÅÍפʽèÍý¤Ë¤Ê¤ê¤Þ¤¹¡£
¡¡½èÍý¤ò¥¤¥á¡¼¥¸¤·¤Ä¤Ä¡¢¼ÂÁõ¤ò¹Ô¤¦¤è¤¦¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
MovingObstacle.cs
<= ¥¯¥ê¥Ã¥¯¤¹¤ë¤È³«¤¤Þ¤¹
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UniRx;¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡//¡¡<=¡¡¡ù¡¡Äɲä·¤Þ¤¹
using Cysharp.Threading.Tasks;¡¡¡¡¡¡¡¡//¡¡<=¡¡¡ù¡¡Äɲä·¤Þ¤¹
using System.Threading; //¡¡<=¡¡¡ù¡¡Äɲä·¤Þ¤¹
[RequireComponent(typeof(NavMeshAgent))]
public class MovingObstacle : ObstacleBase
{
[SerializeField]
private Transform[] targetTrans;
[SerializeField]
private float[] waitTimes;
private NavMeshAgent agent;
private int posCount = 0;
////*¡¡¿·¤·¤¤ÊÑ¿ô¤ÎÀë¸À¤ò£±¤ÄÄɲá¡*////
[SerializeField]
private SearchPlayer searchPlayer;
////*¡¡¤³¤³¤Þ¤Ç¡¡*////
void Start()
{
// ¥Ç¥Ð¥Ã¥°ÍÑ
SetUpObstacle();
}
/// <summary>
/// ½é´üÀßÄê
/// </summary>
public override void SetUpObstacle() {
if (TryGetComponent(out agent)) {
StartCoroutine(MoveObstacleByAgent());
}
////*¡¡½èÍý¤òÄɲá¡*////
searchPlayer.IsSearch.Subscribe(x => ChangeObstacleState(x)).AddTo(gameObject);
////*¡¡¤³¤³¤Þ¤Ç¡¡*////
}
/// <summary>
/// NavMeshAgent ¤Ë¤è¤ë°ÜÆ°
/// </summary>
/// <returns></returns>
private IEnumerator MoveObstacleByAgent() {
Debug.Log("°ÜÆ°³«»Ï");
agent.destination = targetTrans[posCount].position;
yield return new WaitForSeconds(waitTimes[posCount]);
while (agent.velocity.sqrMagnitude > 0.0f) {
yield return null;
}
Debug.Log("°ÜÆ°½ªÎ»");
yield return new WaitForSeconds(waitTimes[posCount]);
// TODO ¸«²ó¤¹½èÍý¤òÆþ¤ì¤ë
// ¥é¥ó¥À¥à¤Ê²ó¿ô·«¤êÊÖ¤¹
posCount = ++posCount % targetTrans.Length;
// ¼¡¤ÎÃÏÅÀ¤Ø¤Î°ÜÆ°
StartCoroutine(MoveObstacleByAgent());
}
////*¡¡¿·¤·¤¯¥á¥½¥Ã¥É¤ò£¶¤ÄÄɲá¡*////
/// <summary>
/// ¾ã³²Êª¤Î¥¹¥Æ¡¼¥È¤ÎÀÚ¤êÂؤ¨
/// ¹ØÆɤ·¤Æ¤¤¤ë SearchPlayer ¤Î IsSearch ¤Ë¹ç¤ï¤»¤ÆÀÚ¤êÂؤ¨¤ë
/// </summary>
/// <param name="isSearch"></param>
private void ChangeObstacleState(bool isSearch) {
¡¡¡¡¡¡¡¡// °ú¿ô¤ÎÃͤ˱þ¤¸¤Æ¡¢¸½ºß¤Î¥¹¥Æ¡¼¥È¤òÀßÄꤹ¤ë
currentObstacleState = isSearch ? ObstacleState.Search : ObstacleState.Idle;
¡¡¡¡¡¡¡¡// ¥¹¥Æ¡¼¥È¤Ë±þ¤¸¤Æ°Û¤Ê¤ë½èÍý¤ò¹Ô¤¦¤³¤È¤Ç¡¢×Ñ×Ë¡¦ÄÉÈøµ¡Ç½¤ò¼«Æ°²½¤¹¤ë
if (currentObstacleState == ObstacleState.Search) {
MoveObstacleByAgentToTarget();
} else {
ResetTarget();
}
}
/// <summary>
/// ¥×¥ì¥¤¥ä¡¼¤Î°ÌÃÖ¤òÌÜɸÃÏÅÀ¤È¤·¤Æ°ÜÆ°
/// </summary>
private void MoveObstacleByAgentToTarget() {
if (searchPlayer.player == null) {
return;
}
Debug.Log("¥×¥ì¥¤¥ä¡¼¤Ø¤Î°ÜÆ°³«»Ï");
agent.SetDestination(searchPlayer.player.transform.position);
}
/// <summary>
/// ¥¨¡¼¥¸¥§¥ó¥È¤Î¥Ñ¥¹¤ò¥ê¥»¥Ã¥È¤·¡¢ºÆÅÙ¡¢¼«Æ°·ÐÏ©¤ËÌ᤹
/// </summary>
private void ResetTarget() {
¡¡¡¡¡¡¡¡// ÌÜŪÃÏÅÀ¤òºï½ü
agent.ResetPath();
currentObstacleState = ObstacleState.Wander;
¡¡¡¡¡¡¡¡// ×Ñ×˽èÍý
StartCoroutine(MoveObstacleByAgent());
Debug.Log("¥¨¡¼¥¸¥§¥ó¥È ºÆÀßÄê");
}
¡¡¡¡// Update¡¡¥á¥½¥Ã¥É¤ò async + UniTask ¤Ë¤·¤Æ await ¤Ë¤è¤ëÈóƱ´ü½èÍý¤¬¼Â¹Ô¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë
async UniTask Update() {
if (searchPlayer.player == null) {
return;
}
if (currentObstacleState != ObstacleState.Search) {
return;
}
if (agent) {
// ¥×¥ì¥¤¥ä¡¼¤ÎºÂɸ¹¹¿·¤Ë¹ç¤ï¤»¤Æ¡¢ÌÜɸÃÏÅÀ¤â¹¹¿·
agent.SetDestination(searchPlayer.player.transform.position);
// °ìÄêµ÷Î¥¤Ë¶á¤Å¤¤¤¿¤é
if (agent.remainingDistance <= 0.25f) {
Debug.Log("¥×¥ì¥¤¥ä¡¼Êá³Í");
// ¥²¡¼¥à¥ª¥Ö¥¸¥§¥¯¥È¤ÏÇ˲õ¤µ¤ì¤¿¾ì¹ç¤Ë¤Ï¡¢ÅÓÃæ¤Ç½èÍý¤ò¥¥ã¥ó¥»¥ë¤Ç¤¤ë¤è¤¦¤Ë¤·¤Æ¤ª¤¯
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡// ¤³¤Î¾ðÊó¤ò°·¤¦¤¿¤á¤Ë using System.Threading ¤ÎÀë¸À¤¬É¬Í×
CancellationToken token = this.GetCancellationTokenOnDestroy();
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡// ÈóƱ´ü½èÍý¤òÂÔµ¡¤·¤Ä¤Ä¼Â¹Ô¤¹¤ë
await TriggerObstacleAsync(token);
}
}
}
/// <summary>
/// ¥×¥ì¥¤¥ä¡¼¤È¾ã³²Êª¤¬ÀÜ¿¨¤·¤¿ºÝ¤Î½èÍý¤Î async ÈÇ
/// </summary>
public async override UniTask TriggerObstacleAsync(CancellationToken cancellationToken) {
// ¥¹¥Æ¡¼¥ÈÀÚ¤êÂؤ¨¡£IsSearch ¤¬ÀÚ¤êÂؤï¤ë¤È¼«Æ°Åª¤Ë×Ñ×ˤ¹¤ë
currentObstacleState = ObstacleState.Idle;
await HoldPlayerAsync(cancellationToken);
}
/// <summary>
/// ¥×¥ì¥¤¥ä¡¼¤ÎÊá³Í
/// </summary>
/// <returns></returns>
private async UniTask HoldPlayerAsync(CancellationToken cancellationToken) {
// Êá³Í±é½Ð¡£±é½Ð½ªÎ»¤Þ¤ÇÂÔµ¡
await HoldEffectAsync(cancellationToken);
// TODO Êá³Í¾õÂÖ¤ò GameStateManager ¤Ç¹ØÆɤµ¤»¤ë
// °ìö¡¢Ãµ¤·¤ÆÂбþ¡¡¥²¡¼¥à¤Î¥ê¥¹¥¿¡¼¥È
GameObject.Find("GameSceneManager").GetComponent<GameSceneManager>().PrepareRestart(restartTran.position, penaltyValue);
}
////*¡¡¤³¤³¤Þ¤Ç¡¡*////
}