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

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
generateStageCount: 1
beginStageOffset: 0.5
partsToPartsOffset: 3
partsToPartsOffset: 0
--- !u!114 &1932485204
MonoBehaviour:
m_ObjectHideFlags: 0

View File

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

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using UnityEngine;
@ -8,77 +9,143 @@ namespace MyGame.Scenes.MiniGame.Scripts
public class StageManager : MonoBehaviour
{
[SerializeField] private Transform stageTarget;
[SerializeField] private float normalTime;
[SerializeField] private float hardTime;
[SerializeField] private float extraTime;
[SerializeField] private float stageGenerateDistance;
[SerializeField] private int generateStageCount;
[SerializeField] private float beginStageOffset;
[SerializeField] private float partsToPartsOffset;
private Transform[] stagePrefabs;
private Transform[] stages;
private float normalTime;
private float hardTime;
private float extraTime;
private Transform[] stageBeginPrefabList;
private Transform[] stageRandomPrefabList;
private int beginIndex;
private int lengthIndex;
private float stageEndXPos;
private float cacheTargetXPos;
public IObservable<float> OnFence => fenceSubject;
public IObservable<float> OnFence => fenceSubject.DelayFrame(1); // 1フレーム送らせて通知
private readonly Subject<float> fenceSubject = new();
public IReadOnlyReactiveProperty<ScrollGameDifficulty> Difficulty => difficulty;
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()
{
fenceSubject.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);
stagePrefabs = newStages;
stageTarget.DestroyAllChildrens();
stageEndXPos = stageTarget.position.x + beginStageOffset;
cacheTargetXPos = stageEndXPos;
lengthIndex = 0;
beginIndex = 0;
generateStageDifficulty = difficulty.Value;
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);
var minPos = float.MaxValue;
var maxPos = float.MinValue;
var holePosList = new List<float>();
stage.FindAllChildrensComponent<StageItem>(x =>
stageCount = generateStageCount;
}
// beginPrefabsの使用が終わったらrandomに切り替え
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;
minPos = Mathf.Min(minPos, xPos);
maxPos = Mathf.Max(maxPos, xPos);
if (x.ItemType == StageItem.Type.Hole)
{
holePosList.Add(xPos);
}
});
var xPos = stage.position.x;
var minDiff = minPos - xPos;
var maxDiff = maxPos - xPos;
stage.SetPositionX(stageEndXPos - minDiff);
var count = Mathf.Min(randomStageCount, prefabs.Length);
stagePrefabs = stagePrefabs.Concat(prefabs.RandomChoose(count)).ToArray();
randomStageCount -= count;
}
}
lengthIndex += stagePrefabs.Length;
foreach (var stagePrefab in stagePrefabs)
{
var stage = Instantiate(stagePrefab, stageTarget.position + Vector3.left * 100f, Quaternion.identity, stageTarget).GetComponent<Stage>();
stage.transform.SetPositionX(stageEndXPos + stage.transform.position.x - stage.StartXPos);
// endPos更新
stageEndXPos = stage.position.x + maxDiff + partsToPartsOffset;
var cacheStageEndPos = stageEndXPos;
stageEndXPos = stage.EndPos + partsToPartsOffset;
// ステージの破棄
var cacheStageEndPos = stageEndXPos;
Observable.Interval(TimeSpan.FromSeconds(.5f))
.First(_ => cacheStageEndPos < cacheTargetXPos)
.Subscribe(_ => { }, () =>
{
Destroy(stage.gameObject);
Destroy(stage.gameObject, 5f);
}).AddTo(stage.gameObject);
// 落とし穴があった場合通知
holePosList.ToObservable().DelayFrame(1).Subscribe(x =>
stage.transform.FindAllChildrensComponent<StageItem>(x =>
{
fenceSubject.OnNext(stage.position.x + x - xPos);
}).AddTo(this);
if (x.ItemType != StageItem.Type.Hole)
{
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();
timerDisposable = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
.Subscribe(x =>
{
if (x >= extraTime)
{
difficulty.Value = ScrollGameDifficulty.Extra;
}
else if (x >= hardTime)
{
difficulty.Value = ScrollGameDifficulty.Hard;
}
else if (x >= normalTime)
{
difficulty.Value = ScrollGameDifficulty.Normal;
}
}).AddTo(this);
}
public void StopTimer()
{
timerDisposable?.Dispose();
return value switch
{
ScrollGameDifficulty.Easy => ScrollGameDifficulty.Normal,
ScrollGameDifficulty.Normal => ScrollGameDifficulty.Hard,
ScrollGameDifficulty.Hard => ScrollGameDifficulty.Extra,
ScrollGameDifficulty.Extra => ScrollGameDifficulty.Extra,
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
};
}
}
}