1
This commit is contained in:
@@ -1970,6 +1970,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
long oldGold = sitData.goldNum; // 记录加金币前的值
|
||||
sitData.goldNum += goldToAdd; // 使用副本,不再依赖 killFish 对象
|
||||
sitData.tMP_GoldNum.text = sitData.goldNum.ToString();
|
||||
currGameType?.ShowGoldColumn(sitData, goldToAdd); // 座位金币柱(XJMH 覆写,其它房间空实现)
|
||||
AudioManager.Instance.PlayerFX(audioID);
|
||||
// ⭐ 记录金币流水:已加钱(杀鱼获得,本地已执行)
|
||||
GameManager.LogGoldFlowAppliedGain("KillFish", $"击中鱼原有金币={oldGold} 增加金币=+{goldToAdd} 剩余金币={sitData.goldNum} 鱼ID={fishId} 座位={sitData.posID} 房间={GameManager.Instance.gameData?.currRoomData?.roomId}");
|
||||
|
||||
@@ -2217,6 +2217,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
targetSit.goldNum += gold;
|
||||
if (targetSit.tMP_GoldNum != null)
|
||||
targetSit.tMP_GoldNum.text = targetSit.goldNum.ToString();
|
||||
ShowGoldColumn(targetSit, gold); // 鱼雷结算:使用者座位金币柱
|
||||
AudioManager.Instance.PlayerFX(audioID);
|
||||
};
|
||||
|
||||
@@ -2541,6 +2542,14 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
/// <summary>面板隐藏时清理炮台切换面板(子类覆写)。</summary>
|
||||
protected virtual void CleanupTurretPanel() { }
|
||||
|
||||
// ==================== 座位金币柱表现(子类扩展) ====================
|
||||
|
||||
/// <summary>
|
||||
/// 某座位加金币时的表现钩子(基类空实现,XJMH 覆写播金币柱)。
|
||||
/// 调用点:CreateFishManager 的 onScoreAdd(所有杀鱼/爆奖加分)、OnTorpedoResult 的 jiaFen。
|
||||
/// </summary>
|
||||
public virtual void ShowGoldColumn(SitPosData sit, long earn) { }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4261,6 +4261,7 @@ MonoBehaviour:
|
||||
btn_BluePT: {fileID: 6960561258226760454}
|
||||
btn_GoldPT: {fileID: 7017233470151915259}
|
||||
btn_VIPPT: {fileID: 5022068518759764265}
|
||||
goldColumnController: {fileID: 0}
|
||||
--- !u!1 &2865408747225355556
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -15195,6 +15196,11 @@ PrefabInstance:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 245637205031072731}
|
||||
m_Modifications:
|
||||
- target: {fileID: 992911195842070766, guid: e5efa9f179bbfdb4ba8e73fe85eb109a,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -8.900024
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2075051064728197762, guid: e5efa9f179bbfdb4ba8e73fe85eb109a,
|
||||
type: 3}
|
||||
propertyPath: m_Name
|
||||
@@ -16167,7 +16173,7 @@ PrefabInstance:
|
||||
- target: {fileID: 224712541214802931, guid: 606caf214eeaa6143a7a9921889255f6,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
value: -1193
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224712541214802931, guid: 606caf214eeaa6143a7a9921889255f6,
|
||||
type: 3}
|
||||
@@ -16789,7 +16795,7 @@ PrefabInstance:
|
||||
- target: {fileID: 224306456571944953, guid: f10599bb76bdc59489435868f1770551,
|
||||
type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
value: -1193
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 224306456571944953, guid: f10599bb76bdc59489435868f1770551,
|
||||
type: 3}
|
||||
|
||||
@@ -16,6 +16,11 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase
|
||||
// 按钮与列表索引的映射(顺序固定:Green=0, Blue=1, Gold=2, VIP=3)
|
||||
private Button[] _ptButtons;
|
||||
|
||||
// ==================== 金币柱 ====================
|
||||
[Tooltip("金币柱控制器:可在预制体上手动挂 GoldColumnController 并拖进来(参数可存盘);留空则运行时自动挂")]
|
||||
public GoldColumnController goldColumnController;
|
||||
private GoldColumnController _goldColumn;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
@@ -87,6 +92,27 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase
|
||||
{
|
||||
base.CleanupTurretPanel();
|
||||
HidePTPanel();
|
||||
_goldColumn?.Cleanup();
|
||||
}
|
||||
|
||||
// ==================== 金币柱 ====================
|
||||
|
||||
/// <summary>
|
||||
/// 座位加金币时播金币柱(基类钩子覆写)。
|
||||
/// 所有杀鱼/爆奖加分都会经此;自己座位用 Self 预制体、其他座位用 Other。
|
||||
/// </summary>
|
||||
public override void ShowGoldColumn(SitPosData sit, long earn)
|
||||
{
|
||||
if (sit == null || earn <= 0) return;
|
||||
|
||||
if (_goldColumn == null)
|
||||
{
|
||||
_goldColumn = goldColumnController != null ? goldColumnController : gameObject.AddComponent<GoldColumnController>();
|
||||
_goldColumn.Init(transform as RectTransform);
|
||||
}
|
||||
|
||||
bool isSelf = currSitData != null && sit == currSitData;
|
||||
_goldColumn.ShowOne(sit, earn, isSelf);
|
||||
}
|
||||
|
||||
/// <summary>隐藏切换面板(带缩放动画)</summary>
|
||||
|
||||
@@ -0,0 +1,501 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// 星际迷航(XJMH)金币柱控制器:座位每次加金币时,在座位炮台旁生成一根从下往上生长的金币柱,
|
||||
/// 柱头红/绿交替、顶部显示本次得分(万/千/亿缩写),多根并排最多 maxColumns 根。
|
||||
///
|
||||
/// 移植自 PW 小游戏的 PW_GoldColumn / PW_GoldColumnMgr:
|
||||
/// - 每座位一个队列,每帧最多补 1 根(连杀时排队上升);
|
||||
/// - 首根绿头(与 PW 的 ColumnType 初值 true 取反一致),之后红绿交替;
|
||||
/// - 队头停留 holdDuration 后淡出,其余整体向座位方向平移补位;
|
||||
/// - 队伍数量 > crowdThreshold 时队头不再额外停顿(快速滚动)。
|
||||
///
|
||||
/// 模板:面板根节点下已放好的 PW_GoldColumn_Self / PW_GoldColumn_Other 两个实例,
|
||||
/// 由 Init 自动查找并隐藏,运行时克隆复用。
|
||||
/// </summary>
|
||||
public class GoldColumnController : MonoBehaviour
|
||||
{
|
||||
// ==================== 可调参数("阈值") ====================
|
||||
|
||||
[Header("柱体上限 / 排列")]
|
||||
[Tooltip("每座位最多同时存在的金币柱数量")]
|
||||
public int maxColumns = 5;
|
||||
[Tooltip("队伍长度超过此值时,队头不再额外停顿(快速滚动)")]
|
||||
public int crowdThreshold = 3;
|
||||
[Tooltip("相邻柱的横向间距(像素)")]
|
||||
public float deltaX = 40f;
|
||||
[Tooltip("首柱相对座位锚点的横向外偏(像素)")]
|
||||
public float offsetX = 100f;
|
||||
[Tooltip("柱底相对座位锚点的纵向偏移(像素)")]
|
||||
public float seatAnchorOffsetY = 0f;
|
||||
|
||||
[Header("高度映射(沿用 PW 公式)")]
|
||||
[Tooltip("高度封顶值:score/scoreDivisor 达到此值即顶格")]
|
||||
public float heightCap = 255f;
|
||||
[Tooltip("得分系数:mul = (earn / 炮倍) / scoreDivisor")]
|
||||
public float scoreDivisor = 2f;
|
||||
[Tooltip("满格高度 = 面板高度 × 该比例")]
|
||||
public float barHeightToPanelRatio = 0.47f;
|
||||
[Tooltip(">0 时忽略 PW 公式,直接按 earn/该值 归一化(满格金额);=0 时用 PW 公式 earn/座位炮倍")]
|
||||
public long fullValue = 0;
|
||||
[Tooltip(">0 时直接作为满格高度(像素),覆盖上面的比例")]
|
||||
public float maxBarHeightOverride = 0f;
|
||||
|
||||
[Header("时长(秒)")]
|
||||
[Tooltip("生长 + 淡入时长")]
|
||||
public float growDuration = 0.3f;
|
||||
[Tooltip("队头停留时长(单根独占时)")]
|
||||
public float holdDuration = 2f;
|
||||
[Tooltip("补位平移时长")]
|
||||
public float shiftDuration = 0.17f;
|
||||
[Tooltip("淡出时长")]
|
||||
public float fadeDuration = 0.3f;
|
||||
[Tooltip("队伍不超过 crowdThreshold 时,新队头的额外停顿")]
|
||||
public float crowdDelay = 1f;
|
||||
|
||||
[Header("对象池")]
|
||||
[Tooltip("每种预制体缓存的空闲柱数量上限(超出直接销毁)")]
|
||||
public int preloadNum = 4;
|
||||
|
||||
[Header("模板名(面板根节点下的子物体名)")]
|
||||
public string selfTemplateName = "PW_GoldColumn_Self";
|
||||
public string otherTemplateName = "PW_GoldColumn_Other";
|
||||
|
||||
// ==================== 运行时状态 ====================
|
||||
|
||||
private RectTransform _panelRoot;
|
||||
private GameObject _selfTemplate;
|
||||
private GameObject _otherTemplate;
|
||||
|
||||
private readonly List<GoldColumnItem> _poolSelf = new List<GoldColumnItem>();
|
||||
private readonly List<GoldColumnItem> _poolOther = new List<GoldColumnItem>();
|
||||
|
||||
private readonly List<GoldColumnItem>[] _list = new List<GoldColumnItem>[4];
|
||||
private readonly Queue<PendingColumn>[] _queue = new Queue<PendingColumn>[4];
|
||||
// 红/绿交替标记:初值 true,取柱时先取反 → 首根绿头(与 PW 一致)
|
||||
private readonly bool[] _redFlag = new bool[4];
|
||||
|
||||
private float _barWidth = 25f;
|
||||
private bool _inited;
|
||||
|
||||
/// <summary>待生成的柱(入队时就把座位位置/炮倍固化,避免座位被销毁后的空引用)</summary>
|
||||
private struct PendingColumn
|
||||
{
|
||||
public long earn;
|
||||
public bool isSelf;
|
||||
public Vector2 basePos; // 座位在面板本地(锚点 0.5,0)的锚点坐标
|
||||
public float ratio; // 炮倍(>=1)
|
||||
public float sign; // 堆叠方向:座位在面板左 → -1,右 → +1
|
||||
}
|
||||
|
||||
// ==================== 初始化 / 清理 ====================
|
||||
|
||||
/// <summary>绑定面板根节点并查找两个模板(自动 SetActive(false))。</summary>
|
||||
public void Init(RectTransform panelRoot)
|
||||
{
|
||||
_panelRoot = panelRoot;
|
||||
_inited = false;
|
||||
if (_panelRoot == null)
|
||||
{
|
||||
Debug.LogWarning("[GoldColumn] panelRoot 为空,金币柱不启用");
|
||||
return;
|
||||
}
|
||||
|
||||
_selfTemplate = FindChildByName(_panelRoot, selfTemplateName)?.gameObject;
|
||||
_otherTemplate = FindChildByName(_panelRoot, otherTemplateName)?.gameObject;
|
||||
|
||||
if (_selfTemplate == null || _otherTemplate == null)
|
||||
{
|
||||
Debug.LogWarning($"[GoldColumn] 未在面板下找到模板 {selfTemplateName}({_selfTemplate != null}) / " +
|
||||
$"{otherTemplateName}({_otherTemplate != null}),金币柱不启用");
|
||||
return;
|
||||
}
|
||||
|
||||
// 模板本身只是资源,隐藏掉;取原始柱宽
|
||||
_selfTemplate.SetActive(false);
|
||||
_otherTemplate.SetActive(false);
|
||||
var tmplRt = _selfTemplate.transform as RectTransform;
|
||||
if (tmplRt != null && tmplRt.sizeDelta.x > 0f) _barWidth = tmplRt.sizeDelta.x;
|
||||
|
||||
for (int i = 0; i < _list.Length; i++)
|
||||
{
|
||||
_list[i] = new List<GoldColumnItem>();
|
||||
_queue[i] = new Queue<PendingColumn>();
|
||||
_redFlag[i] = true;
|
||||
}
|
||||
|
||||
_poolSelf.Clear();
|
||||
_poolOther.Clear();
|
||||
_inited = true;
|
||||
|
||||
Debug.Log($"[GoldColumn] Init: self={_selfTemplate.name} other={_otherTemplate.name} " +
|
||||
$"barW={_barWidth} panelH={_panelRoot.rect.height:0.#}");
|
||||
}
|
||||
|
||||
/// <summary>退房/隐藏时调用:杀掉所有动画、回收/销毁全部柱、清空队列(模板与控制器保留,可继续复用)。</summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
for (int pos = 0; pos < _list.Length; pos++)
|
||||
{
|
||||
var list = _list[pos];
|
||||
if (list == null) continue;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
DestroyItem(list[i]);
|
||||
list.Clear();
|
||||
_queue[pos]?.Clear();
|
||||
_redFlag[pos] = true;
|
||||
}
|
||||
_poolSelf.Clear();
|
||||
_poolOther.Clear();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
// ==================== 对外接口 ====================
|
||||
|
||||
/// <summary>座位加金币时调用(入队,由 Update 逐帧限流生成)。</summary>
|
||||
public void ShowOne(SitPosData sit, long earn, bool isSelf)
|
||||
{
|
||||
if (!_inited || sit == null || earn <= 0) return;
|
||||
|
||||
int pos = sit.posID;
|
||||
if (pos < 0 || pos >= _list.Length) return;
|
||||
|
||||
Vector3 local = _panelRoot.InverseTransformPoint(sit.transform.position);
|
||||
float ratio = sit.consumeGoldNum > 0 ? sit.consumeGoldNum : 1f;
|
||||
|
||||
// 柱锚点是 (0.5,0):锚点坐标 = 本地坐标 - 锚点参考点(面板底边中点)
|
||||
Rect r = _panelRoot.rect;
|
||||
Vector2 anchorRef = new Vector2(r.xMin + r.width * 0.5f, r.yMin);
|
||||
|
||||
_queue[pos].Enqueue(new PendingColumn
|
||||
{
|
||||
earn = earn,
|
||||
isSelf = isSelf,
|
||||
basePos = new Vector2(local.x - anchorRef.x, local.y - anchorRef.y),
|
||||
ratio = ratio,
|
||||
sign = local.x < 0f ? -1f : 1f,
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 逐帧驱动 ====================
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_inited) return;
|
||||
|
||||
for (int pos = 0; pos < _list.Length; pos++)
|
||||
{
|
||||
var list = _list[pos];
|
||||
|
||||
// ⭐ 每座位每帧最多补 1 根(复刻 PW CheckData,连杀才会排队上升,不能写成 while)
|
||||
if (_queue[pos].Count > 0 && list.Count < maxColumns)
|
||||
SpawnOne(pos);
|
||||
|
||||
// 队头计时
|
||||
if (list.Count > 0)
|
||||
{
|
||||
var head = list[0];
|
||||
if (!head.fading)
|
||||
{
|
||||
head.holdRemaining -= Time.deltaTime;
|
||||
if (head.holdRemaining <= 0f)
|
||||
FadeOutHead(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnOne(int pos)
|
||||
{
|
||||
var pending = _queue[pos].Dequeue();
|
||||
var template = pending.isSelf ? _selfTemplate : _otherTemplate;
|
||||
var item = GetItem(template, pending.isSelf);
|
||||
var list = _list[pos];
|
||||
|
||||
item.isSelf = pending.isSelf;
|
||||
item.pos = pos;
|
||||
item.sign = pending.sign;
|
||||
item.basePos = pending.basePos;
|
||||
item.index = list.Count;
|
||||
item.fading = false;
|
||||
item.holdRemaining = float.MaxValue; // 非队头不倒计时
|
||||
|
||||
// 红/绿交替:取反后赋给红头(首根为绿,与 PW 一致)
|
||||
_redFlag[pos] = !_redFlag[pos];
|
||||
bool showRed = _redFlag[pos];
|
||||
if (item.headRed != null) item.headRed.SetActive(showRed);
|
||||
if (item.headGreen != null) item.headGreen.SetActive(!showRed);
|
||||
|
||||
// 文本(原版 Lua: self.num:SetText(ChangeUnit(num)))
|
||||
SetNum(item, ChangeUnit(pending.earn));
|
||||
|
||||
// 位置:座位锚点 + 方向 × (首柱外偏 + 序号间距)
|
||||
float x = pending.basePos.x + pending.sign * (offsetX + item.index * deltaX);
|
||||
float y = pending.basePos.y + seatAnchorOffsetY;
|
||||
item.rt.anchoredPosition = new Vector2(x, y);
|
||||
|
||||
// 高度:默认沿用 PW 公式 score=earn/炮倍 → mul=score/scoreDivisor → 封顶归一化;
|
||||
// fullValue>0 时改用「满格金额」(earn/fullValue) 归一化,便于快速调参
|
||||
float score = pending.earn / pending.ratio;
|
||||
float mul = score / Mathf.Max(0.0001f, scoreDivisor);
|
||||
float norm = fullValue > 0
|
||||
? Mathf.Clamp01((float)pending.earn / fullValue)
|
||||
: Mathf.Clamp01(Mathf.Min(mul, heightCap) / Mathf.Max(1f, heightCap));
|
||||
float panelH = _panelRoot.rect.height;
|
||||
if (panelH <= 1f) panelH = Screen.height; // 兜底:面板高度取不到时用屏幕高
|
||||
float maxBarHeight = maxBarHeightOverride > 0f ? maxBarHeightOverride : panelH * barHeightToPanelRatio;
|
||||
float aimHeight = norm * maxBarHeight;
|
||||
|
||||
// 诊断:高度不变化时看这行数值
|
||||
Debug.Log($"[GoldColumn] pos={pos} earn={pending.earn} ratio={pending.ratio} score={score:0.##} " +
|
||||
$"mul={mul:0.##} norm={norm:0.####} panelH={panelH:0.#} maxBarH={maxBarHeight:0.#} aimH={aimHeight:0.#} " +
|
||||
$"barW={_barWidth} text={item.numText != null} tmp={item.numTmp != null}");
|
||||
|
||||
// 生长(动画 sizeDelta.y,不能动 fillAmount:柱头/数字锚在父顶边,靠父变高上移)
|
||||
item.rt.DOKill();
|
||||
item.alphaTween?.Kill();
|
||||
item.rt.sizeDelta = new Vector2(_barWidth, 0f);
|
||||
item.alpha = 0f;
|
||||
ApplyAlpha(item, 0f);
|
||||
item.rtTween = item.rt.DOSizeDelta(new Vector2(_barWidth, aimHeight), growDuration).SetEase(Ease.OutCubic);
|
||||
item.alphaTween = DOTween.To(() => item.alpha, a => { item.alpha = a; ApplyAlpha(item, a); }, 1f, growDuration)
|
||||
.SetEase(Ease.OutQuad);
|
||||
|
||||
list.Add(item);
|
||||
|
||||
// 单根独占时走 holdDuration(PW:EnterAction 里 index==1 → 2 秒)
|
||||
if (list.Count == 1)
|
||||
item.holdRemaining = holdDuration;
|
||||
}
|
||||
|
||||
/// <summary>队头淡出 → 回收 → 其余柱整体向座位平移补位。</summary>
|
||||
private void FadeOutHead(int pos)
|
||||
{
|
||||
var list = _list[pos];
|
||||
if (list.Count == 0) return;
|
||||
|
||||
var head = list[0];
|
||||
head.fading = true;
|
||||
list.RemoveAt(0);
|
||||
|
||||
head.rtTween?.Kill();
|
||||
head.alphaTween?.Kill();
|
||||
head.alphaTween = DOTween.To(() => head.alpha, a => { head.alpha = a; ApplyAlpha(head, a); }, 0f, fadeDuration)
|
||||
.SetEase(Ease.InQuad)
|
||||
.OnComplete(() => RecycleItem(head));
|
||||
|
||||
// 补位:所有剩余柱 index-1,向座位方向移动 deltaX
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
var item = list[i];
|
||||
item.index = i;
|
||||
float targetX = item.rt.anchoredPosition.x - item.sign * deltaX;
|
||||
item.rtTween?.Kill();
|
||||
item.rtTween = item.rt.DOAnchorPosX(targetX, shiftDuration).SetEase(Ease.Linear);
|
||||
}
|
||||
|
||||
// 新队头停顿(PW:队伍数量 > 3 → 0,否则 crowdDelay)
|
||||
if (list.Count > 0)
|
||||
{
|
||||
var newHead = list[0];
|
||||
newHead.fading = false;
|
||||
newHead.holdRemaining = list.Count > crowdThreshold ? 0f : crowdDelay;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 对象池 ====================
|
||||
|
||||
private GoldColumnItem GetItem(GameObject template, bool isSelf)
|
||||
{
|
||||
var pool = isSelf ? _poolSelf : _poolOther;
|
||||
GoldColumnItem item = null;
|
||||
if (pool.Count > 0)
|
||||
{
|
||||
item = pool[pool.Count - 1];
|
||||
pool.RemoveAt(pool.Count - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
item = CreateItem(template);
|
||||
}
|
||||
item.go.SetActive(true);
|
||||
return item;
|
||||
}
|
||||
|
||||
private GoldColumnItem CreateItem(GameObject template)
|
||||
{
|
||||
var go = Instantiate(template, _panelRoot);
|
||||
go.name = template.name + "_Clone";
|
||||
var rt = go.transform as RectTransform;
|
||||
var numNode = FindChildByName(rt, "Num");
|
||||
|
||||
var item = new GoldColumnItem
|
||||
{
|
||||
go = go,
|
||||
rt = rt,
|
||||
rootImg = go.GetComponent<Image>(),
|
||||
headRed = FindChildByName(rt, "1")?.gameObject,
|
||||
headGreen = FindChildByName(rt, "2")?.gameObject,
|
||||
// ⭐ 原版预制体 Num 上是 UGUI Text(m_Text "999万"),不是 TMP;两者都取,谁有写谁
|
||||
numText = numNode != null ? numNode.GetComponent<Text>() : null,
|
||||
numTmp = numNode != null ? numNode.GetComponent<TextMeshProUGUI>() : null,
|
||||
};
|
||||
if (numNode != null && item.numText == null && item.numTmp == null)
|
||||
{
|
||||
// 兜底:Text/TMP 挂在 Num 的子物体上
|
||||
item.numText = numNode.GetComponentInChildren<Text>(true);
|
||||
item.numTmp = numNode.GetComponentInChildren<TextMeshProUGUI>(true);
|
||||
}
|
||||
|
||||
// ⭐ 模板为了让自己在编辑器里不露出来可能把 fillAmount 设小 → 强制整条可见;柱高全靠 sizeDelta.y
|
||||
if (item.rootImg != null)
|
||||
{
|
||||
item.rootImg.type = Image.Type.Simple;
|
||||
item.rootImg.fillAmount = 1f;
|
||||
}
|
||||
|
||||
// ⭐ 柱是纯表现,不能挡棋盘点击
|
||||
item.graphics = go.GetComponentsInChildren<Graphic>(true);
|
||||
item.origAlpha = new float[item.graphics.Length];
|
||||
for (int i = 0; i < item.graphics.Length; i++)
|
||||
{
|
||||
item.graphics[i].raycastTarget = false;
|
||||
item.origAlpha[i] = item.graphics[i].color.a;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private void RecycleItem(GoldColumnItem item)
|
||||
{
|
||||
if (item == null) return;
|
||||
|
||||
item.rt?.DOKill();
|
||||
item.alphaTween?.Kill();
|
||||
|
||||
var pool = item.isSelf ? _poolSelf : _poolOther;
|
||||
if (pool.Count < preloadNum)
|
||||
{
|
||||
item.go.SetActive(false);
|
||||
item.fading = false;
|
||||
item.holdRemaining = float.MaxValue;
|
||||
pool.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(item.go);
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyItem(GoldColumnItem item)
|
||||
{
|
||||
if (item == null) return;
|
||||
item.rt?.DOKill();
|
||||
item.alphaTween?.Kill();
|
||||
if (item.go != null) Destroy(item.go);
|
||||
}
|
||||
|
||||
// ==================== 工具 ====================
|
||||
|
||||
/// <summary>写 Num 文本(原版 Lua: self.num:SetText),UGUI Text 与 TMP 都兼容。</summary>
|
||||
private static void SetNum(GoldColumnItem item, string text)
|
||||
{
|
||||
if (item == null) return;
|
||||
if (item.numText != null) item.numText.text = text;
|
||||
if (item.numTmp != null) item.numTmp.text = text;
|
||||
}
|
||||
|
||||
/// <summary>把 Graphic 的透明度按 a(0~1)乘回原值。</summary>
|
||||
private void ApplyAlpha(GoldColumnItem item, float a)
|
||||
{
|
||||
if (item.graphics == null) return;
|
||||
for (int i = 0; i < item.graphics.Length; i++)
|
||||
{
|
||||
var g = item.graphics[i];
|
||||
if (g == null) continue;
|
||||
var c = g.color;
|
||||
c.a = item.origAlpha[i] * a;
|
||||
g.color = c;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>数字缩写(万/千/亿),移植自 PW_GoldColumn:ChangeUnit。</summary>
|
||||
private static string ChangeUnit(long num)
|
||||
{
|
||||
if (num >= 10000000L)
|
||||
{
|
||||
double v = Math.Floor(num * 100.0 / 100000000.0) / 100.0;
|
||||
return v.ToString("0.00") + "亿";
|
||||
}
|
||||
if (num >= 1000000L)
|
||||
{
|
||||
long v = (long)Math.Floor(num / 10000.0);
|
||||
return v + "万";
|
||||
}
|
||||
if (num >= 100000L)
|
||||
{
|
||||
double v = Math.Floor(num * 10.0 / 10000.0) / 10.0;
|
||||
return v.ToString("0.0") + "万";
|
||||
}
|
||||
if (num >= 10000L)
|
||||
{
|
||||
double v = Math.Floor(num * 100.0 / 10000.0) / 100.0;
|
||||
return v.ToString("0.00") + "万";
|
||||
}
|
||||
if (num >= 1000L)
|
||||
{
|
||||
double v = Math.Floor(num * 100.0 / 1000.0) / 100.0;
|
||||
return v.ToString("0.00") + "千";
|
||||
}
|
||||
return num.ToString();
|
||||
}
|
||||
|
||||
/// <summary>递归按名字查找子物体。</summary>
|
||||
private static Transform FindChildByName(Transform parent, string name)
|
||||
{
|
||||
if (parent == null || string.IsNullOrEmpty(name)) return null;
|
||||
if (parent.name == name) return parent;
|
||||
for (int i = 0; i < parent.childCount; i++)
|
||||
{
|
||||
var result = FindChildByName(parent.GetChild(i), name);
|
||||
if (result != null) return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>单个金币柱实例。</summary>
|
||||
private class GoldColumnItem
|
||||
{
|
||||
public GameObject go;
|
||||
public RectTransform rt;
|
||||
public Image rootImg;
|
||||
public GameObject headRed;
|
||||
public GameObject headGreen;
|
||||
// Num 节点:原版预制体挂的是 UGUI Text(PW 的 SetText 就是它),这里同时兼容 TMP
|
||||
public Text numText;
|
||||
public TextMeshProUGUI numTmp;
|
||||
public Graphic[] graphics;
|
||||
public float[] origAlpha;
|
||||
|
||||
public bool isSelf;
|
||||
public int pos;
|
||||
public int index;
|
||||
public float sign;
|
||||
public Vector2 basePos;
|
||||
public float holdRemaining;
|
||||
public bool fading;
|
||||
public float alpha;
|
||||
|
||||
public Tween rtTween;
|
||||
public Tween alphaTween;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8241b2fef05a1194085a61f39c0d2deb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user