Merge branch 'develop' of bitbucket.org:usaya/popcorn into develop

This commit is contained in:
koya_15 2021-09-02 15:05:21 +09:00
commit 4a7729e412
5 changed files with 488 additions and 190 deletions

View File

@ -55,12 +55,13 @@ MonoBehaviour:
walkSideTopPosition: -0.6 walkSideTopPosition: -0.6
walkSideMidPos: -4 walkSideMidPos: -4
walkSideBottomPos: -6.7 walkSideBottomPos: -6.7
walkSideLeavePos: -1
stopPosision: 0 stopPosision: 0
stopPositionRange: 1 stopPositionRange: 3
orderStayPositions: [] orderStayPositions: []
orderPosision: 0.5 orderPosision: 0.5
orderPositionRange: 2 orderPositionRange: 2
waitOrderPosision: -0.6 waitOrderPosision: -1.5
walkSideSpeed: 1.3 walkSideSpeed: 1.3
walkFrontBackSpeed: 1 walkFrontBackSpeed: 1
--- !u!114 &1385243083193661112 --- !u!114 &1385243083193661112
@ -78,6 +79,32 @@ MonoBehaviour:
bigHeart: {fileID: 7988005957398545984} bigHeart: {fileID: 7988005957398545984}
smallHeart: {fileID: 992423202615605163} smallHeart: {fileID: 992423202615605163}
target: {fileID: 0} target: {fileID: 0}
--- !u!61 &3337152902562194938
BoxCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5409985851491668855}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 0}
m_IsTrigger: 0
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0}
oldSize: {x: 0, y: 0}
newSize: {x: 0, y: 0}
adaptiveTilingThreshold: 0
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 2, y: 2}
m_EdgeRadius: 0
--- !u!210 &7449452199590198578 --- !u!210 &7449452199590198578
SortingGroup: SortingGroup:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -156,6 +183,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: NormalBody value: NormalBody
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4886416729068509251, guid: db654393793a67d45a7d0b70a68b73a6,
type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4886416729748261544, guid: db654393793a67d45a7d0b70a68b73a6, - target: {fileID: 4886416729748261544, guid: db654393793a67d45a7d0b70a68b73a6,
type: 3} type: 3}
propertyPath: m_IsActive propertyPath: m_IsActive

View File

@ -7,16 +7,27 @@ using Random = UnityEngine.Random;
public enum CustomerMovingType public enum CustomerMovingType
{ {
WalkFront,
WalkSide, WalkSide,
WalkBack,
WalkBackHalf,
StayBack,
StayBackLook,
WalkFrontEat,
WalkSideEat, WalkSideEat,
WalkCenter, WalkCenter,
StayBack,
StayBackLook,
WalkBack,
WalkBackHalf,
WalkFront,
WalkFrontEat,
} }
public enum CustomerState
{
Walk,
Want,
Wait,
Order,
Leave,
EatingLeave,
}
public class CustomerController : MonoBehaviour public class CustomerController : MonoBehaviour
{ {
private static readonly int WalkFront = Animator.StringToHash("WalkFront"); private static readonly int WalkFront = Animator.StringToHash("WalkFront");
@ -40,6 +51,7 @@ public class CustomerController : MonoBehaviour
[SerializeField] private float walkSideTopPosition; [SerializeField] private float walkSideTopPosition;
[SerializeField] private float walkSideMidPos; [SerializeField] private float walkSideMidPos;
[SerializeField] private float walkSideBottomPos; [SerializeField] private float walkSideBottomPos;
[SerializeField] private float walkSideLeavePos;
// 立ち止まる範囲 // 立ち止まる範囲
[SerializeField] private float stopPosision = 0f; [SerializeField] private float stopPosision = 0f;
[SerializeField] private float stopPositionRange = 2f; [SerializeField] private float stopPositionRange = 2f;
@ -47,32 +59,47 @@ public class CustomerController : MonoBehaviour
[SerializeField] private List<Transform> orderStayPositions = new List<Transform>(); [SerializeField] private List<Transform> orderStayPositions = new List<Transform>();
// 購入ポジ // 購入ポジ
[SerializeField] private float orderPosision = .5f; [SerializeField] private float orderPosision = .5f;
[SerializeField] private float orderPositionRange = 2f; [SerializeField] private float orderPositionRange = 1f;
[SerializeField] private float waitOrderPosision = .2f; [SerializeField] private float waitOrderPosision = .2f;
// 歩行速度 // 歩行速度
[SerializeField] private float walkSideSpeed = 1.3f; // 1.3f [SerializeField] private float walkSideSpeed = 1.3f; // 1.3f
[SerializeField] private float walkFrontBackSpeed = 1.0f; // 1.0f [SerializeField] private float walkFrontBackSpeed = 1.0f; // 1.0f
private float speed = 0f; private static readonly float leftEndPosision = -10f;
private Vector3 beginPos; private Vector3 beginPos;
private Vector3 wayPoint; private Vector3 wayPoint;
private List<CustomerMovingType> moves = new List<CustomerMovingType>(); private CustomerMovingType currentMovingType;
private static readonly float leftEndPosision = -10f; private List<(CustomerMovingType type, float duration)> moves = new List<(CustomerMovingType, float)>();
// 停止時間 private float speed = 0f;
private float completedDuration;
private float durationDelta;
// 左右どちらから出るか // 左右どちらから出るか
private Subject<Unit> orderSubject = new Subject<Unit>(); private float walkSideDirection;
public IObservable<Unit> OrderObservable => orderSubject; public IReadOnlyReactiveProperty<CustomerMovingType> MoveEndObservable => moveEndSubject;
private readonly ReactiveProperty<CustomerMovingType> moveEndSubject = new ReactiveProperty<CustomerMovingType>();
public IReadOnlyReactiveProperty<CustomerState> CustomerState => customerState;
private readonly ReactiveProperty<CustomerState> customerState = new ReactiveProperty<CustomerState>();
private void Start() private void Start()
{ {
customerState.AddTo(this);
durationDelta = 0f;
this.UpdateAsObservable().Subscribe(_ => this.UpdateAsObservable().Subscribe(_ =>
{ {
transform.localPosition = Vector3.MoveTowards(transform.localPosition, wayPoint, speed * Time.deltaTime); transform.localPosition = Vector3.MoveTowards(transform.localPosition, wayPoint, speed * Time.deltaTime);
if (Vector3.Distance(transform.localPosition, wayPoint) < .01f) if (Vector3.Distance(transform.localPosition, wayPoint) < .01f)
{ {
if (durationDelta < completedDuration)
{
durationDelta += Time.deltaTime;
return;
}
durationDelta = 0f;
moveEndSubject.Value = currentMovingType;
if (moves.Count > 0) if (moves.Count > 0)
{ {
SetMove(moves[0]); var move = moves[0];
moves.RemoveAt(0); moves.RemoveAt(0);
SetMove(move.type, move.duration);
} }
} }
}).AddTo(this); }).AddTo(this);
@ -80,77 +107,153 @@ public class CustomerController : MonoBehaviour
public void Setup() public void Setup()
{ {
walkSideDirection = Mathf.Sign(Random.value - .5f);
beginPos = Vector3.zero; beginPos = Vector3.zero;
beginPos.x = leftEndPosision; beginPos.x = leftEndPosision * walkSideDirection;
beginPos.y = Random.Range(walkSideMidPos, walkSideBottomPos); beginPos.y = Random.Range(walkSideMidPos, walkSideBottomPos);
beginPos.z = beginPos.y + Mathf.Abs(walkSideBottomPos);
transform.localPosition = beginPos; transform.localPosition = beginPos;
currentMovingType = CustomerMovingType.StayBack;
SetWayPoint(beginPos); SetWayPoint(beginPos);
} }
public void AddMove(CustomerMovingType type) public void ChangeCustomerState(CustomerState state)
{ {
moves.Add(type); customerState.Value = state;
Debug.Log(state);
switch (state)
{
case global::CustomerState.Walk:
SetMove(CustomerMovingType.WalkCenter);
// 数秒立ち止まる
AddMove(CustomerMovingType.StayBackLook, 2f);
AddMove(CustomerMovingType.WalkSide);
break;
case global::CustomerState.Want:
// 店に向かう
moves.Clear();
if (currentMovingType == CustomerMovingType.StayBackLook)
{
SetMove(CustomerMovingType.WalkBackHalf);
break;
}
SetMove(CustomerMovingType.WalkCenter);
break;
case global::CustomerState.Wait:
// 順番待ち
// 近くの場合その場に待機
// まだ遠い場合待機場所に移動
AddMove(CustomerMovingType.WalkBackHalf);
AddMove(CustomerMovingType.StayBackLook);
break;
case global::CustomerState.Order:
// 受付まで行く
AddMove(CustomerMovingType.WalkBack);
AddMove(CustomerMovingType.StayBack);
break;
case global::CustomerState.Leave:
moves.Clear();
SetMove(CustomerMovingType.WalkSide);
break;
case global::CustomerState.EatingLeave:
AddMove(CustomerMovingType.WalkFrontEat);
AddMove(CustomerMovingType.WalkSideEat);
break;
default:
throw new ArgumentOutOfRangeException(nameof(state), state, null);
}
}
private void AddMove(CustomerMovingType type, float duration = 0f)
{
moves.Add((type, duration));
} }
// キャラの奥行き描画順のため、y方向に対応したz軸を設定 // キャラの奥行き描画順のため、y方向に対応したz軸を設定
private void SetMove(CustomerMovingType type) private void SetMove(CustomerMovingType type, float duration = 0f)
{ {
if (currentMovingType == type)
{
return;
}
completedDuration = duration;
switch (type) switch (type)
{ {
case CustomerMovingType.WalkFront:
SetWayPoint(new Vector3(wayPoint.x, Random.Range(walkSideMidPos, walkSideTopPosition)));
speed = walkFrontBackSpeed;
animator.SetTrigger(WalkFront);
break;
case CustomerMovingType.WalkSide: case CustomerMovingType.WalkSide:
SetWayPoint(new Vector3(-leftEndPosision, wayPoint.y)); SetWayPoint(new Vector3(-leftEndPosision * walkSideDirection, wayPoint.y));
speed = walkSideSpeed; speed = walkSideSpeed;
// アニメーション違和感回避
if (currentMovingType == CustomerMovingType.WalkCenter)
{
break;
}
animator.SetTrigger(WalkSide); animator.SetTrigger(WalkSide);
break; break;
case CustomerMovingType.WalkBack: case CustomerMovingType.WalkSideEat:
SetWayPoint(new Vector3((Random.value - .5f) * 2 * orderPositionRange, orderPosision)); SetWayPoint(new Vector3(-leftEndPosision * walkSideDirection, wayPoint.y));
speed = walkFrontBackSpeed; speed = walkSideSpeed;
animator.SetTrigger(WalkBack); animator.SetTrigger(WalkSideEat);
break; break;
case CustomerMovingType.WalkBackHalf: case CustomerMovingType.WalkCenter:
SetWayPoint(new Vector3(stopPosision + (Random.value - .5f) * 2 * stopPositionRange, waitOrderPosision)); // 通り過ぎた人はwalkSideDirection基準にするとあるき過ぎるので改善したい
speed = walkFrontBackSpeed; // 立ち止まったあと戻ってしまう場合があるので、中央付近だと戻りがないようにする
animator.SetTrigger(WalkBack); if (Mathf.Abs(transform.localPosition.x - stopPosision) <= stopPositionRange)
{
SetWayPoint(new Vector3(transform.localPosition.x, beginPos.y));
}
else
{
SetWayPoint(new Vector3(stopPosision - Random.value * stopPositionRange * walkSideDirection, beginPos.y));
}
speed = walkSideSpeed;
// アニメーション違和感回避
if (currentMovingType == CustomerMovingType.WalkSide)
{
break;
}
animator.SetTrigger(WalkSide);
break; break;
case CustomerMovingType.StayBack: case CustomerMovingType.StayBack:
// オーダー
speed = 0f; speed = 0f;
animator.SetTrigger(StayBack); animator.SetTrigger(StayBack);
orderSubject.OnNext(Unit.Default);
break; break;
case CustomerMovingType.StayBackLook: case CustomerMovingType.StayBackLook:
speed = 0f; speed = 0f;
animator.SetTrigger(StayBackLook); animator.SetTrigger(StayBackLook);
break; break;
case CustomerMovingType.WalkBack:
SetWayPoint(new Vector3(Random.value * orderPositionRange * walkSideDirection, orderPosision));
speed = walkFrontBackSpeed;
animator.SetTrigger(WalkBack);
break;
case CustomerMovingType.WalkBackHalf:
// 待機列に入る
SetWayPoint(new Vector3(wayPoint.x, waitOrderPosision));
speed = walkFrontBackSpeed;
animator.SetTrigger(WalkBack);
break;
case CustomerMovingType.WalkFront:
// 購入場所に行く
SetWayPoint(new Vector3(wayPoint.x, Random.Range(walkSideLeavePos, walkSideTopPosition)));
speed = walkFrontBackSpeed;
animator.SetTrigger(WalkFront);
break;
case CustomerMovingType.WalkFrontEat: case CustomerMovingType.WalkFrontEat:
SetWayPoint(new Vector3(wayPoint.x, Random.Range(walkSideMidPos, walkSideTopPosition))); SetWayPoint(new Vector3(wayPoint.x, Random.Range(walkSideLeavePos, walkSideTopPosition)));
speed = walkFrontBackSpeed; speed = walkFrontBackSpeed;
animator.SetTrigger(WalkFrontEat); animator.SetTrigger(WalkFrontEat);
break; break;
case CustomerMovingType.WalkSideEat:
SetWayPoint(new Vector3(-leftEndPosision, wayPoint.y));
speed = walkSideSpeed;
animator.SetTrigger(WalkSideEat);
break;
case CustomerMovingType.WalkCenter:
SetWayPoint(new Vector3(stopPosision + (Random.value - .5f) * 2 * stopPositionRange, beginPos.y));
speed = walkSideSpeed;
animator.SetTrigger(WalkSide);
break;
default: default:
throw new ArgumentOutOfRangeException(nameof(type), type, null); throw new ArgumentOutOfRangeException(nameof(type), type, null);
} }
currentMovingType = type;
} }
private void SetWayPoint(Vector3 point) private void SetWayPoint(Vector3 point)
{ {
wayPoint = point; wayPoint = point;
wayPoint.z = wayPoint.y + Mathf.Abs(walkSideBottomPos); wayPoint.z = wayPoint.y + Mathf.Abs(walkSideBottomPos);
transform.localRotation = Quaternion.Euler((wayPoint - transform.localPosition).x >= 0 ? Vector3.zero : Vector3.up * 180);
} }
public void ChangeWantFlavor(int flavor) public void ChangeWantFlavor(int flavor)
@ -170,9 +273,4 @@ public class CustomerController : MonoBehaviour
wantFlavorSprite.sprite = defaultSprite; wantFlavorSprite.sprite = defaultSprite;
} }
} }
public void SetCustomerType()
{
}
} }

View File

@ -3,9 +3,17 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UniRx; using UniRx;
using UniRx.Triggers;
using UnityEngine; using UnityEngine;
using Random = UnityEngine.Random; using Random = UnityEngine.Random;
public enum ShopState
{
Open,
Busy,
Close,
}
public class Market : MonoBehaviour public class Market : MonoBehaviour
{ {
public static readonly int ShopStockCount = 20; public static readonly int ShopStockCount = 20;
@ -18,29 +26,51 @@ public class Market : MonoBehaviour
private readonly List<RecipeData> allRecipe = RecipeData.GetAllRecipe(); private readonly List<RecipeData> allRecipe = RecipeData.GetAllRecipe();
private List<int> displayFlavors; private List<int> displayFlavors;
private List<int> shuffledOrder; private List<int> shuffledOrder;
private ReactiveProperty<ShopState> shopState = new ReactiveProperty<ShopState>();
private ReactiveCollection<CustomerController> waitCustomerList = new ReactiveCollection<CustomerController>();
private Subject<CustomerController> requestSubject = new Subject<CustomerController>();
// Start is called before the first frame update // Start is called before the first frame update
void Start() void Start()
{ {
shopState.AddTo(this);
waitCustomerList.AddTo(this);
requestSubject.AddTo(this);
var gameData = GameDataManager.GameData; var gameData = GameDataManager.GameData;
CoinManager.Instance.ChangeCoin(gameData.coin); CoinManager.Instance.ChangeCoin(gameData.coin);
HeartMeter.Instance.Initialize(new List<int>{
0, var shopLevelList = new List<(int level, int heart, int tenMinCustomer)>
10, {
30, (1, 0, 10),
50, (2, 10, 15),
80, (3, 30, 20),
130, (4, 50, 25),
210, (5, 80, 30),
320, (6, 130, 35),
470, (7, 210, 40),
650, (8, 320, 45),
}); (9, 470, 50),
(10, 650, 55),
(11, 870, 60),
(12, 1120, 65),
(13, 1420, 70),
(14, 1870, 75),
(15, 2470, 80),
(16, 3170, 85),
(17, 4070, 90),
(18, 5470, 95),
(19, 7070, 100),
(20, 9070, 105),
};
HeartMeter.Instance.Initialize(shopLevelList.Select(x => x.heart).ToList());
HeartMeter.Instance.SetHeart(15); HeartMeter.Instance.SetHeart(15);
// 在庫数表示 // 在庫数表示
stockView.SetStock(gameData.StorageTanks); stockView.SetStock(gameData.StorageTanks);
FixStock(); CheckAndFixStock();
StockFlavorLog(); StockFlavorLog();
// 陳列 // 陳列
@ -50,66 +80,214 @@ public class Market : MonoBehaviour
// 売り順決定 // 売り順決定
shuffledOrder = ShuffleOrder(displayFlavors.Count); shuffledOrder = ShuffleOrder(displayFlavors.Count);
// お客さん出現パターン確率計算と行動パターン計算 // お店の状態設定
shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open;
var customerObservable = Observable.Interval(TimeSpan.FromSeconds(60f)).Select(_ => // 購入リクエスト
shopState
.Where(x => x == ShopState.Open)
.Where(_ => waitCustomerList.Count > 0)
.Select(_ => waitCustomerList[0])
.Merge(waitCustomerList.ObserveAdd().Select(x => x.Value))
.BatchFrame()
.Select(x => x.RandomChoose()) // 同時にリクエストが有った場合1人選ぶ
.Where(_ => shopState.Value == ShopState.Open) // 他に購入中の客がいないことを確認
.Subscribe(x =>
{
Debug.Log($"RequestComfirmed");
waitCustomerList.Remove(x);
// 購入へ
x.ChangeCustomerState(CustomerState.Order);
shopState.Value = ShopState.Busy;
}).AddTo(this);
// お客さん一覧
var customerList = new ReactiveCollection<CustomerController>();
customerList.AddTo(this);
// 購入客
customerList.ObserveAdd()
.Select(x => x.Value)
.Subscribe(customerController =>
{
// 店に向かう
customerController.ChangeCustomerState(CustomerState.Want);
waitCustomerList.Add(customerController);
shopState.Subscribe(x =>
{
switch (x)
{
case ShopState.Open:
break;
case ShopState.Busy:
// 自分が購入中
if (customerController.CustomerState.Value == CustomerState.Order)
{
return;
}
// 待機
customerController.ChangeCustomerState(CustomerState.Wait);
break;
case ShopState.Close:
// 売り切れの場合帰る
customerController.ChangeCustomerState(CustomerState.Leave);
break;
default:
throw new ArgumentOutOfRangeException(nameof(x), x, null);
}
}).AddTo(customerController);
}).AddTo(this);
requestSubject.Subscribe(customerController =>
{ {
return 0; // 売り切れ
}); if (gameData.ShopStock.Count == 0)
var walkerObservable = Observable.Timer(TimeSpan.FromSeconds(2f), TimeSpan.FromSeconds(5f)) {
shopState.Value = ShopState.Close;
return;
}
// shuffledOrder順に販売
Debug.Log(shuffledOrder.Aggregate("", (s, i) => s + i));
var orderNum = shuffledOrder[0];
shuffledOrder.RemoveAt(0);
// コーンの味吹き出しを設定
customerController.ChangeWantFlavor(displayFlavors[orderNum]);
this.CallWaitForSeconds(1.5f, () =>
{
// 購入
SellPopcorn(orderNum);
blueView.SellAction();
// 自動補充 refill
RefillOneProduct();
StockFlavorLog();
var setStockFlag = false;
// 補充された場合フレーバー再設定
if (gameData.ShopStock.Count == ShopStockCount)
{
shuffledOrder.Add(orderNum);
displayFlavors[orderNum] = gameData.ShopStock.Last();
}
else if (gameData.ShopStock.Count <= 13 && shuffledOrder.Exists(x => x > 13))
{
displayFlavors = gameData.ShopStock.Select(x => x).ToList();
shuffledOrder = ShuffleOrder(displayFlavors.Count);
setStockFlag = true;
}
else if (gameData.ShopStock.Count <= 7 && shuffledOrder.Exists(x => x > 7))
{
displayFlavors = gameData.ShopStock.Select(x => x).ToList();
shuffledOrder = ShuffleOrder(displayFlavors.Count);
setStockFlag = true;
}
// 表示更新
this.CallWaitForSeconds(1f, () =>
{
var heartAnimation = customerController.GetComponent<HeartAnimation>();
heartAnimation.GetHeart(() =>
{
HeartMeter.Instance.AddHeart(3);
});
customerController.ChangeCustomerState(CustomerState.EatingLeave);
stockView.SetStock(gameData.StorageTanks);
if (gameData.ShopStock.Count == ShopStockCount)
{
// 補充したフレーバーのスキンを設定
cartView.Refill(orderNum, displayFlavors[orderNum]);
}
else if (setStockFlag)
{
cartView.SetStock(displayFlavors);
}
});
shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open;
});
}).AddTo(this);
// お客さん出現タイマー(店舗レベル連動
var changeCustomerFlowObservable = HeartMeter.Instance.ShopLevel
.Select(x => (float)60 * 10 / shopLevelList.First(y => y.level == x).tenMinCustomer); // 10分間期待値から来客の間隔を算出
var customerObservable = changeCustomerFlowObservable
.Select(x => Observable.Interval(TimeSpan.FromSeconds(x))
.Select(_ =>
{
Debug.Log($"customer:{GetHashCode()}");
// 一般客orセレブ
// 複数パターンある場合ChooseRandom
return (isCustomer: true, isSpecial: false);
}))
.Switch();
// 歩行者出現頻度、立ち止まり確率も設定(歩行者タイマー1分間に6人
var walkerObservable = Observable.Timer(TimeSpan.FromSeconds(2f), TimeSpan.FromSeconds(10f))
.Select(x => .Select(x =>
{ {
return 0; Debug.Log($"walker:{GetHashCode()}");
// 一般客orセレブ
// 複数パターンある場合ChooseRandom
return (isCustomer: false, isSpecial: false);
}); });
Observable.Merge(customerObservable, walkerObservable)
// .Take(5) // 宣伝時、タップすると60秒だけ稼働するストリーム
.Subscribe(_ => // タップ, リアクティブコマンドで60秒押せない,その後復活
var adClickObservable = new Subject<Unit>();
adClickObservable.AddTo(this);
var adWalkerObservable = Observable.Interval(TimeSpan.FromSeconds(3f))
.Take(20)
.Select(x =>
{ {
var customer = Instantiate(customerPrefab); Debug.Log($"adWalker");
var heartAnimation = customer.GetComponent<HeartAnimation>(); return (isCustomer: false, isSpecial: false);
var customerController = customer.GetComponent<CustomerController>(); });
customerController.Setup(); var adClickWalkerObservable = adClickObservable
if (Random.value < .4f) .Do(_ => { Debug.Log($"clicked");})
.Delay(TimeSpan.FromSeconds(2f))
.Select(x => adWalkerObservable).Switch();
// Observable.Timer(TimeSpan.FromSeconds(3f)).Subscribe(_ => { adClickObservable.OnNext(default); }).AddTo(this);
// キャラ生成
Observable.Merge(walkerObservable, customerObservable)
// .Merge(adClickWalkerObservable)
.Subscribe(x =>
{
var customer = Instantiate(customerPrefab);
var customerController = customer.GetComponent<CustomerController>();
customerController.Setup();
customerController.MoveEndObservable.SkipLatestValueOnSubscribe().DistinctUntilChanged().Subscribe(type =>
{
// Debug.Log($"move end {type}");
switch (type)
{ {
customerController.AddMove(CustomerMovingType.WalkSide); case CustomerMovingType.WalkSide:
case CustomerMovingType.WalkSideEat:
customerList.Remove(customerController);
Destroy(customer);
break;
case CustomerMovingType.StayBack:
requestSubject.OnNext(customerController);
break;
default:
break;
} }
else }).AddTo(customerController);
if (x.isCustomer)
{
// 購入客リスト追加
customerList.Add(customerController);
}
else
{
// 歩行者はタップ後購入客
customerController.ChangeCustomerState(CustomerState.Walk);
var eventTrigger = customer.transform.GetChild(0).gameObject.AddComponent<ObservableEventTrigger>();
eventTrigger.OnPointerClickAsObservable().Take(1).Subscribe(_ =>
{ {
customerController.AddMove(CustomerMovingType.WalkCenter); customerList.Add(customerController);
customerController.AddMove(CustomerMovingType.WalkBack); }).AddTo(customerController);
customerController.AddMove(CustomerMovingType.StayBack); }
} }).AddTo(this);
customerController.OrderObservable.Subscribe(__ =>
{
// 購入
if (gameData.ShopStock.Count == 0)
{
customerController.AddMove(CustomerMovingType.WalkFront);
customerController.AddMove(CustomerMovingType.WalkSide);
return;
}
// shuffledOrder順に販売
var orderNum = shuffledOrder[0];
shuffledOrder.RemoveAt(0);
// コーンの味吹き出しを設定
customerController.ChangeWantFlavor(displayFlavors[orderNum]);
this.CallWaitForSeconds(2f, () =>
{
SellPopcorn(orderNum);
blueView.SellAction();
this.CallWaitForSeconds(2f, () =>
{
heartAnimation.GetHeart(() =>
{
HeartMeter.Instance.AddHeart(3);
});
customerController.AddMove(CustomerMovingType.WalkFrontEat);
customerController.AddMove(CustomerMovingType.WalkSideEat);
Destroy(customer.gameObject, 10f);
});
});
});
}).AddTo(this);
} }
private void SellPopcorn(int orderNum) private void SellPopcorn(int orderNum)
@ -134,45 +312,6 @@ public class Market : MonoBehaviour
CoinManager.Instance.AddCoinWithEffect(flavor.Price * (1 + bonusRate / 100), () => { }); CoinManager.Instance.AddCoinWithEffect(flavor.Price * (1 + bonusRate / 100), () => { });
gameData.coin = CoinManager.Instance.OwnCoin; gameData.coin = CoinManager.Instance.OwnCoin;
GameDataManager.SaveGameData(); GameDataManager.SaveGameData();
// 自動補充 refill
RefillOneProduct();
var setStockFlag = false;
// 補充された場合フレーバー再設定
if (gameData.ShopStock.Count == ShopStockCount)
{
shuffledOrder.Add(orderNum);
displayFlavors[orderNum] = gameData.ShopStock.Last();
}
else if (gameData.ShopStock.Count <= 13 && shuffledOrder.Exists(x => x > 13))
{
displayFlavors = gameData.ShopStock.Select(x => x).ToList();
shuffledOrder = ShuffleOrder(displayFlavors.Count);
setStockFlag = true;
}
else if (gameData.ShopStock.Count <= 7 && shuffledOrder.Exists(x => x > 7))
{
displayFlavors = gameData.ShopStock.Select(x => x).ToList();
shuffledOrder = ShuffleOrder(displayFlavors.Count);
setStockFlag = true;
}
// 表示更新
this.CallWaitForSeconds(1f, () =>
{
stockView.SetStock(gameData.StorageTanks);
if (gameData.ShopStock.Count == ShopStockCount)
{
// 補充したフレーバーのスキンを設定
cartView.Refill(orderNum, displayFlavors[orderNum]);
}
else if (setStockFlag)
{
cartView.SetStock(displayFlavors);
}
});
StockFlavorLog();
} }
private List<int> ShuffleOrder(int length) private List<int> ShuffleOrder(int length)
@ -199,7 +338,7 @@ public class Market : MonoBehaviour
GameDataManager.SaveGameData(); GameDataManager.SaveGameData();
} }
private void FixStock() private void CheckAndFixStock()
{ {
if (GameDataManager.GameData.ShopStock.Count > ShopStockCount) if (GameDataManager.GameData.ShopStock.Count > ShopStockCount)
{ {

View File

@ -1601,6 +1601,7 @@ GameObject:
- component: {fileID: 658354830} - component: {fileID: 658354830}
- component: {fileID: 658354829} - component: {fileID: 658354829}
- component: {fileID: 658354828} - component: {fileID: 658354828}
- component: {fileID: 658354831}
m_Layer: 0 m_Layer: 0
m_Name: Main Camera m_Name: Main Camera
m_TagString: MainCamera m_TagString: MainCamera
@ -1673,6 +1674,22 @@ Transform:
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 0 m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &658354831
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 658354827}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 56666c5a40171f54783dd416a44f42bf, type: 3}
m_Name:
m_EditorClassIdentifier:
m_EventMask:
serializedVersion: 2
m_Bits: 4294967295
m_MaxRayIntersections: 0
--- !u!1 &676633148 --- !u!1 &676633148
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -11566,7 +11583,7 @@ PrefabInstance:
- target: {fileID: 5409985849651702441, guid: 6fbb038c9aae840f2bea57bce30740f7, - target: {fileID: 5409985849651702441, guid: 6fbb038c9aae840f2bea57bce30740f7,
type: 3} type: 3}
propertyPath: m_LocalPosition.y propertyPath: m_LocalPosition.y
value: -0.02 value: -1.07
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 5409985849651702441, guid: 6fbb038c9aae840f2bea57bce30740f7, - target: {fileID: 5409985849651702441, guid: 6fbb038c9aae840f2bea57bce30740f7,
type: 3} type: 3}

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using TMPro; using TMPro;
using UniRx;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@ -9,50 +11,61 @@ public class HeartMeter : SingletonMonoBehaviour<HeartMeter>
[SerializeField] private Slider slider; [SerializeField] private Slider slider;
[SerializeField] private TextMeshProUGUI heartLevel; [SerializeField] private TextMeshProUGUI heartLevel;
private Coroutine coroutine;
private List<int> levelList = new List<int>(); private List<int> levelList = new List<int>();
private int currentHeartCount; private int currentHeartCount;
private float tmpHeart; private readonly ReactiveProperty<float> viewHeartCount = new ReactiveProperty<float>();
private Coroutine coroutine; public IReadOnlyReactiveProperty<int> ShopLevel => shopLevel;
private readonly ReactiveProperty<int> shopLevel = new ReactiveProperty<int>();
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private void Awake()
{
if (CheckInstance()) return;
}
private void Start()
{
shopLevel.AddTo(this);
viewHeartCount.AddTo(this);
compositeDisposable.AddTo(this);
}
public void Initialize(List<int> list) public void Initialize(List<int> list)
{ {
levelList = list; levelList = list;
compositeDisposable.Clear();
shopLevel.Subscribe(x =>
{
heartLevel.text = $"{x}";
}).AddTo(compositeDisposable);
viewHeartCount.SkipLatestValueOnSubscribe().Subscribe(heartCount =>
{
if (levelList.Empty())
{
return;
}
shopLevel.Value = GetShopLevel(Mathf.FloorToInt(heartCount)) + 1;
if (levelList.Count == shopLevel.Value)
{
slider.value = 1;
}
else
{
slider.value = (heartCount - levelList[shopLevel.Value - 1]) / (levelList[shopLevel.Value] - levelList[shopLevel.Value - 1]);
}
}).AddTo(compositeDisposable);
} }
public void SetHeart(int heartCount) public void SetHeart(int heartCount)
{ {
Debug.Log($"{currentHeartCount}, {tmpHeart}");
currentHeartCount = heartCount; currentHeartCount = heartCount;
tmpHeart = heartCount; viewHeartCount.SetValueAndForceNotify(heartCount);
SetView(currentHeartCount);
} }
private void SetView(float heartCount) private int GetShopLevel(int heartCount)
{ {
var index = GetNextLevel(Mathf.FloorToInt(heartCount)); return levelList.FindLastIndex(x => x <= heartCount);
SetLevelView(index);
SetMeterView(heartCount, index);
}
private void SetLevelView(int level)
{
heartLevel.text = $"{level}";
}
private void SetMeterView(float heartCount, int index)
{
slider.value = (heartCount - levelList[index - 1]) / (levelList[index] - levelList[index - 1]);
}
private int GetNextLevel(int heartCount)
{
var index = levelList.FindIndex(x => x > heartCount);
if (levelList.Last() < heartCount)
{
index = levelList.Count - 1;
}
return index;
} }
public void AddHeart(int value) public void AddHeart(int value)
@ -65,8 +78,7 @@ public class HeartMeter : SingletonMonoBehaviour<HeartMeter>
}); });
this.CallLerp(1f, f => this.CallLerp(1f, f =>
{ {
tmpHeart += value * Time.deltaTime; viewHeartCount.Value = Mathf.Min(currentHeartCount, viewHeartCount.Value + value * Time.deltaTime);
SetView(Mathf.Min(currentHeartCount, tmpHeart));
}); });
} }
} }