diff --git a/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornManager.cs b/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornManager.cs index a406bc28..5586281c 100644 --- a/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornManager.cs +++ b/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornManager.cs @@ -18,6 +18,11 @@ public class CornManager : MonoBehaviour [SerializeField] private Transform cornSpawnTarget; [SerializeField] private Corn cornPrefab; [SerializeField] private GameObject spilledCornAnimationPrefab; + [SerializeField] private GameObject missCornAnimationPrefab; + [SerializeField] private CornMissMeter cornMissMeter; + [SerializeField] private RectTransform missTextSpawnTransform; + private static readonly Bounds missEffectBounds = new Bounds(new Vector3(0f, 1.7f), new Vector3(10f, 7f)); + [SerializeField] private int cornSpawnCount = 20; [SerializeField] private int maxFailedCornCount = 10; [SerializeField, ReadOnly] private float baseGrowSpeed = 1f; @@ -39,6 +44,8 @@ public class CornManager : MonoBehaviour private bool isCompleted; private readonly List> cornConditions = new List>(); private readonly Subject cornSpilledSubject = new Subject(); + private readonly Subject cornMissCountSubject = new Subject(); + private readonly ReactiveProperty missCount = new ReactiveProperty(); private readonly ReactiveProperty cornGrowSpeed = new FloatReactiveProperty(0f); private readonly CompositeDisposable compositeDisposable = new CompositeDisposable(); @@ -79,6 +86,31 @@ public class CornManager : MonoBehaviour SpawnSpilledAnimation(condition); } }).AddTo(this); + + // ミス通知 + cornMissCountSubject + .Where(_ => !isCompleted) + .Subscribe(x => + { + SpawnMissAnimation(x); + }); + + // ミス数メータ反映 + missCount + .BatchFrame(2, FrameCountType.Update) + .Select(x => x.Max()) + .Subscribe(x => + { + cornMissMeter.SetMeter((float)x/maxFailedCornCount); + }).AddTo(this); + + // ミス数上限で失敗 + missCount + .Where(x => x == maxFailedCornCount) + .Subscribe(_ => + { + SetResult(CornResult.Failure); + }).AddTo(this); #if DEVELOPMENT_BUILD || UNITY_EDITOR cornCountSlider.wholeNumbers = true; cornCountSlider.value = cornSpawnCount; @@ -105,6 +137,8 @@ public class CornManager : MonoBehaviour public void RespawnCorn() { cornGrowSpeed.Value = 0f; + missCount.Value = 0; + cornMissMeter.ResetMeter(); isCompleted = false; compositeDisposable.Clear(); cornConditions.Clear(); @@ -153,8 +187,13 @@ public class CornManager : MonoBehaviour } break; case CornCondition.Burnt: + cornMissCountSubject.OnNext(condition.Current); break; case CornCondition.Spilled: + if (condition.Previous != CornCondition.Burnt) + { + cornMissCountSubject.OnNext(condition.Current); + } // 同時に飛び出したとき用に演出をばらつかせる corn.CallWaitForSeconds(Random.Range(0f, .5f), () => cornSpilledSubject.OnNext(condition.Previous)); break; @@ -167,17 +206,7 @@ public class CornManager : MonoBehaviour } var cornConditionsObservable = Observable.CombineLatest(cornConditions).Publish().RefCount(); - - // 焦げたコーンorフライパンを飛び出したコーンが設定値を超えるとFailure - cornConditionsObservable - .FirstOrDefault(x => x.Count(c => c == CornCondition.Burnt || c == CornCondition.Spilled) >= maxFailedCornCount) - .Subscribe(x => - { - if (x == null) return; - SetResult(CornResult.Failure); - }) - .AddTo(compositeDisposable); - + // すべてのコーンがSeedではなくなった場合 cornConditionsObservable .FirstOrDefault(x => !x.Contains(CornCondition.Seed)) @@ -232,6 +261,27 @@ public class CornManager : MonoBehaviour this.CallWaitForSeconds(1.5f, () => Destroy(animation)); } + private void SpawnMissAnimation(CornCondition condition) + { + var position = new Vector2(Random.Range(missEffectBounds.min.x, missEffectBounds.max.x), Random.Range(missEffectBounds.min.y, missEffectBounds.max.y)); + // ミス表示 + var animation = Instantiate(missCornAnimationPrefab, position, Quaternion.identity, missTextSpawnTransform); + animation.GetComponent().ChangeSkin(condition); + this.CallWaitForSeconds(.5f, () => + { + this.CallLerp(.2f, f => + { + animation.transform.position = Vector3.Lerp(position, cornMissMeter.transform.position, f.EaseInQuadratic()); + }, () => + { + VibrationManager.Instance.PlayVibrationOnce(); + // 表示終了後ミス数加算 + missCount.Value++; + Destroy(animation); + }); + }); + } + private void SetResult(CornResult resultValue) { cornGrowSpeed.Value = 0f; diff --git a/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornMissMeter.cs b/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornMissMeter.cs index 406cb578..b908c5d5 100644 --- a/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornMissMeter.cs +++ b/popcorn/Assets/MyGame/Scenes/Cooking/Scripts/CornMissMeter.cs @@ -15,25 +15,24 @@ public class CornMissMeter : MonoBehaviour private float duration = .4f; private void Start() { + var totalValue = 1 - minValue; ResetMeter(); this.UpdateAsObservable().Subscribe(x => { - missGauge.fillAmount = Mathf.Lerp(prevValue, nextValue, elapsed.EaseInQuadratic()); + missGauge.fillAmount = minValue + Mathf.Lerp(prevValue, nextValue, elapsed.EaseInQuadratic()) * totalValue; elapsed += Time.deltaTime / duration; }).AddTo(this); } public void SetMeter(float value, bool animated = true) { - nextValue = value * (1f - minValue); + nextValue = value; prevValue = missGauge.fillAmount; elapsed = animated ? 0f : 1f; - Debug.Log($"{nextValue} {prevValue}"); } public void ResetMeter() { - prevValue = minValue; - SetMeter(minValue, false); + SetMeter(0f, false); } } \ No newline at end of file