This commit is contained in:
2026-09-22 03:59:20 +08:00
parent c612f527ea
commit af7a380e18
147 changed files with 28761 additions and 26 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fa7bc334f6405104db8bcd505104c32e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,201 @@
using Assets.Framework.Tool;
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 抽奖 item 层(第三层):挂在 toggle 层里的每个奖品格子上,
/// 记录道具信息以及奖励的详细信息(prize:类型/数量/权重/库存/道具 product 等),
/// 并负责展示——图标 + 数量文本由代码动态生成在格子下;
/// 已抽中的奖项置灰(奖励不重复)。
///
/// itemId = 本格子的位置编号(对应 prizeId 后两位,如 588203 → 3),
/// 初始化时奖品按它对号入座,Inspector 里按美术摆放顺序填 1、2、3……
/// </summary>
public class ChouJiangItem : MonoBehaviour
{
[Tooltip("本格子的位置编号 = prizeId 后两位(如 588203 → 3),初始化时奖品按它对号入座")]
public int itemId;
[Header("动态生成参数")]
[Tooltip("图标占格子短边的比例")]
public float iconRatio = 0.85f;
[Tooltip("图标中心相对格子中心的纵向偏移(0=居中,负数=往下贴)")]
public float iconOffsetY = 0f;
[Tooltip("数量文本字号")]
public float fontSize = 22f;
[Tooltip("已抽中置灰的颜色")]
public Color drawnColor = new Color(0.35f, 0.35f, 0.35f, 0.5f);
[Tooltip("遮罩蒙版图片(可选):适配不规则格子;蒙版大小=格子(背景)大小,图标放进蒙版里被裁出形状")]
public Sprite maskSprite;
[Header("奖励数据(Init 时由代码填充,Play 模式选中物体可实时查看)")]
[Tooltip("道具信息 + 奖励详细信息(prizeId/名称/图标/类型/数量/道具 product/权重/库存)")]
public LotteryPrize prize;
[Tooltip("是否已被抽中(奖励不重复,抽中后置灰)")]
[SerializeField] private bool isDrawn;
/// <summary>是否已被抽中</summary>
public bool IsDrawn => isDrawn;
private Image img_Icon; // 动态生成的图标
private TextMeshProUGUI tmp_Count; // 动态生成的数量文本
private GameObject maskObj; // 动态生成的遮罩蒙版(不规则裁剪用)
// 金币/钻石本地图标(Resources 根目录,与 BackPackPropItem 同一套),静态缓存避免重复加载
private static Sprite _goldSprite;
private static Sprite _diamondSprite;
/// <summary>记录奖励数据并展示(图标 + 数量)</summary>
public void Init(LotteryPrize prize)
{
this.prize = prize; // 记录道具信息以及奖励的详细信息
ClearUI();
if (prize == null) return;
RectTransform rt = transform as RectTransform;
if (rt == null)
{
Debug.LogWarning($"[ChouJiangItem] 格子不是 UI(缺 RectTransform):{name}");
return;
}
float w = rt.rect.width, h = rt.rect.height;
if (w < 1f || h < 1f) { w = 90f; h = 79f; } // 无尺寸兜底
// 遮罩蒙版:大小=格子(背景)大小,图标放进蒙版里被裁出形状(适配不规则格子)
RectTransform iconParent = rt;
if (maskSprite != null)
iconParent = CreateMask(rt, w, h);
// 图标:方形占短边 iconRatio,居中(iconOffsetY 可微调)
float side = Mathf.Min(w, h) * iconRatio;
img_Icon = CreateIcon(iconParent, side);
SetPrizeIcon(img_Icon, prize);
// 数量:压在图标底部(文字叠在图片上面,不进蒙版)
tmp_Count = CreateCountText(rt, w, side);
tmp_Count.text = prize.count.ToString();
// 新数据默认未抽中,已抽列表由面板 Init 后统一刷新
RefreshDrawnState(false);
}
/// <summary>置灰/恢复(奖励不重复,抽中后置灰)</summary>
public void RefreshDrawnState(bool drawn)
{
isDrawn = drawn;
if (img_Icon != null)
img_Icon.color = drawn ? drawnColor : Color.white;
}
/// <summary>清掉动态生成的 UI(重复 Init 复用前调用)</summary>
public void ClearUI()
{
if (img_Icon != null) { Destroy(img_Icon.gameObject); img_Icon = null; }
if (tmp_Count != null) { Destroy(tmp_Count.gameObject); tmp_Count = null; }
if (maskObj != null) { Destroy(maskObj); maskObj = null; }
}
/// <summary>生成遮罩蒙版:Image(maskSprite)+ Mask,居中、大小=格子(背景)大小;图标放它下面被裁剪</summary>
private RectTransform CreateMask(RectTransform parent, float w, float h)
{
maskObj = new GameObject("Mask", typeof(RectTransform));
RectTransform r = (RectTransform)maskObj.transform;
r.SetParent(parent, false);
r.anchorMin = r.anchorMax = r.pivot = Vector2.one * 0.5f;
r.anchoredPosition = Vector2.zero;
// 遮罩 0.9 倍背景大小(试过比全尺寸好看)
r.sizeDelta = new Vector2(w * 0.9f, h * 0.9f);
Image maskImg = maskObj.AddComponent<Image>();
maskImg.sprite = maskSprite;
maskImg.raycastTarget = false;
// 只当裁剪形状用,不显示蒙版图本身
Mask mask = maskObj.AddComponent<Mask>();
mask.showMaskGraphic = false;
return r;
}
/// <summary>生成格子里的图标物体(往下贴 iconOffsetY)</summary>
private Image CreateIcon(RectTransform parent, float side)
{
GameObject go = new GameObject("Icon", typeof(RectTransform));
RectTransform r = (RectTransform)go.transform;
r.SetParent(parent, false);
r.anchorMin = r.anchorMax = r.pivot = Vector2.one * 0.5f;
r.anchoredPosition = new Vector2(0f, iconOffsetY);
r.sizeDelta = new Vector2(side, side);
Image img = go.AddComponent<Image>();
img.raycastTarget = false;
return img;
}
/// <summary>生成压在图标底部的数量文本</summary>
private TextMeshProUGUI CreateCountText(RectTransform parent, float w, float iconSide)
{
GameObject go = new GameObject("Count", typeof(RectTransform));
RectTransform r = (RectTransform)go.transform;
r.SetParent(parent, false);
r.anchorMin = r.anchorMax = r.pivot = Vector2.one * 0.5f;
// 图标底边往上 0.8 个字高:文字压在图片上面
r.anchoredPosition = new Vector2(0f, iconOffsetY - iconSide / 2f + fontSize * 0.8f);
r.sizeDelta = new Vector2(w, fontSize * 1.6f);
TextMeshProUGUI tmp = go.AddComponent<TextMeshProUGUI>();
TMP_FontAsset font = TMP_Settings.defaultFontAsset;
if (font != null) tmp.font = font;
tmp.fontSize = fontSize;
tmp.alignment = TextAlignmentOptions.Center;
tmp.color = Color.white;
tmp.raycastTarget = false;
return tmp;
}
/// <summary>
/// 设置奖励图标:1=金币 / 2=钻石 用 Resources 本地图,
/// 3=道具 / 4=道具碎片 下载 icon(为空时用 product.imageUrl)。
/// </summary>
private void SetPrizeIcon(Image img, LotteryPrize prize)
{
switch (prize.type)
{
case 1: // 金币
Sprite gold = _goldSprite != null ? _goldSprite
: (_goldSprite = Resources.Load<Sprite>("gold"));
if (gold != null) img.sprite = gold;
break;
case 2: // 钻石
Sprite diamond = _diamondSprite != null ? _diamondSprite
: (_diamondSprite = Resources.Load<Sprite>("diamond"));
if (diamond != null) img.sprite = diamond;
break;
default: // 道具/碎片:下载图标
string url = prize.icon;
if (string.IsNullOrEmpty(url) && prize.product != null)
url = prize.product.imageUrl;
if (!string.IsNullOrEmpty(url))
{
WebTool.DownImage(url, tex =>
{
// 回调触发时本物体可能已被销毁(关闭面板清空父节点),需判空
if (this == null || img == null) return;
if (tex != null)
img.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height),
Vector2.one * 0.5f);
});
}
break;
}
}
private void OnDestroy()
{
ClearUI();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59c98b7739d292e409a9c611858e6ee5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,299 @@
using Assets.MyGame.Scripts.Net;
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
using Assets.MyGame.Scripts.Net.APIRequest.Params;
using Assets.MyGame.Scripts.Net.APIResponses;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>奖池分组(swagger:0=旧调用兼容,1=炮台,2=战神,3=翅膀)</summary>
public enum LotteryPoolType
{
旧调用 = 0,
炮台 = 1,
战神 = 2,
翅膀 = 3,
}
/// <summary>
/// 抽奖活动总面板(第一层·最外层,ChouJiang.prefab 根节点)。
///
/// 三层结构:
/// 第一层 本面板:拉配置、切分组、抽奖、花费/次数显示;
/// 第二层 ChouJiangToggle:挂 PT炮台/CB翅膀/ZS战神 三个 toggle 面板,一个 toggle 对应一个面板,
/// 面板里一堆 item 分为 A/B/C 三个列表(items_A/items_B/items_C);
/// 第三层 ChouJiangItem:挂每个奖品格子,记录道具信息以及奖励的详细信息。
///
/// 流程:OnShow 拉取活动配置(/api/ActivityConfig/lotteryConfig)→ 初始化各 toggle 的 item
/// → 拉取已抽奖项置灰 + 用户状态(/api/Lottery/UserStatus)显示花费/次数
/// → 点抽奖调 /api/Lottery/Draw?poolType=当前分组。
///
/// 花费规则(swagger):costs 独立计费非累加——第 N+1 次抽花 costs[N],超出长度取最后一个;
/// userMaxDraw=0 不限次数;isFinished 或达到上限后不能再抽。
/// </summary>
public class ChouJiangPanel : SubUIBase
{
[Tooltip("三个 toggle 面板按顺序拖:[0]=炮台,[1]=战神,[2]=翅膀(poolType 按列表顺序自动赋值)")]
public List<ChouJiangToggle> toggles;
[Tooltip("分组切换按钮按顺序拖:[0]=炮台,[1]=战神,[2]=翅膀(还没做就留空)")]
public List<Toggle> toggles_PoolType;
[Header("可选 UI(没摆就留空,不影响逻辑)")]
public Button btn_Draw; // 抽奖按钮
public TextMeshProUGUI tmp_ActivityName; // 活动名
public TextMeshProUGUI tmp_Cost; // 下一次抽奖花费
public TextMeshProUGUI tmp_DrawCount; // 已抽次数/上限
public TextMeshProUGUI tmp_EndTime; // 活动结束时间/状态
/// <summary>当前展示/抽奖的奖池分组</summary>
public LotteryPoolType currPoolType { get; private set; }
private LotteryActivityConfig config; // 活动配置
private LotteryUserStatus userStatus; // 用户抽奖状态(次数决定花费与上限)
private bool isDrawing; // 防连点
public override void Awake()
{
base.Awake();
// toggles 列表顺序即分组:[0]=炮台,[1]=战神,[2]=翅膀(按顺序自动赋 poolType,不用逐个手设)
if (toggles != null)
{
int n = Mathf.Min(toggles.Count, 3);
for (int i = 0; i < n; i++)
{
if (toggles[i] != null)
toggles[i].poolType = (LotteryPoolType)(i + 1);
}
}
// 分组切换:一个按钮对应一个 toggle 面板(索引 0/1/2 = 炮台/战神/翅膀)
if (toggles_PoolType != null)
{
for (int i = 0; i < toggles_PoolType.Count; i++)
{
if (toggles_PoolType[i] == null) continue;
LotteryPoolType type = (LotteryPoolType)(i + 1);
toggles_PoolType[i].onValueChanged.AddListener(isOn =>
{
if (isOn) ShowPoolType(type);
});
}
}
if (btn_Draw != null)
btn_Draw.onClick.AddListener(OnDrawClick);
// 初始分组 = 预制体里当前激活的面板,并同步一次面板/按钮状态
ChouJiangToggle first = GetActiveToggle();
currPoolType = first != null ? first.poolType : LotteryPoolType.炮台;
ShowPoolType(currPoolType);
}
protected override void OnShow(object args = null)
{
base.OnShow(args);
Refresh();
}
/// <summary>拉取活动配置 + 刷新各 toggle 与用户状态</summary>
public void Refresh()
{
APIRequestList.GetLotteryActivityConfig(cfg =>
{
if (this == null) return;
config = cfg;
UpdateActivityUI();
InitToggles();
RefreshUserStatus();
});
}
/// <summary>初始化各 toggle 面板的 item(A/B/C 三个列表),并置灰已抽中的奖项</summary>
private void InitToggles()
{
if (toggles == null || config == null) return;
for (int i = 0; i < toggles.Count; i++)
{
if (toggles[i] != null)
toggles[i].Init(config);
}
RefreshDrawnPrizes();
}
/// <summary>拉取用户抽奖状态(已抽次数决定下一次花费与是否到上限)</summary>
private void RefreshUserStatus()
{
APIRequestList.GetLotteryUserStatus(status =>
{
if (this == null) return;
userStatus = status;
UpdateDrawUI();
});
}
/// <summary>拉取已抽奖项列表,置灰各 toggle 的对应 item(奖励不重复)</summary>
private void RefreshDrawnPrizes()
{
APIRequestList.GetLotteryDrawnPrizes(ids =>
{
if (this == null || toggles == null) return;
for (int i = 0; i < toggles.Count; i++)
{
if (toggles[i] != null)
toggles[i].RefreshDrawnState(ids);
}
});
}
/// <summary>切到指定分组的 toggle 面板</summary>
public void ShowPoolType(LotteryPoolType type)
{
currPoolType = type;
if (toggles != null)
{
for (int i = 0; i < toggles.Count; i++)
{
if (toggles[i] == null) continue;
toggles[i].gameObject.SetActive(toggles[i].poolType == type);
}
}
// 同步切换按钮勾选状态(不触发回调)
if (toggles_PoolType != null)
{
int idx = (int)type - 1;
for (int i = 0; i < toggles_PoolType.Count; i++)
{
if (toggles_PoolType[i] == null || i == idx) continue;
toggles_PoolType[i].SetIsOnWithoutNotify(false);
}
if (idx >= 0 && idx < toggles_PoolType.Count && toggles_PoolType[idx] != null)
toggles_PoolType[idx].SetIsOnWithoutNotify(true);
}
UpdateDrawButtonState();
}
/// <summary>取当前激活的 toggle 面板(都没有激活时取第一个)</summary>
private ChouJiangToggle GetActiveToggle()
{
if (toggles == null || toggles.Count == 0) return null;
for (int i = 0; i < toggles.Count; i++)
{
if (toggles[i] != null && toggles[i].gameObject.activeSelf)
return toggles[i];
}
return toggles[0];
}
/// <summary>活动信息显示</summary>
private void UpdateActivityUI()
{
if (config == null) return;
if (tmp_ActivityName != null)
tmp_ActivityName.text = config.activityName;
if (tmp_EndTime != null)
{
if (!config.isOpen)
tmp_EndTime.text = "活动未开启";
else if (config.endTime > 0)
tmp_EndTime.text = "结束时间 " + DateTimeOffset
.FromUnixTimeSeconds(config.endTime).LocalDateTime.ToString("yyyy/MM/dd HH:mm");
else
tmp_EndTime.text = "长期活动";
}
}
/// <summary>花费/次数/按钮状态显示</summary>
private void UpdateDrawUI()
{
int drawn = userStatus != null ? userStatus.totalDrawCount : 0;
if (tmp_Cost != null)
tmp_Cost.text = GetNextCost().ToString();
if (tmp_DrawCount != null)
tmp_DrawCount.text = config != null && config.userMaxDraw > 0
? $"{drawn}/{config.userMaxDraw}"
: drawn.ToString();
UpdateDrawButtonState();
}
private void UpdateDrawButtonState()
{
if (btn_Draw != null)
btn_Draw.interactable = CanDraw() && !isDrawing;
}
/// <summary>下一次抽奖花费:第 N+1 次取 costs[N],超出长度取最后一个(独立计费非累加)</summary>
private long GetNextCost()
{
if (config == null || config.costs == null || config.costs.Count == 0) return 0;
int drawn = userStatus != null ? userStatus.totalDrawCount : 0;
int idx = Mathf.Min(drawn, config.costs.Count - 1);
return config.costs[idx];
}
/// <summary>能否再抽:活动开启、在时间内、未抽完、未达次数上限</summary>
private bool CanDraw()
{
if (config == null || !config.isOpen) return false;
if (userStatus != null && userStatus.isFinished) return false;
long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
if (config.startTime > 0 && now < config.startTime) return false;
if (config.endTime > 0 && now > config.endTime) return false;
if (config.userMaxDraw > 0 && userStatus != null
&& userStatus.totalDrawCount >= config.userMaxDraw) return false;
return true;
}
/// <summary>抽奖:GET /api/Lottery/Draw?poolType=当前分组</summary>
private void OnDrawClick()
{
if (isDrawing || !CanDraw()) return;
isDrawing = true;
UpdateDrawButtonState();
bool done = false;
APIRequestList.LotteryDraw(new LotteryDrawParam { poolType = (int)currPoolType }, res =>
{
done = true;
if (this == null) return;
// 抽中结果(结算 UI 摆好后在这里接入)
Debug.Log($"[ChouJiangPanel] 抽中:{res.name} x{res.count}(type={res.type},消耗={res.cost},分组={(LotteryPoolType)res.poolType})");
// 花费随次数增长、已抽奖项要置灰,重拉状态刷新
RefreshUserStatus();
RefreshDrawnPrizes();
});
// code!=0 时 APIManager 只弹错误不回调,超时兜底解锁防连点锁死
StartCoroutine(IEWaitDrawDone(() => done));
}
/// <summary>等待抽奖回调完成(最多 10 秒),结束解锁按钮</summary>
private IEnumerator IEWaitDrawDone(Func<bool> done)
{
float t = 0f;
while (!done() && t < 10f)
{
t += Time.deltaTime;
yield return null;
}
isDrawing = false;
UpdateDrawButtonState();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c3692baaedece14fa8c7527b163ced3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,142 @@
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 抽奖 toggle 层(第二层):挂在总面板里的三个 toggle 面板(PT炮台 / CB翅膀 / ZS战神)其中一个上,
/// poolType 决定本面板显示哪组奖池;面板里有一堆 item(ChouJiangItem,第三层),
/// 分为三种 item 类型也就是 A/B/C 三个列表:
/// items_A(A级·大奖)/ items_B(B级·中奖)/ items_C(C级·小奖)
/// Init 时筛出本组奖池、同等级合并,每个奖品按 prizeId 后两位(itemId)找到自己的格子。
/// </summary>
public class ChouJiangToggle : MonoBehaviour
{
[Tooltip("本面板的奖池分组:1=炮台,2=战神,3=翅膀(总面板按 toggles 列表顺序自动赋值,一般不用手设)")]
public LotteryPoolType poolType = LotteryPoolType.炮台;
[Tooltip("A级(大奖)item,按展示顺序拖")]
public List<ChouJiangItem> items_A;
[Tooltip("B级(中奖)item,按展示顺序拖")]
public List<ChouJiangItem> items_B;
[Tooltip("C级(小奖)item,按展示顺序拖")]
public List<ChouJiangItem> items_C;
/// <summary>
/// 初始化:筛出本组(poolType)的全部奖池,同等级合并后,
/// A/B/C 级的奖品各自按 prizeId 后两位(itemId)找到自己的格子。
/// </summary>
public void Init(LotteryActivityConfig config)
{
// 先清空所有 item 的旧数据
ClearItems(items_A);
ClearItems(items_B);
ClearItems(items_C);
if (config == null || config.pools == null || config.pools.Count == 0)
{
Debug.LogWarning($"[ChouJiangToggle] 抽奖配置为空(poolType={poolType})");
return;
}
// 同组同等级可能配多条奖池,先按等级合并再分发
Dictionary<string, List<LotteryPrize>> prizesByLevel = new Dictionary<string, List<LotteryPrize>>();
foreach (LotteryPoolLevel pool in config.pools)
{
if (pool == null || pool.poolType != (int)poolType) continue;
string level = pool.level != null ? pool.level.ToUpperInvariant() : null;
if (level != "A" && level != "B" && level != "C")
{
Debug.LogWarning($"[ChouJiangToggle] 未知奖池等级 {pool.level}(只支持 A/B/C)");
continue;
}
List<LotteryPrize> list;
if (!prizesByLevel.TryGetValue(level, out list))
{
list = new List<LotteryPrize>();
prizesByLevel[level] = list;
}
if (pool.prizeList != null) list.AddRange(pool.prizeList);
}
FillLevel("A", items_A, prizesByLevel);
FillLevel("B", items_B, prizesByLevel);
FillLevel("C", items_C, prizesByLevel);
}
/// <summary>按已抽奖项列表置灰本面板所有 item(奖励不重复)</summary>
public void RefreshDrawnState(List<string> drawnPrizeIds)
{
ApplyDrawn(items_A, drawnPrizeIds);
ApplyDrawn(items_B, drawnPrizeIds);
ApplyDrawn(items_C, drawnPrizeIds);
}
/// <summary>每个奖品按 prizeId 后两位找到自己的 item(itemId 对号入座)</summary>
private void FillLevel(string level, List<ChouJiangItem> items, Dictionary<string, List<LotteryPrize>> prizesByLevel)
{
if (items == null || items.Count == 0) return;
List<LotteryPrize> prizes;
prizesByLevel.TryGetValue(level, out prizes);
if (prizes == null || prizes.Count == 0)
{
Debug.LogWarning($"[ChouJiangToggle] {poolType} 组没有 {level} 级奖池");
return;
}
for (int i = 0; i < prizes.Count; i++)
{
int no = ParseItemId(prizes[i].prizeId);
ChouJiangItem item = FindItemById(items, no);
if (item == null)
{
Debug.LogWarning($"[ChouJiangToggle] {poolType} 组 {level} 级奖品 {prizes[i].prizeId}(编号 {no})找不到对应 itemId 的 item,跳过");
continue;
}
item.Init(prizes[i]);
}
}
/// <summary>取 prizeId 后两位作为位置编号(如 588203 → 3);解析失败返回 -1</summary>
private static int ParseItemId(string prizeId)
{
if (string.IsNullOrEmpty(prizeId) || prizeId.Length < 2) return -1;
int no;
if (!int.TryParse(prizeId.Substring(prizeId.Length - 2), out no)) return -1;
return no;
}
/// <summary>按位置编号找 item;找不到返回 null</summary>
private static ChouJiangItem FindItemById(List<ChouJiangItem> items, int itemId)
{
if (itemId < 0 || items == null) return null;
for (int i = 0; i < items.Count; i++)
{
if (items[i] != null && items[i].itemId == itemId) return items[i];
}
return null;
}
private void ApplyDrawn(List<ChouJiangItem> items, List<string> drawnPrizeIds)
{
if (items == null) return;
for (int i = 0; i < items.Count; i++)
{
if (items[i] == null || items[i].prize == null) continue;
string prizeId = items[i].prize.prizeId;
items[i].RefreshDrawnState(!string.IsNullOrEmpty(prizeId)
&& drawnPrizeIds != null && drawnPrizeIds.Contains(prizeId));
}
}
private void ClearItems(List<ChouJiangItem> items)
{
if (items == null) return;
for (int i = 0; i < items.Count; i++)
{
if (items[i] != null) items[i].Init(null);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 940297b369ce43043bf02ea74c3ed80f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: