功能:添加启动器场景并更新项目设置
- 调整了启动器场景名(Assets/Launcher.unity)及对应的元数据文件。 - 添加了README.md项目文档,包含安装说明、项目结构、编码规范、测试指南及依赖项。
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class GoodsItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Image _iconImage;
|
||||
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
[SerializeField] private TMP_Text _typeText;
|
||||
|
||||
[SerializeField] private TMP_Text _descriptionText;
|
||||
|
||||
[SerializeField] private TMP_Text _costText;
|
||||
|
||||
[SerializeField] private CommonButton _purchaseButton;
|
||||
|
||||
#region Init
|
||||
|
||||
public void Init(GoodsItemContext data)
|
||||
{
|
||||
_iconImage.sprite = data.Icon;
|
||||
_titleText.text = data.Title;
|
||||
_typeText.text = data.Type;
|
||||
_descriptionText.text = data.Description;
|
||||
_costText.text = data.Price.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 271f2a0727c521c4280eb2d47fd8de33
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,103 @@
|
||||
using Components;
|
||||
using CustomEvent;
|
||||
using Entity;
|
||||
using GameFramework.Event;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class HudForm : UGuiForm
|
||||
{
|
||||
[SerializeField] private float _sliderFadeDuration = 0.5f;
|
||||
|
||||
[SerializeField] private Slider _hpSlider;
|
||||
private float _currentHpPercent = 0;
|
||||
private Coroutine _hpSliderFadeCoroutine;
|
||||
|
||||
[SerializeField] private Slider _expSlider;
|
||||
private float _currentExpPercent = 0;
|
||||
private Coroutine _expSliderFadeCoroutine;
|
||||
|
||||
[SerializeField] private TMP_Text _coinText;
|
||||
private int _currentCoin = 0;
|
||||
|
||||
#region FSM
|
||||
|
||||
protected override void OnInit(object userData)
|
||||
{
|
||||
base.OnInit(userData);
|
||||
|
||||
GameEntry.Event.Subscribe(PlayerHealthChangeEventArgs.EventId, OnPlayerHpChange);
|
||||
GameEntry.Event.Subscribe(PlayerExpChangeEventArgs.EventId, OnPlayerExpChange);
|
||||
GameEntry.Event.Subscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
GameEntry.Event.Unsubscribe(PlayerHealthChangeEventArgs.EventId, OnPlayerHpChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerExpChangeEventArgs.EventId, OnPlayerExpChange);
|
||||
GameEntry.Event.Unsubscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnPlayerHpChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerHealthChangeEventArgs args)) return;
|
||||
float percent = (float)args.CurrentHealth / args.MaxHealth;
|
||||
if (Mathf.Approximately(_currentHpPercent, percent)) return;
|
||||
|
||||
_currentHpPercent = percent;
|
||||
|
||||
if (_hpSliderFadeCoroutine != null) StopCoroutine(_hpSliderFadeCoroutine);
|
||||
_hpSliderFadeCoroutine = StartCoroutine(_hpSlider.SmoothValue(percent, _sliderFadeDuration));
|
||||
}
|
||||
|
||||
private void OnPlayerExpChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerExpChangeEventArgs args)) return;
|
||||
float percent = (float)args.CurrentExp / args.MaxExp;
|
||||
if (Mathf.Approximately(_currentExpPercent, percent)) return;
|
||||
|
||||
_currentExpPercent = percent;
|
||||
|
||||
if (_expSliderFadeCoroutine != null) StopCoroutine(_expSliderFadeCoroutine);
|
||||
_expSliderFadeCoroutine = StartCoroutine(_expSlider.SmoothValue(percent, _sliderFadeDuration));
|
||||
}
|
||||
|
||||
private void OnPlayerCoinChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerCoinChangeEventArgs args)) return;
|
||||
if (_currentCoin == args.CoinCount) return;
|
||||
|
||||
_coinText.text = args.CoinCount.ToString();
|
||||
_currentCoin = args.CoinCount;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Test
|
||||
|
||||
private Player _player;
|
||||
|
||||
public void CauseDamageToPlayer()
|
||||
{
|
||||
if (_player == null)
|
||||
{
|
||||
_player = FindObjectOfType<Player>();
|
||||
}
|
||||
|
||||
if (_player == null) return;
|
||||
|
||||
_player.GetComponent<HealthComponent>().TakeDamage(2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd4c4d6e8d4b0f54c830e2cfef46848e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
using CustomEvent;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpForm : UGuiForm
|
||||
{
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
[SerializeField] private LevelUpPropItem[] _propItems;
|
||||
|
||||
private LevelUpFormContext _context;
|
||||
|
||||
public void RefreshUI(LevelUpFormContext context)
|
||||
{
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = $"Level Up (Lv.{_context.Level})";
|
||||
}
|
||||
|
||||
foreach (var propItem in _propItems)
|
||||
{
|
||||
propItem.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (_context.Props == null) return;
|
||||
for (int i = 0; i < _propItems.Length; i++)
|
||||
{
|
||||
_propItems[i].gameObject.SetActive(true);
|
||||
_propItems[i].Init(_context.Props[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#region FSM
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
if (userData is LevelUpFormContext context)
|
||||
{
|
||||
RefreshUI(context);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("LevelUpForm requires LevelUpFormContext as userData.");
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
_context = null;
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnSelectProp(int index)
|
||||
{
|
||||
GameEntry.Event.Fire(this, LevelUpPropSelectedEventArgs.Create(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73f52c8a6d8b8ec42ad8cd3c00e0254d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class LevelUpPropItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Image _iconImage;
|
||||
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
[SerializeField] private TMP_Text _typeText;
|
||||
|
||||
[SerializeField] private TMP_Text _descriptionText;
|
||||
|
||||
private LevelUpPropContext _context;
|
||||
|
||||
|
||||
public void Init(LevelUpPropContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
Log.Error("LevelUpPropContext context is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null) _titleText.text = context.Title;
|
||||
if (_typeText != null) _typeText.text = context.Type;
|
||||
if (_descriptionText != null) _descriptionText.text = context.Description;
|
||||
if (_iconImage != null) _iconImage.sprite = context.Icon;
|
||||
|
||||
LoadIcon(_context.IconAssetName);
|
||||
}
|
||||
|
||||
private void LoadIcon(string iconAssetName)
|
||||
{
|
||||
if (_iconImage == null) return;
|
||||
|
||||
if (string.IsNullOrEmpty(iconAssetName)) return;
|
||||
|
||||
GameEntry.SpriteCache.GetSprite(iconAssetName, sprite => _iconImage.sprite = sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 237d64392d274c14f9f5c81b54122a93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,110 @@
|
||||
using CustomEvent;
|
||||
using GameFramework.Event;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
public class ShopForm : UGuiForm
|
||||
{
|
||||
#region Property
|
||||
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
[SerializeField] private TMP_Text _continueButtonText;
|
||||
|
||||
[SerializeField] private TMP_Text _refreshPriceText;
|
||||
|
||||
[SerializeField] private TMP_Text _playerCoinText;
|
||||
private int _currentCoin;
|
||||
|
||||
[SerializeField] private GoodsItem[] _goodsItems;
|
||||
|
||||
private ShopFormContext _context;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public void RefreshUI(ShopFormContext context)
|
||||
{
|
||||
_context = context;
|
||||
|
||||
_titleText.text = $"商店 (Lv.{context.CurrentLevel})";
|
||||
_continueButtonText.text = $"继续 (Lv.{context.CurrentLevel + 1})";
|
||||
_refreshPriceText.text = $"-{context.RefreshPrice}";
|
||||
_playerCoinText.text = context.PlayerCoin.ToString();
|
||||
|
||||
foreach (var item in _goodsItems)
|
||||
{
|
||||
item.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (_context.GoodsItems == null) return;
|
||||
for (int i = 0; i < _context.GoodsItems.Count; i++)
|
||||
{
|
||||
_goodsItems[i].Init(context.GoodsItems[i]);
|
||||
_goodsItems[i].gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
#region ButtonClick
|
||||
|
||||
public void OnContinueButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, ShopContinueEventArgs.Create());
|
||||
}
|
||||
|
||||
public void OnPurchaseButtonClick(int index)
|
||||
{
|
||||
GameEntry.Event.Fire(this, ShopPurchaseEventArgs.Create(index));
|
||||
}
|
||||
|
||||
public void OnRefreshButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, ShopRefreshEventArgs.Create(_context.RefreshPrice));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region FSM
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
GameEntry.Event.Subscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
|
||||
if (userData is ShopFormContext context)
|
||||
{
|
||||
RefreshUI(context);
|
||||
return;
|
||||
}
|
||||
|
||||
UnityGameFramework.Runtime.Log.Warning("ShopForm requires ShopFormContext as userData.");
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
_context = null;
|
||||
|
||||
GameEntry.Event.Unsubscribe(PlayerCoinChangeEventArgs.EventId, OnPlayerCoinChange);
|
||||
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnPlayerCoinChange(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is PlayerCoinChangeEventArgs args)) return;
|
||||
if (args.CoinCount == _currentCoin) return;
|
||||
|
||||
_currentCoin = args.CoinCount;
|
||||
_playerCoinText.text = _currentCoin.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6f22432e5701804d9a78d0c07f4c334
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user