ステージ切り替え方式変更

This commit is contained in:
kimura 2022-07-28 12:49:07 +09:00
parent 59bc6367fc
commit bdcd475ff6
3 changed files with 131 additions and 76 deletions

View File

@ -1942,7 +1942,7 @@ MonoBehaviour:
stageGenerateDistance: 15 stageGenerateDistance: 15
generateStageCount: 1 generateStageCount: 1
beginStageOffset: 0.5 beginStageOffset: 0.5
partsToPartsOffset: 3 partsToPartsOffset: 0
--- !u!114 &1932485204 --- !u!114 &1932485204
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -76,6 +76,7 @@ namespace MyGame.Scenes.MiniGame.Scripts
var levelPlaceList = placeList.Where(data => data.placeId == placeId).ToArray(); var levelPlaceList = placeList.Where(data => data.placeId == placeId).ToArray();
var levelStageList = stageList.Where(data => data.placeId == placeId).ToArray(); var levelStageList = stageList.Where(data => data.placeId == placeId).ToArray();
// スコア保存に1つ目のstageDataIdを使用
var stageData = levelStageList[0]; var stageData = levelStageList[0];
var scoreUpdate = new Subject<Unit>().AddTo(this); var scoreUpdate = new Subject<Unit>().AddTo(this);
stageSelectView.SetPlaceData(levelPlaceList); stageSelectView.SetPlaceData(levelPlaceList);
@ -92,20 +93,14 @@ namespace MyGame.Scenes.MiniGame.Scripts
{ {
if (gameData.ScrollGameTodayPlayCount == 0) if (gameData.ScrollGameTodayPlayCount == 0)
{ {
gameData.ScrollGameLastPlayTime = DateTime.UtcNow.ToBinary(); ResetGameWithCount(levelPlaceList, levelStageList);
gameData.ScrollGameTodayPlayCount++;
ResetGame(levelPlaceList, stageData);
menuState.Value = MenuState.Game;
return; return;
} }
// ポップアップ ビデオ視聴表示 // ポップアップ ビデオ視聴表示
ScrollGameWatchVideoDialog.ShowDialog(() => ScrollGameWatchVideoDialog.ShowDialog(() =>
{ {
gameData.ScrollGameLastPlayTime = DateTime.UtcNow.ToBinary(); ResetGameWithCount(levelPlaceList, levelStageList);
gameData.ScrollGameTodayPlayCount++;
ResetGame(levelPlaceList, stageData);
menuState.Value = MenuState.Game;
}); });
}).AddTo(this); }).AddTo(this);
scoreUpdate.OnNext(Unit.Default); scoreUpdate.OnNext(Unit.Default);
@ -162,7 +157,6 @@ namespace MyGame.Scenes.MiniGame.Scripts
break; break;
case GameState.Play: case GameState.Play:
SoundManager.Instance.PlaySE("se_minigame_Start"); SoundManager.Instance.PlaySE("se_minigame_Start");
stageManager.StartTimer();
break; break;
case GameState.Success: case GameState.Success:
SoundManager.Instance.PlaySE("se_minigame_End"); SoundManager.Instance.PlaySE("se_minigame_End");
@ -200,7 +194,10 @@ namespace MyGame.Scenes.MiniGame.Scripts
// カメラ移動 // カメラ移動
cameraTransform.position = playerPosX * Vector3.right + cameraOffset; cameraTransform.position = playerPosX * Vector3.right + cameraOffset;
bgManager.UpdatePos(playerPosX); bgManager.UpdatePos(playerPosX);
stageManager.UpdatePos(playerPosX); if (!player.IsHit)
{
stageManager.UpdatePos(playerPosX);
}
}).AddTo(this); }).AddTo(this);
stageManager.OnFence.Subscribe(x => stageManager.OnFence.Subscribe(x =>
@ -274,7 +271,6 @@ namespace MyGame.Scenes.MiniGame.Scripts
switch (item.ItemType) switch (item.ItemType)
{ {
case StageItem.Type.Obstacle: case StageItem.Type.Obstacle:
stageManager.StopTimer();
player.Hit(closestPoint); player.Hit(closestPoint);
break; break;
case StageItem.Type.Item1: case StageItem.Type.Item1:
@ -290,12 +286,21 @@ namespace MyGame.Scenes.MiniGame.Scripts
} }
}).AddTo(this); }).AddTo(this);
} }
private void ResetGameWithCount (ScrollGamePlaceData[] levelPlaceList, ScrollGameStageData[] levelStageList)
{
GameDataManager.GameData.ScrollGameLastPlayTime = DateTime.UtcNow.ToBinary();
GameDataManager.GameData.ScrollGameTodayPlayCount++;
stageManager.SetStageList(levelStageList);
ResetGame(levelPlaceList, levelStageList);
menuState.Value = MenuState.Game;
}
private void ResetGame(ScrollGamePlaceData[] placeList, ScrollGameStageData stageData) private void ResetGame(ScrollGamePlaceData[] placeList, ScrollGameStageData[] stageDataList)
{ {
SoundManager.Instance.ChangeVolumeUniqueBGM(1f); SoundManager.Instance.ChangeVolumeUniqueBGM(1f);
// ステージ読み込み // ステージ読み込み
stageManager.SetBeginStages(stageData.GetBeginStagePrefabs()); stageManager.SetBeginStages();
player.transform.position = characterBeginPos; player.transform.position = characterBeginPos;
player.ResetPlayer(); player.ResetPlayer();
scoreCount.Value = 0; scoreCount.Value = 0;
@ -306,7 +311,7 @@ namespace MyGame.Scenes.MiniGame.Scripts
.SelectMany(Observable.Timer(TimeSpan.FromSeconds(resultWaitTime))) .SelectMany(Observable.Timer(TimeSpan.FromSeconds(resultWaitTime)))
.Subscribe(x => .Subscribe(x =>
{ {
resultManager.ShowResult(scoreCount.Value, placeList, stageData); resultManager.ShowResult(scoreCount.Value, placeList, stageDataList[0]);
SoundManager.Instance.ChangePitchBGM(1f); SoundManager.Instance.ChangePitchBGM(1f);
}).AddTo(gameCompositeDisposable); }).AddTo(gameCompositeDisposable);
@ -314,10 +319,7 @@ namespace MyGame.Scenes.MiniGame.Scripts
{ {
ScrollGameWatchVideoDialog.ShowDialog(() => ScrollGameWatchVideoDialog.ShowDialog(() =>
{ {
GameDataManager.GameData.ScrollGameLastPlayTime = DateTime.UtcNow.ToBinary(); ResetGameWithCount(placeList, stageDataList);
GameDataManager.GameData.ScrollGameTodayPlayCount++;
// ステージ読み込み
ResetGame(placeList, stageData);
}); });
}).AddTo(gameCompositeDisposable); }).AddTo(gameCompositeDisposable);

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UniRx; using UniRx;
using UnityEngine; using UnityEngine;
@ -8,77 +9,143 @@ namespace MyGame.Scenes.MiniGame.Scripts
public class StageManager : MonoBehaviour public class StageManager : MonoBehaviour
{ {
[SerializeField] private Transform stageTarget; [SerializeField] private Transform stageTarget;
[SerializeField] private float normalTime;
[SerializeField] private float hardTime;
[SerializeField] private float extraTime;
[SerializeField] private float stageGenerateDistance; [SerializeField] private float stageGenerateDistance;
[SerializeField] private int generateStageCount; [SerializeField] private int generateStageCount;
[SerializeField] private float beginStageOffset; [SerializeField] private float beginStageOffset;
[SerializeField] private float partsToPartsOffset; [SerializeField] private float partsToPartsOffset;
private Transform[] stagePrefabs; private float normalTime;
private Transform[] stages; private float hardTime;
private float extraTime;
private Transform[] stageBeginPrefabList;
private Transform[] stageRandomPrefabList;
private int beginIndex;
private int lengthIndex;
private float stageEndXPos; private float stageEndXPos;
private float cacheTargetXPos; private float cacheTargetXPos;
public IObservable<float> OnFence => fenceSubject; public IObservable<float> OnFence => fenceSubject.DelayFrame(1); // 1フレーム送らせて通知
private readonly Subject<float> fenceSubject = new(); private readonly Subject<float> fenceSubject = new();
public IReadOnlyReactiveProperty<ScrollGameDifficulty> Difficulty => difficulty; public IReadOnlyReactiveProperty<ScrollGameDifficulty> Difficulty => difficulty;
private readonly ReactiveProperty<ScrollGameDifficulty> difficulty = new(); private readonly ReactiveProperty<ScrollGameDifficulty> difficulty = new();
private IDisposable timerDisposable; private ScrollGameDifficulty generateStageDifficulty;
private IDisposable timerDisposable;
private readonly Dictionary<ScrollGameDifficulty, ScrollGameStageData> stageDataDict = new();
private void Start() private void Start()
{ {
fenceSubject.AddTo(this); fenceSubject.AddTo(this);
difficulty.AddTo(this); difficulty.AddTo(this);
difficulty.SkipLatestValueOnSubscribe().Subscribe(_ =>
{
// 難易度変更時にリソース開放
Resources.UnloadUnusedAssets();
Debug.Log($"change difficulty ({difficulty.Value}) and unload resources");
}).AddTo(this);
} }
public void SetBeginStages(Transform[] newStages)
public void SetStageList(ScrollGameStageData[] stageDataList)
{
// ステージリストを取り込み
stageDataDict.Clear();
foreach (var stageData in stageDataList)
{
if (stageDataDict.ContainsKey(stageData.Difficulty))
{
continue;
}
stageDataDict.Add(stageData.Difficulty, stageData);
}
}
public void SetBeginStages()
{ {
difficulty.SetValueAndForceNotify(ScrollGameDifficulty.Easy); difficulty.SetValueAndForceNotify(ScrollGameDifficulty.Easy);
stagePrefabs = newStages;
stageTarget.DestroyAllChildrens(); stageTarget.DestroyAllChildrens();
stageEndXPos = stageTarget.position.x + beginStageOffset; stageEndXPos = stageTarget.position.x + beginStageOffset;
cacheTargetXPos = stageEndXPos; cacheTargetXPos = stageEndXPos;
lengthIndex = 0;
beginIndex = 0;
generateStageDifficulty = difficulty.Value;
GenerateStage(); GenerateStage();
} }
private void GenerateStage() private void GenerateStage()
{ {
var selectIndex = UnityEngine.Random.Range(0, stagePrefabs.Length); // リソース読み込み
for (var i = 0; i < generateStageCount; i++) stageBeginPrefabList = stageDataDict[generateStageDifficulty].GetBeginStagePrefabs();
stageRandomPrefabList = stageDataDict[generateStageDifficulty].GetRandomStagePrefabs();
var stagePrefabs = Array.Empty<Transform>();
var stageCount = stageDataDict[generateStageDifficulty].length;
if (stageCount == 0)
{ {
var stage = Instantiate(stagePrefabs[selectIndex], stageTarget.position + Vector3.left * 100f, Quaternion.identity, stageTarget); stageCount = generateStageCount;
var minPos = float.MaxValue; }
var maxPos = float.MinValue;
var holePosList = new List<float>(); // beginPrefabsの使用が終わったらrandomに切り替え
stage.FindAllChildrensComponent<StageItem>(x => if (stageBeginPrefabList.Length > beginIndex)
{
var rangeEnd = Mathf.Min(beginIndex + stageCount, stageBeginPrefabList.Length);
stagePrefabs = stageBeginPrefabList[beginIndex..rangeEnd];
beginIndex += stagePrefabs.Length;
}
var randomStageCount = stageCount - stagePrefabs.Length;
if (randomStageCount > 0)
{
var prefabs = (stageRandomPrefabList?.Length ?? 0) > 0 ? stageRandomPrefabList : stageBeginPrefabList;
while (randomStageCount > 0)
{ {
var xPos = x.transform.position.x; var count = Mathf.Min(randomStageCount, prefabs.Length);
minPos = Mathf.Min(minPos, xPos); stagePrefabs = stagePrefabs.Concat(prefabs.RandomChoose(count)).ToArray();
maxPos = Mathf.Max(maxPos, xPos); randomStageCount -= count;
if (x.ItemType == StageItem.Type.Hole) }
{ }
holePosList.Add(xPos);
} lengthIndex += stagePrefabs.Length;
});
var xPos = stage.position.x; foreach (var stagePrefab in stagePrefabs)
var minDiff = minPos - xPos; {
var maxDiff = maxPos - xPos; var stage = Instantiate(stagePrefab, stageTarget.position + Vector3.left * 100f, Quaternion.identity, stageTarget).GetComponent<Stage>();
stage.SetPositionX(stageEndXPos - minDiff); stage.transform.SetPositionX(stageEndXPos + stage.transform.position.x - stage.StartXPos);
// endPos更新 // endPos更新
stageEndXPos = stage.position.x + maxDiff + partsToPartsOffset; stageEndXPos = stage.EndPos + partsToPartsOffset;
var cacheStageEndPos = stageEndXPos;
// ステージの破棄 // ステージの破棄
var cacheStageEndPos = stageEndXPos;
Observable.Interval(TimeSpan.FromSeconds(.5f)) Observable.Interval(TimeSpan.FromSeconds(.5f))
.First(_ => cacheStageEndPos < cacheTargetXPos) .First(_ => cacheStageEndPos < cacheTargetXPos)
.Subscribe(_ => { }, () => .Subscribe(_ => { }, () =>
{ {
Destroy(stage.gameObject); Destroy(stage.gameObject, 5f);
}).AddTo(stage.gameObject); }).AddTo(stage.gameObject);
// 落とし穴があった場合通知 // 落とし穴があった場合通知
holePosList.ToObservable().DelayFrame(1).Subscribe(x => stage.transform.FindAllChildrensComponent<StageItem>(x =>
{ {
fenceSubject.OnNext(stage.position.x + x - xPos); if (x.ItemType != StageItem.Type.Hole)
}).AddTo(this); {
return;
}
fenceSubject.OnNext(x.transform.position.x);
});
}
// 指定の長さ生成を終えた場合
if (lengthIndex >= stageDataDict[generateStageDifficulty].length)
{
// 次回ステージ生成の難易度を変更
generateStageDifficulty = NextDifficulty(generateStageDifficulty);
lengthIndex = 0;
beginIndex = 0;
// ステージを完走すると難易度変更
var cacheStageEndPos = stageEndXPos;
Observable.Interval(TimeSpan.FromSeconds(.5f))
.First(_ => cacheStageEndPos < cacheTargetXPos)
.Subscribe(_ => { }, () =>
{
difficulty.Value = NextDifficulty(difficulty.Value);
}).AddTo(this);
} }
} }
@ -91,30 +158,16 @@ namespace MyGame.Scenes.MiniGame.Scripts
} }
} }
public void StartTimer() private static ScrollGameDifficulty NextDifficulty(ScrollGameDifficulty value)
{ {
StopTimer(); return value switch
timerDisposable = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1)) {
.Subscribe(x => ScrollGameDifficulty.Easy => ScrollGameDifficulty.Normal,
{ ScrollGameDifficulty.Normal => ScrollGameDifficulty.Hard,
if (x >= extraTime) ScrollGameDifficulty.Hard => ScrollGameDifficulty.Extra,
{ ScrollGameDifficulty.Extra => ScrollGameDifficulty.Extra,
difficulty.Value = ScrollGameDifficulty.Extra; _ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
} };
else if (x >= hardTime)
{
difficulty.Value = ScrollGameDifficulty.Hard;
}
else if (x >= normalTime)
{
difficulty.Value = ScrollGameDifficulty.Normal;
}
}).AddTo(this);
}
public void StopTimer()
{
timerDisposable?.Dispose();
} }
} }
} }