特效处理
This commit is contained in:
@@ -15897,7 +15897,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 801.1, y: -366.5}
|
||||
m_AnchoredPosition: {x: 223, y: -366.5}
|
||||
m_SizeDelta: {x: 246, y: 396}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3830484646943208791
|
||||
@@ -67792,6 +67792,11 @@ PrefabInstance:
|
||||
value:
|
||||
objectReference: {fileID: 11400000, guid: 01284b3a32c7e83468569928f5c73965,
|
||||
type: 2}
|
||||
- target: {fileID: 5060419867541585992, guid: 4df885aec65db17408fe5f416586659b,
|
||||
type: 3}
|
||||
propertyPath: allowMultipleCanvasRenderers
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5330474313186595698, guid: 4df885aec65db17408fe5f416586659b,
|
||||
type: 3}
|
||||
propertyPath: m_IsActive
|
||||
@@ -68017,14 +68022,19 @@ PrefabInstance:
|
||||
propertyPath: m_IsActive
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedComponents:
|
||||
- {fileID: 5060419867541585992, guid: 4df885aec65db17408fe5f416586659b, type: 3}
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects:
|
||||
- targetCorrespondingSourceObject: {fileID: 8853572317385043517, guid: 4df885aec65db17408fe5f416586659b,
|
||||
type: 3}
|
||||
insertIndex: 0
|
||||
addedObject: {fileID: 9040017639815608408}
|
||||
m_AddedComponents: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 6926977592608490996, guid: 4df885aec65db17408fe5f416586659b,
|
||||
type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 5779381528187236056}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 4df885aec65db17408fe5f416586659b, type: 3}
|
||||
--- !u!224 &263134585676878738 stripped
|
||||
RectTransform:
|
||||
@@ -68032,6 +68042,89 @@ RectTransform:
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 8752995051435752879}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1826618619158689883 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 6926977592608490996, guid: 4df885aec65db17408fe5f416586659b,
|
||||
type: 3}
|
||||
m_PrefabInstance: {fileID: 8752995051435752879}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!114 &5779381528187236056
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1826618619158689883}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d85b887af7e6c3f45a2e2d2920d641bc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 2100000, guid: 349c2798841dd9f4c89acdb1e52cbf3b, type: 2}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
skeletonDataAsset: {fileID: 11400000, guid: 01284b3a32c7e83468569928f5c73965, type: 2}
|
||||
initialSkinName: default
|
||||
initialFlipX: 0
|
||||
initialFlipY: 0
|
||||
startingAnimation: idle
|
||||
startingLoop: 1
|
||||
timeScale: 1
|
||||
freeze: 0
|
||||
updateWhenInvisible: 3
|
||||
unscaledTime: 0
|
||||
allowMultipleCanvasRenderers: 1
|
||||
canvasRenderers:
|
||||
- {fileID: 201318676101694961}
|
||||
- {fileID: 8235293816368149592}
|
||||
- {fileID: 2446405798293491568}
|
||||
- {fileID: 340079405198258509}
|
||||
- {fileID: 5062598685067098695}
|
||||
- {fileID: 1207224931900852095}
|
||||
- {fileID: 1455918537387431194}
|
||||
- {fileID: 2103692984007865899}
|
||||
- {fileID: 3424533732130890899}
|
||||
- {fileID: 8656755274658975106}
|
||||
- {fileID: 7371864405799979440}
|
||||
- {fileID: 2286248722853339403}
|
||||
- {fileID: 3862144865375682425}
|
||||
- {fileID: 5316933298778596933}
|
||||
- {fileID: 5494442923517133337}
|
||||
- {fileID: 2945609307869315189}
|
||||
- {fileID: 2270748183178458588}
|
||||
- {fileID: 4867439765306778051}
|
||||
- {fileID: 8574667605618192794}
|
||||
- {fileID: 3748848972706537091}
|
||||
- {fileID: 6010473928609515947}
|
||||
- {fileID: 2448868564627096078}
|
||||
- {fileID: 4920217292007767453}
|
||||
- {fileID: 5590666519804690853}
|
||||
- {fileID: 6217535141042166839}
|
||||
- {fileID: 5282035822308975466}
|
||||
- {fileID: 330046349550623742}
|
||||
- {fileID: 798947272716457757}
|
||||
- {fileID: 955824026465409844}
|
||||
- {fileID: 3924789657280705301}
|
||||
- {fileID: 6319058580571699530}
|
||||
separatorSlotNames: []
|
||||
enableSeparatorSlots: 0
|
||||
separatorParts: []
|
||||
updateSeparatorPartLocation: 1
|
||||
meshGenerator:
|
||||
settings:
|
||||
useClipping: 1
|
||||
zSpacing: 0
|
||||
pmaVertexColors: 1
|
||||
tintBlack: 0
|
||||
canvasGroupTintBlack: 0
|
||||
calculateTangents: 0
|
||||
addNormals: 0
|
||||
immutableTriangles: 0
|
||||
--- !u!114 &1869197814322494115 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 6955909806736836364, guid: 4df885aec65db17408fe5f416586659b,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06b6699f783747445ae6a6ad233d3725
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,285 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using TMPro;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// ChouJiangItem 批量绑定工具(编辑器专用)。
|
||||
/// 把预制体拖进窗口(或 Project 里选中预制体/文件夹后点「从当前选中添加」),再点「开始绑定」:
|
||||
/// 工具会找出所有名字以 ItemGrid 开头的格子,给每个格子挂上 ChouJiangItem,并按子物体名自动赋值:
|
||||
///
|
||||
/// Item → img_Icon(该节点上的 Image 组件)
|
||||
/// Label → tmp_Count(该节点上是 TMP 时)/ tmp_Count_Old(该节点上是 UGUI Text 时)
|
||||
/// 道具名字节点 → tmp_Name / tmp_Name_Old(节点名在窗口里配,留空则不处理)
|
||||
/// GridMask → obj_Drawn
|
||||
/// eff_xuan → obj_Selecting
|
||||
/// eff_xuanzhong → obj_Landed
|
||||
///
|
||||
/// 节点名先在**直接子物体**里精确匹配(ItemGrid 下还有同名的 GridMask 子节点,
|
||||
/// 所以必须优先取直接子物体),找不到再退到子树里找第一个同名节点。
|
||||
/// itemId 不动,交给 ChouJiangToggle 按列表顺序自动编号。
|
||||
/// </summary>
|
||||
public class ChouJiangItemBinder : EditorWindow
|
||||
{
|
||||
const string CellPrefix = "ItemGrid"; // 格子节点名前缀
|
||||
const string NodeIcon = "Item"; // 奖品图片
|
||||
const string NodeLabel = "Label"; // 数量文本
|
||||
const string NodeDrawn = "GridMask"; // 已抽中遮罩
|
||||
const string NodeSelecting = "eff_xuan"; // 选中高亮
|
||||
const string NodeLanded = "eff_xuanzhong"; // 抽中停留
|
||||
|
||||
[SerializeField] List<GameObject> targets = new List<GameObject>();
|
||||
[SerializeField] string nameNode = ""; // 道具名字节点名,留空=不处理
|
||||
[SerializeField] bool keepExisting = false; // 已有引用不覆盖
|
||||
|
||||
Vector2 scroll;
|
||||
|
||||
[MenuItem("Tools/抽奖/批量绑定 ChouJiangItem")]
|
||||
static void Open()
|
||||
{
|
||||
ChouJiangItemBinder w = GetWindow<ChouJiangItemBinder>("抽奖 Item 绑定");
|
||||
w.minSize = new Vector2(440f, 360f);
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUILayout.LabelField("把预制体拖进来(或 Project 里选中后点下面的按钮)", EditorStyles.boldLabel);
|
||||
|
||||
Rect dropArea = GUILayoutUtility.GetRect(0f, 46f, GUILayout.ExpandWidth(true));
|
||||
GUI.Box(dropArea, "拖预制体 / 文件夹到这里");
|
||||
HandleDrag(dropArea);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("从当前选中添加")) AddFromSelection();
|
||||
if (GUILayout.Button("清空列表")) targets.Clear();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
nameNode = EditorGUILayout.TextField("道具名字节点名(留空=不处理)", nameNode);
|
||||
keepExisting = EditorGUILayout.Toggle("保留已有引用(不覆盖)", keepExisting);
|
||||
|
||||
EditorGUILayout.LabelField($"待绑定预制体:{targets.Count} 个");
|
||||
scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Height(110f));
|
||||
for (int i = targets.Count - 1; i >= 0; i--)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
targets[i] = (GameObject)EditorGUILayout.ObjectField(targets[i], typeof(GameObject), false);
|
||||
if (GUILayout.Button("×", GUILayout.Width(24f))) targets.RemoveAt(i);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
using (new EditorGUI.DisabledScope(targets.Count == 0))
|
||||
{
|
||||
if (GUILayout.Button("开始绑定", GUILayout.Height(30f))) Run();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- 目标收集 ----------------
|
||||
|
||||
void HandleDrag(Rect area)
|
||||
{
|
||||
Event e = Event.current;
|
||||
if (e == null || !area.Contains(e.mousePosition)) return;
|
||||
if (e.type != EventType.DragUpdated && e.type != EventType.DragPerform) return;
|
||||
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
if (e.type == EventType.DragPerform)
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
foreach (Object o in DragAndDrop.objectReferences) AddTarget(o);
|
||||
e.Use();
|
||||
}
|
||||
}
|
||||
|
||||
void AddFromSelection()
|
||||
{
|
||||
int before = targets.Count;
|
||||
foreach (Object o in Selection.objects) AddTarget(o);
|
||||
if (targets.Count == before) Debug.LogWarning("[抽奖绑定] 当前选中里没有预制体或含预制体的文件夹");
|
||||
}
|
||||
|
||||
void AddTarget(Object o)
|
||||
{
|
||||
// 文件夹:递归收集里面的预制体
|
||||
string path = AssetDatabase.GetAssetPath(o);
|
||||
if (!string.IsNullOrEmpty(path) && AssetDatabase.IsValidFolder(path))
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { path });
|
||||
foreach (string g in guids) AddTarget(AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(g)));
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject go = o as GameObject;
|
||||
if (go == null)
|
||||
{
|
||||
Debug.LogWarning("[抽奖绑定] 只支持预制体(GameObject),已跳过:" + o);
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(path) || !path.EndsWith(".prefab"))
|
||||
{
|
||||
Debug.LogWarning("[抽奖绑定] 不是预制体文件,已跳过:" + go.name);
|
||||
return;
|
||||
}
|
||||
if (!targets.Contains(go)) targets.Add(go);
|
||||
}
|
||||
|
||||
// ---------------- 执行绑定 ----------------
|
||||
|
||||
void Run()
|
||||
{
|
||||
List<string> paths = new List<string>();
|
||||
foreach (GameObject go in targets)
|
||||
{
|
||||
string p = AssetDatabase.GetAssetPath(go);
|
||||
if (!string.IsNullOrEmpty(p) && !paths.Contains(p)) paths.Add(p);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int cellAll = 0, missAll = 0;
|
||||
|
||||
for (int i = 0; i < paths.Count; i++)
|
||||
{
|
||||
string path = paths[i];
|
||||
EditorUtility.DisplayProgressBar("绑定 ChouJiangItem", path, (float)i / paths.Count);
|
||||
try
|
||||
{
|
||||
int cells, miss;
|
||||
BindOne(path, out cells, out miss);
|
||||
cellAll += cells;
|
||||
missAll += miss;
|
||||
sb.AppendLine($"{System.IO.Path.GetFileName(path)}:格子 {cells} 个" +
|
||||
(miss > 0 ? $",{miss} 个有缺失节点(见 Console 警告)" : ",全部绑定完成"));
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
sb.AppendLine($"{System.IO.Path.GetFileName(path)}:失败 {ex.Message}");
|
||||
Debug.LogError($"[抽奖绑定] {path} 处理失败:{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
targets.Clear();
|
||||
Debug.Log($"[抽奖绑定] 完成,共 {cellAll} 个格子,{missAll} 个有缺失节点\n{sb}");
|
||||
}
|
||||
|
||||
void BindOne(string path, out int cellCount, out int missingCount)
|
||||
{
|
||||
cellCount = 0;
|
||||
missingCount = 0;
|
||||
|
||||
GameObject root = PrefabUtility.LoadPrefabContents(path);
|
||||
try
|
||||
{
|
||||
Transform[] all = root.GetComponentsInChildren<Transform>(true);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
Transform t = all[i];
|
||||
if (!t.name.StartsWith(CellPrefix)) continue;
|
||||
|
||||
// 防止把同名前缀的容器误当格子:必须带 Item 或 GridMask 直接子物体
|
||||
if (t.Find(NodeIcon) == null && t.Find(NodeDrawn) == null) continue;
|
||||
|
||||
cellCount++;
|
||||
|
||||
ChouJiangItem item = t.GetComponent<ChouJiangItem>();
|
||||
if (item == null) item = t.gameObject.AddComponent<ChouJiangItem>();
|
||||
|
||||
int missing = 0;
|
||||
|
||||
// 奖品图片
|
||||
Image icon = FindComp<Image>(t, NodeIcon);
|
||||
if (icon != null) { if (!keepExisting || item.img_Icon == null) item.img_Icon = icon; }
|
||||
else missing++;
|
||||
|
||||
// 数量文本:TMP 优先,没有 TMP 再用 UGUI Text(两版互斥)
|
||||
Transform label = FindNode(t, NodeLabel);
|
||||
TextMeshProUGUI tmp = label != null ? label.GetComponent<TextMeshProUGUI>() : null;
|
||||
Text txt = label != null ? label.GetComponent<Text>() : null;
|
||||
if (tmp != null)
|
||||
{
|
||||
if (!keepExisting || item.tmp_Count == null) { item.tmp_Count = tmp; item.tmp_Count_Old = null; }
|
||||
}
|
||||
else if (txt != null)
|
||||
{
|
||||
if (!keepExisting || item.tmp_Count_Old == null) { item.tmp_Count_Old = txt; item.tmp_Count = null; }
|
||||
}
|
||||
else missing++;
|
||||
|
||||
// 道具名字(节点名可配,留空不处理)
|
||||
if (!string.IsNullOrEmpty(nameNode))
|
||||
{
|
||||
Transform nameT = FindNode(t, nameNode);
|
||||
TextMeshProUGUI nameTmp = nameT != null ? nameT.GetComponent<TextMeshProUGUI>() : null;
|
||||
Text nameTxt = nameT != null ? nameT.GetComponent<Text>() : null;
|
||||
if (nameTmp != null)
|
||||
{
|
||||
if (!keepExisting || item.tmp_Name == null) { item.tmp_Name = nameTmp; item.tmp_Name_Old = null; }
|
||||
}
|
||||
else if (nameTxt != null)
|
||||
{
|
||||
if (!keepExisting || item.tmp_Name_Old == null) { item.tmp_Name_Old = nameTxt; item.tmp_Name = null; }
|
||||
}
|
||||
}
|
||||
|
||||
// 三个状态 GameObject
|
||||
Transform drawn = FindNode(t, NodeDrawn);
|
||||
if (drawn != null) { if (!keepExisting || item.obj_Drawn == null) item.obj_Drawn = drawn.gameObject; }
|
||||
else missing++;
|
||||
|
||||
Transform selecting = FindNode(t, NodeSelecting);
|
||||
if (selecting != null) { if (!keepExisting || item.obj_Selecting == null) item.obj_Selecting = selecting.gameObject; }
|
||||
else missing++;
|
||||
|
||||
Transform landed = FindNode(t, NodeLanded);
|
||||
if (landed != null) { if (!keepExisting || item.obj_Landed == null) item.obj_Landed = landed.gameObject; }
|
||||
else missing++;
|
||||
|
||||
if (missing > 0)
|
||||
{
|
||||
missingCount++;
|
||||
Debug.LogWarning($"[抽奖绑定] {System.IO.Path.GetFileName(path)} → 格子 {t.name} 缺 {missing} 个节点" +
|
||||
"(Item / Label / GridMask / eff_xuan / eff_xuanzhong)");
|
||||
}
|
||||
}
|
||||
|
||||
if (cellCount == 0)
|
||||
{
|
||||
Debug.LogWarning($"[抽奖绑定] {path} 里没找到名字以 {CellPrefix} 开头、且带 Item 或 GridMask 的格子");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrefabUtility.SaveAsPrefabAsset(root, path);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
PrefabUtility.UnloadPrefabContents(root);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- 查找 ----------------
|
||||
|
||||
/// <summary>先找直接子物体(精确同名),找不到再在整个子树里找第一个同名节点</summary>
|
||||
static Transform FindNode(Transform cell, string name)
|
||||
{
|
||||
Transform direct = cell.Find(name);
|
||||
if (direct != null) return direct;
|
||||
|
||||
Transform[] all = cell.GetComponentsInChildren<Transform>(true);
|
||||
for (int i = 0; i < all.Length; i++)
|
||||
{
|
||||
if (all[i] != cell && all[i].name == name) return all[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static T FindComp<T>(Transform cell, string name) where T : Component
|
||||
{
|
||||
Transform n = FindNode(cell, name);
|
||||
return n != null ? n.GetComponent<T>() : null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c7eb0452470ed54ca72730328199fbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fda7ba84219c7041adfc0234a371c65
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
-114
@@ -1,114 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
/// <summary>
|
||||
/// 大厅图集切片烘焙工具(绕开 TextureImporter 管线,纯 Unity API):
|
||||
/// 1. 读取 NGUI 图集 prefab 的 mSprites 坐标
|
||||
/// 2. Sprite.Create 从大图切出 56 个 sprite,AssetDatabase.CreateAsset 落盘
|
||||
/// 3. 大厅 prefab 里 108 个 Image 按节点语义规则重绑切片
|
||||
/// 菜单:Tools / 烘焙大厅图集切片
|
||||
/// </summary>
|
||||
public static class BakeLobbySlicesTool
|
||||
{
|
||||
const string AtlasPrefabPath = "Assets/dataresources/atlas/a大厅/atlas_bylobbyclassic/Atlas_ByLobbyClassic.prefab";
|
||||
const string AtlasTexPath = "Assets/dataresources/atlas/a大厅/atlas_bylobbyclassic/Atlas_ByLobbyClassic.png";
|
||||
const string OutDir = "Assets/BakeLobbySlicesAssets";
|
||||
const string LobbyPrefabPath = "Assets/bundles/by_lobby/bundles/panel/BY_LbPlayMainUGUIPanel.prefab";
|
||||
|
||||
[MenuItem("Tools/烘焙大厅图集切片")]
|
||||
public static void Bake()
|
||||
{
|
||||
// ---------- 1. 读图集坐标 ----------
|
||||
var atlasObj = AssetDatabase.LoadAssetAtPath<Object>(AtlasPrefabPath);
|
||||
if (atlasObj == null) { Debug.LogError("[烘焙] 图集 prefab 加载失败: " + AtlasPrefabPath); return; }
|
||||
var so = new SerializedObject(atlasObj);
|
||||
var mSprites = so.FindProperty("mSprites");
|
||||
if (mSprites == null || !mSprites.isArray || mSprites.arraySize == 0)
|
||||
{ Debug.LogError("[烘焙] mSprites 读取失败 (arraySize=" + (mSprites == null ? -1 : mSprites.arraySize) + ")"); return; }
|
||||
|
||||
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(AtlasTexPath);
|
||||
if (tex == null) { Debug.LogError("[烘焙] 大图加载失败,请先等 Unity 刷新完成: " + AtlasTexPath); return; }
|
||||
Debug.Log($"[烘焙] 图集 {mSprites.arraySize} 切片, 大图 {tex.width}x{tex.height}");
|
||||
|
||||
// ---------- 2. 切片落盘 ----------
|
||||
if (!AssetDatabase.IsValidFolder(OutDir)) AssetDatabase.CreateFolder("Assets", "BakeLobbySlicesAssets");
|
||||
var made = new Dictionary<string, Sprite>();
|
||||
for (int i = 0; i < mSprites.arraySize; i++)
|
||||
{
|
||||
var el = mSprites.GetArrayElementAtIndex(i);
|
||||
string name = el.FindPropertyRelative("name").stringValue;
|
||||
var rect = new Rect(el.FindPropertyRelative("x").floatValue, el.FindPropertyRelative("y").floatValue,
|
||||
el.FindPropertyRelative("width").floatValue, el.FindPropertyRelative("height").floatValue);
|
||||
var border = new Vector4(el.FindPropertyRelative("borderLeft").floatValue, el.FindPropertyRelative("borderBottom").floatValue,
|
||||
el.FindPropertyRelative("borderRight").floatValue, el.FindPropertyRelative("borderTop").floatValue);
|
||||
var sp = Sprite.Create(tex, rect, new Vector2(0.5f, 0.5f), 100f, 0, SpriteMeshType.FullRect, border);
|
||||
sp.name = name;
|
||||
var path = $"{OutDir}/{name}.asset";
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
AssetDatabase.CreateAsset(sp, path);
|
||||
made[name] = sp;
|
||||
}
|
||||
Debug.Log($"[烘焙] 生成 {made.Count} 个 sprite asset → {OutDir}");
|
||||
|
||||
// ---------- 3. 重绑大厅 prefab ----------
|
||||
var root = PrefabUtility.LoadPrefabContents(LobbyPrefabPath);
|
||||
int bound = 0, missing = 0;
|
||||
try
|
||||
{
|
||||
var images = root.GetComponentsInChildren<UnityEngine.UI.Image>(true);
|
||||
foreach (var img in images)
|
||||
{
|
||||
var sp = PickSlice(img.gameObject.name, made);
|
||||
if (sp != null) { img.sprite = sp; bound++; }
|
||||
else missing++;
|
||||
}
|
||||
PrefabUtility.SaveAsPrefabAsset(root, LobbyPrefabPath);
|
||||
}
|
||||
finally { PrefabUtility.UnloadPrefabContents(root); }
|
||||
Debug.Log($"[烘焙] prefab 重绑 {bound} 个 Image, 未匹配 {missing} 个 —— 完成!");
|
||||
}
|
||||
|
||||
// 节点名 → 切片(与此前 Python 修复用的语义规则一致,最后有兜底)
|
||||
static Sprite PickSlice(string n, Dictionary<string, Sprite> m)
|
||||
{
|
||||
string s = null;
|
||||
if (Regex.IsMatch(n, @"Frame_bg$")) s = "topbar_frame";
|
||||
else if (n.Contains("Frame_lobby")) s = "topbar_def2";
|
||||
else if (n.Contains("topbar_btn")) s = "topbar_btn";
|
||||
else if (n.Contains("BtnClassic") || n == "Classic") s = "ic_tab_n1";
|
||||
else if (n.Contains("BtnSuper") || n == "Super") s = "ic_tab_n2";
|
||||
else if (n.Contains("BtnSiuxian") || n == "Siuxian") s = "ic_tab_n3";
|
||||
else if (n.Contains("BtnFold")) s = "ic_tab_n4";
|
||||
else if (n.StartsWith("tab_sel")) s = "tab_sel1";
|
||||
else if (n.Contains("tab_bg")) s = "tab_bg";
|
||||
else if (n.Contains("share_btn_bg")) s = "nor_frame_b";
|
||||
else if (n.Contains("icon_more")) s = "icon_more";
|
||||
else if (n.Contains("redDot")) s = "com_redDot";
|
||||
else if (n.Contains("arrow") || n.Contains("jiantou")) s = "arrow";
|
||||
else if (n == "bg_arrow") s = "bg_arrow";
|
||||
else if (Regex.IsMatch(n, @"^(gem|gold|money|energy|bp)_bg")) s = "icon_bg";
|
||||
else if (n.EndsWith("_spr")) s = "icon_bg2";
|
||||
else if (n.Contains("headIcon")) s = "s_frame_p";
|
||||
else if (n.Contains("player_level") || n.Contains("vip_spr")) s = "s_frame_r";
|
||||
else if (n.EndsWith("_btn")) s = "btn";
|
||||
else if (n.Contains("Frame") || n.Contains("frame")) s = "nor_frame_b2";
|
||||
else if (n.StartsWith("eff_") || n.Contains("_eff")) s = "effect_1";
|
||||
else if (n.Contains("lizi") || n.Contains("glow") || n.Contains("star") || n.Contains("sanguang")) s = "tx_mask";
|
||||
else if (Regex.IsMatch(n, @"^bg( \(\d+\))?$")) s = "nor_frame_b";
|
||||
else if (Regex.IsMatch(n, @"^Background( \(\d+\))?$")) s = "nor_frame_b2";
|
||||
else if (n.Contains("ContentRoot")) s = "icon_bg";
|
||||
else if (n.Contains("GodGuardTab") || n.Contains("ActivityCenter")) s = "tab_bg02";
|
||||
else if (n.Contains("propIcon")) s = "icon_bg3";
|
||||
else if (n.Contains("propTip")) s = "ls_txk_1";
|
||||
else if (n.Contains("setup_bg")) s = "icon_bg3";
|
||||
else if (n.Contains("musicOpen")) s = "icon_cardSystem_Bubble01";
|
||||
else if (n.Contains("hlby_") || n.Contains("hong_spr")) s = "icon_cardSystem_Bubble02";
|
||||
else if (n == "zi" || n.Contains("Label") || n.EndsWith("lab")) s = "txt_y_1";
|
||||
else if (Regex.IsMatch(n, @"^Sprite( \(\d+\))?$")) s = "icon_bg2";
|
||||
|
||||
if (s != null && m.ContainsKey(s)) return m[s];
|
||||
return m.ContainsKey("icon_bg2") ? m["icon_bg2"] : null; // 兜底
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6a3beb0f1bea6743becefb7271d8b07
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// 纯视觉 Prefab 生成器:剥掉所有逻辑脚本,只保留表现组件。
|
||||
/// 用法:Project 窗口选中一个/多个 prefab → Tools → 生成纯视觉Prefab
|
||||
/// 输出:同目录 <原名>_Visual.prefab(不覆盖原文件)
|
||||
///
|
||||
/// 保留白名单:Unity 内置表现组件、UGUI、TMP、Spine、Animancer、DOTween、URP Volume
|
||||
/// 删除:其余所有 MonoBehaviour(BY_* 游戏逻辑、LuaBehaviour、FMOD、NGUI 等)
|
||||
/// Missing 脚本(原逻辑脚本移除后的残留)同时清理。
|
||||
/// </summary>
|
||||
public static class StripVisualPrefabTool
|
||||
{
|
||||
// 表现类程序集/命名空间白名单
|
||||
static readonly string[] KeepNamespaces = {
|
||||
"UnityEngine.UI", "TMPro", "Spine", "Spine.Unity", "Animancer",
|
||||
"DG.Tweening", "UnityEngine.Rendering", "UnityEngine.U2D",
|
||||
"UnityEngine", "UnityEngine.Experimental",
|
||||
};
|
||||
// 表现类程序集名(.dll)
|
||||
static readonly string[] KeepAssemblies = {
|
||||
"UnityEngine.UI", "Unity.TextMeshPro", "Unity.Timeline",
|
||||
"Spine", "Spine.Unity", "Animancer", "DOTween", "DOTweenPro",
|
||||
"Unity.RenderPipelines.Core.Runtime", "Unity.RenderPipelines.Universal.Runtime",
|
||||
"Unity.2D.Animation.Runtime", "Unity.Animator2D",
|
||||
"Assembly-CSharp", // 视觉辅助:UIGradient/TextSpacing/Outline8/Z1_EffectFollow 等
|
||||
};
|
||||
|
||||
[MenuItem("Tools/生成纯视觉Prefab(剥离逻辑脚本)")]
|
||||
public static void StripSelected()
|
||||
{
|
||||
// 收集目标:选中的 prefab + 选中文件夹下递归的所有 prefab
|
||||
var prefabPaths = new HashSet<string>();
|
||||
foreach (var obj in Selection.objects)
|
||||
{
|
||||
var path = AssetDatabase.GetAssetPath(obj);
|
||||
if (string.IsNullOrEmpty(path)) continue;
|
||||
if (path.EndsWith(".prefab")) prefabPaths.Add(path);
|
||||
else if (System.IO.Directory.Exists(path))
|
||||
{
|
||||
foreach (var f in System.IO.Directory.GetFiles(path, "*.prefab", System.IO.SearchOption.AllDirectories))
|
||||
prefabPaths.Add(f.Replace('\\', '/'));
|
||||
}
|
||||
}
|
||||
if (prefabPaths.Count == 0) { Debug.LogError("[纯视觉] 未找到 prefab——请选中 prefab 或包含 prefab 的文件夹"); return; }
|
||||
|
||||
Debug.Log($"[纯视觉] 共 {prefabPaths.Count} 个 prefab 待处理...");
|
||||
int done = 0;
|
||||
foreach (var path in prefabPaths) { StripOne(path); done++; }
|
||||
Debug.Log($"[纯视觉] 处理完成 {done} 个 prefab(输出为 *_Visual.prefab)");
|
||||
}
|
||||
|
||||
[MenuItem("Tools/生成纯视觉Prefab(剥离逻辑脚本)", true)]
|
||||
static bool Validate() { return Selection.objects != null && Selection.objects.Length > 0; }
|
||||
|
||||
static void StripOne(string path)
|
||||
{
|
||||
var root = PrefabUtility.LoadPrefabContents(path);
|
||||
int removed = 0;
|
||||
try
|
||||
{
|
||||
// 1. 删除非白名单 MonoBehaviour
|
||||
var mbs = root.GetComponentsInChildren<MonoBehaviour>(true);
|
||||
var toRemove = new List<Component>();
|
||||
foreach (var mb in mbs)
|
||||
{
|
||||
if (mb == null) continue;
|
||||
if (!IsVisual(mb)) toRemove.Add(mb);
|
||||
}
|
||||
foreach (var c in toRemove) { Object.DestroyImmediate(c, true); removed++; }
|
||||
|
||||
// 2. 清理 Missing 脚本组件(serialized 里的 m_Script 已失效的)
|
||||
foreach (var t in root.GetComponentsInChildren<Transform>(true))
|
||||
RemoveMissingScripts(t.gameObject);
|
||||
|
||||
// 3. 另存
|
||||
string dir = System.IO.Path.GetDirectoryName(path).Replace('\\', '/');
|
||||
string name = System.IO.Path.GetFileNameWithoutExtension(path);
|
||||
string newPath = $"{dir}/{name}_Visual.prefab";
|
||||
PrefabUtility.SaveAsPrefabAsset(root, newPath);
|
||||
Debug.Log($"[纯视觉] {name} → {newPath} (剥离 {removed} 个逻辑组件)");
|
||||
}
|
||||
finally { PrefabUtility.UnloadPrefabContents(root); }
|
||||
}
|
||||
|
||||
static bool IsVisual(Component c)
|
||||
{
|
||||
var t = c.GetType();
|
||||
// 程序集白名单(精确优先)
|
||||
var asm = t.Assembly.GetName().Name;
|
||||
foreach (var k in KeepAssemblies)
|
||||
if (asm == k) return true;
|
||||
// 命名空间白名单
|
||||
var ns = t.Namespace ?? "";
|
||||
foreach (var k in KeepNamespaces)
|
||||
if (ns == k || ns.StartsWith(k + ".")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void RemoveMissingScripts(GameObject go)
|
||||
{
|
||||
var so = new SerializedObject(go);
|
||||
var comps = so.FindProperty("m_Component");
|
||||
for (int i = comps.arraySize - 1; i >= 0; i--)
|
||||
{
|
||||
var comp = comps.GetArrayElementAtIndex(i).FindPropertyRelative("component");
|
||||
if (comp != null && comp.objectReferenceValue == null)
|
||||
comps.DeleteArrayElementAtIndex(i);
|
||||
}
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08151b804de85fe4095e31e99127a036
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user