Project_WL/AgentScripts/WL760_Seq.cs

285 lines
18 KiB
C#
Raw Permalink Normal View History

WL 리뉴얼 세션 2026-09-06~07 (#760~#800) — 전투·배경·UI·타격감 (조직 PD 로그 #746~#800 · 대화로그 §14~§24) - 전투: Knight@Attack1~3_S 3콤보(4 컨트롤러·클래스별 서브클립) · 타겟팅 4규칙(정면 우선·재타겟·즉시 공격·어그로 금지 · WLTargetingSettings) · 대쉬 후 공격(Stander@Chase_Start · DashDriver · 5 m · 사정거리+0.8 · 근거리 적 우선) · 공격 이동 FrameTable(발 접지 실측 표 · AttackRootMotion) · 충돌 반경/투사체 0.3 배(WLCollisionTuning) · 무적(임시)·펫 금지(WLGameplaySettings) - 검기: NamuFX Slash_B 배리언트 Effect_WLSwingArc 원 피팅 정합 배치 + 캘리브레이션(SlashArcMeasure · SlashTrailSettings) · 찌르기 Effect_WLStab 대기 · 램프 리본(BladeTrail · WL_BladeRibbon.shader · T_WL_BladeRibbonRamp) 보존(drawRibbon 0) - 타격감: Assets/WL/Feel(WLHitFeel · 히트스톱 0.03 · 셰이크 0.10 m · 몹 펀치 1.12 · Actor.Get_Damage 훅 1줄 · 원본 RealCamera 셰이크 결함 대체) - 배경/맵: LMHPOLY Demo_01~10 → WL_Nature01~10(프리팹·씬·NavMesh·스포너·BattleMapConfig) · 물(ToonWaterU) · 포스트 블룸 0.9/0.3 · 잔디(BruteForce·드레싱) 제거 · 마젠타 머티리얼 URP 변환 - UI: 세로 HUD(WL_HUD · 하단 5메뉴 폭 전체 · 채팅/전투 패드 숨김 · WLIngameUiOverride) · Title/TitleInfo 1080×1920 Expand + 배경 높이 fit(WLBackgroundFit) · 로딩 SortOrder_5(WLRawImageAspectSync · 초점표 8장) · Loading1~8 ASTC 6×6 - 도구: AgentScripts/*(LightProbe · WL_MapSwitch · WL760~WL800 프로브/집행/검증 · 상단 사용법 주석) · 에디터 락 프로토콜 파일(staging) - 제외(별도 커밋 예정): Assets/LMHPOLY(703 MB) · Assets/Feel(422 MB) · Assets/Shinabro(300 MB) — 에셋 스토어/구 WL 팩 원본 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 23:24:25 +00:00
// WL760_Seq.cs — PD 지시 #760 2-A 런타임 검증 시퀀스 (PM 도구 · 코루틴 1회 · 서버 쓰기 없음 · Assets 무수정)
// unity command run_script --file AgentScripts/WL760_Seq.cs --entry WL760_Seq.Run --args '[10101, "10101"]'
// unity command run_script --file AgentScripts/WL760_Seq.cs --entry WL760_Seq.Report --args '["10101"]'
// unity command run_script --file AgentScripts/WL760_Seq.cs --entry WL760_Seq.Driver
// unity command run_script --file AgentScripts/WL760_Seq.cs --entry WL760_Seq.Pet --args '[0]' (0 = 펫 비활성, 1 = 복구)
// unity command run_script --file AgentScripts/WL760_Seq.cs --entry WL760_Seq.SetSuppress --args '[0, 1]'
// Run: 클래스 전환(0 = 유지) → 가장 가까운 몹 1.5 m 앞으로 Warp → Play_Attack(0) → 3.8 s 동안 매 프레임
// 클립 전이 · 반경 6 m 몹 전원의 HP 변화(몹 이름 · PC m_Target 표기) · SlashCrescentMask 이미터 상태 · BladeTrail 상태를 기록,
// 각 Attack 클립 시작 +0.22 s 에 게임뷰 캡처. 결과는 Screenshots_WL/combat2/seq_<tag>.txt (Assets 밖).
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.AI;
public static class WL760_Seq
{
const string OutDir = "Screenshots_WL/combat2";
const BindingFlags BF = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
public static object Run(int classId, string tag) { return RunAt(classId, tag, 1.5f, 1); }
/// <summary>dist = 몹 앞 거리(m), noPet = 1 이면 런 동안 펫을 꺼 둔다(데미지 귀속 = PC).</summary>
public static object RunAt(int classId, string tag, float dist, int noPet)
{
if (!Application.isPlaying) return "not playing";
var me = UnityEngine.Object.FindObjectsByType<MyActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None).FirstOrDefault();
if (me == null) return "MyActor none";
var old = GameObject.Find("__wl760seq");
if (old != null) return "sequence already running";
var host = new GameObject("__wl760seq").AddComponent<SeqHost>();
host.StartCoroutine(host.Co(me, classId, tag, dist, noPet != 0));
return "started " + tag + " dist=" + dist + " noPet=" + noPet;
}
public static object Report(string tag)
{
var p = System.IO.Path.Combine(OutDir, "seq_" + tag + ".txt");
return System.IO.File.Exists(p) ? System.IO.File.ReadAllText(p) : "(no report yet) " + p;
}
/// <summary>펫(PetActor) 을 잠시 끄거나 켠다 — 데미지 귀속을 PC 로 한정하기 위한 검증용 토글(메모리만).</summary>
public static object Pet(int active)
{
if (!Application.isPlaying) return "not playing";
var pets = UnityEngine.Object.FindObjectsByType<PetActor>(FindObjectsInactive.Include, FindObjectsSortMode.None);
var sb = new StringBuilder("pets=" + pets.Length);
foreach (var p in pets) { p.gameObject.SetActive(active != 0); sb.Append(" [" + p.name + " active=" + p.gameObject.activeSelf + "]"); }
return sb.ToString();
}
/// <summary>PC 의 WeaponTrailDriver 슬롯 상태(트레일 오브젝트 생존 여부 포함)를 덤프한다 — 판정 ⓓ 원인 추적.</summary>
public static object Driver()
{
if (!Application.isPlaying) return "not playing";
var drivers = UnityEngine.Object.FindObjectsByType<WL.Combat.WeaponTrailDriver>(FindObjectsInactive.Include, FindObjectsSortMode.None);
var sb = new StringBuilder("drivers=" + drivers.Length + "\n");
foreach (var d in drivers)
{
var tp = d.GetType();
sb.AppendLine(" on " + d.gameObject.name + " scene=" + d.gameObject.scene.name);
var fSlots = tp.GetField("_slots", BF);
var slots = fSlots != null ? fSlots.GetValue(d) as IList : null;
sb.AppendLine(" _slotsResolved=" + tp.GetField("_slotsResolved", BF)?.GetValue(d) + " slots=" + (slots != null ? slots.Count : -1)
+ " swingActive=" + tp.GetField("_swingActive", BF)?.GetValue(d) + " classId=" + tp.GetField("_resolvedClassId", BF)?.GetValue(d));
if (slots != null)
foreach (var s in slots)
{
var st = s.GetType();
var trail = st.GetField("trail", BF)?.GetValue(s) as UnityEngine.Object;
var blade = st.GetField("bladeRoot", BF)?.GetValue(s) as Transform;
var alive = st.GetProperty("IsAlive", BF)?.GetValue(s);
sb.AppendLine(" slot socket=" + st.GetField("socketIndex", BF)?.GetValue(s) + " IsAlive=" + alive
+ " blade=" + (blade != null ? blade.name : "(null)")
+ " len=" + st.GetField("bladeLength", BF)?.GetValue(s)
+ " trail=" + (trail == null ? "NULL/DESTROYED" : ((Component)trail).gameObject.name + " active=" + ((Component)trail).gameObject.activeInHierarchy + " scene=" + ((Component)trail).gameObject.scene.name));
}
}
var trails = UnityEngine.Object.FindObjectsByType<WL.Combat.BladeTrail>(FindObjectsInactive.Include, FindObjectsSortMode.None);
sb.AppendLine("BladeTrail objects in memory=" + trails.Length);
return sb.ToString();
}
/// <summary>판정 ⓕ 롤백 확인용 — 런타임 SlashTrailSettings.Instance 의 suppressMode / enableWeaponTrail 을 바꾼다
/// (메모리만 · 디스크 저장 없음 · 검증 후 반드시 원복: mode 2, enable 1).</summary>
public static object SetSuppress(int mode, int enableTrail)
{
if (!Application.isPlaying) return "not playing";
var st = WL.Combat.SlashTrailSettings.Instance;
if (st == null) return "SlashTrailSettings.Instance null";
var tp = st.GetType();
var fMode = tp.GetField("suppressMode", BF); var fEn = tp.GetField("enableWeaponTrail", BF);
if (fMode == null || fEn == null) return "fields not found (suppressMode/enableWeaponTrail)";
string before = "suppressMode=" + fMode.GetValue(st) + " enableWeaponTrail=" + fEn.GetValue(st);
fMode.SetValue(st, Enum.ToObject(fMode.FieldType, mode));
fEn.SetValue(st, enableTrail != 0);
return before + " -> suppressMode=" + fMode.GetValue(st) + " enableWeaponTrail=" + fEn.GetValue(st) + " (asset=" + st.name + ", memory only)";
}
class SeqHost : MonoBehaviour
{
static double HP(Actor a)
{
var mi = typeof(Actor).GetMethod("Get_HP", BF);
if (mi == null || a == null) return double.NaN;
try { return Convert.ToDouble(mi.Invoke(a, null)); } catch { return double.NaN; }
}
static string TargetName(Actor a)
{
Actor t = null;
var f = typeof(Actor).GetField("m_Target", BF);
if (f != null) t = f.GetValue(a) as Actor;
else { var p = typeof(Actor).GetProperty("m_Target", BF); if (p != null) t = p.GetValue(a) as Actor; }
return t != null ? t.name : "(none)";
}
// 펫이 있으면 같은 몹을 때려 데미지 귀속이 오염된다 → 런 동안 매 프레임 꺼 두고 끝나면 켠다(게임이 도중에 다시 켤 수 있음).
// #806(2026-09-07) 수정: 복원(suppress=false) 때 "이 도구가 끈 펫"만 되살린다.
// 이전 버전은 씬의 비활성 PetActor 를 전부 켜서, 게임이 의도적으로 꺼 둔 펫(PCInfo.Make_Pet 의 Off() 잔여 · 펫 메뉴 미리보기 모델)까지
// 되살렸다 → #792 검증 중 "펫 재등장" 의 유력 원인【추정】. 게임 코드 게이트(WLGameplaySettings.spawnPlayerPet)와 무관한 도구 결함.
static readonly System.Collections.Generic.HashSet<int> s_suppressed = new System.Collections.Generic.HashSet<int>();
WL 리뉴얼 세션 2026-09-06~07 (#760~#800) — 전투·배경·UI·타격감 (조직 PD 로그 #746~#800 · 대화로그 §14~§24) - 전투: Knight@Attack1~3_S 3콤보(4 컨트롤러·클래스별 서브클립) · 타겟팅 4규칙(정면 우선·재타겟·즉시 공격·어그로 금지 · WLTargetingSettings) · 대쉬 후 공격(Stander@Chase_Start · DashDriver · 5 m · 사정거리+0.8 · 근거리 적 우선) · 공격 이동 FrameTable(발 접지 실측 표 · AttackRootMotion) · 충돌 반경/투사체 0.3 배(WLCollisionTuning) · 무적(임시)·펫 금지(WLGameplaySettings) - 검기: NamuFX Slash_B 배리언트 Effect_WLSwingArc 원 피팅 정합 배치 + 캘리브레이션(SlashArcMeasure · SlashTrailSettings) · 찌르기 Effect_WLStab 대기 · 램프 리본(BladeTrail · WL_BladeRibbon.shader · T_WL_BladeRibbonRamp) 보존(drawRibbon 0) - 타격감: Assets/WL/Feel(WLHitFeel · 히트스톱 0.03 · 셰이크 0.10 m · 몹 펀치 1.12 · Actor.Get_Damage 훅 1줄 · 원본 RealCamera 셰이크 결함 대체) - 배경/맵: LMHPOLY Demo_01~10 → WL_Nature01~10(프리팹·씬·NavMesh·스포너·BattleMapConfig) · 물(ToonWaterU) · 포스트 블룸 0.9/0.3 · 잔디(BruteForce·드레싱) 제거 · 마젠타 머티리얼 URP 변환 - UI: 세로 HUD(WL_HUD · 하단 5메뉴 폭 전체 · 채팅/전투 패드 숨김 · WLIngameUiOverride) · Title/TitleInfo 1080×1920 Expand + 배경 높이 fit(WLBackgroundFit) · 로딩 SortOrder_5(WLRawImageAspectSync · 초점표 8장) · Loading1~8 ASTC 6×6 - 도구: AgentScripts/*(LightProbe · WL_MapSwitch · WL760~WL800 프로브/집행/검증 · 상단 사용법 주석) · 에디터 락 프로토콜 파일(staging) - 제외(별도 커밋 예정): Assets/LMHPOLY(703 MB) · Assets/Feel(422 MB) · Assets/Shinabro(300 MB) — 에셋 스토어/구 WL 팩 원본 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 23:24:25 +00:00
static void SuppressPets(bool suppress)
{
if (suppress)
{
foreach (var p in UnityEngine.Object.FindObjectsByType<PetActor>(FindObjectsInactive.Include, FindObjectsSortMode.None))
if (p.gameObject.activeSelf) { p.gameObject.SetActive(false); s_suppressed.Add(p.GetInstanceID()); }
}
else
{
foreach (var p in UnityEngine.Object.FindObjectsByType<PetActor>(FindObjectsInactive.Include, FindObjectsSortMode.None))
if (s_suppressed.Contains(p.GetInstanceID()) && !p.gameObject.activeSelf) p.gameObject.SetActive(true);
s_suppressed.Clear();
}
WL 리뉴얼 세션 2026-09-06~07 (#760~#800) — 전투·배경·UI·타격감 (조직 PD 로그 #746~#800 · 대화로그 §14~§24) - 전투: Knight@Attack1~3_S 3콤보(4 컨트롤러·클래스별 서브클립) · 타겟팅 4규칙(정면 우선·재타겟·즉시 공격·어그로 금지 · WLTargetingSettings) · 대쉬 후 공격(Stander@Chase_Start · DashDriver · 5 m · 사정거리+0.8 · 근거리 적 우선) · 공격 이동 FrameTable(발 접지 실측 표 · AttackRootMotion) · 충돌 반경/투사체 0.3 배(WLCollisionTuning) · 무적(임시)·펫 금지(WLGameplaySettings) - 검기: NamuFX Slash_B 배리언트 Effect_WLSwingArc 원 피팅 정합 배치 + 캘리브레이션(SlashArcMeasure · SlashTrailSettings) · 찌르기 Effect_WLStab 대기 · 램프 리본(BladeTrail · WL_BladeRibbon.shader · T_WL_BladeRibbonRamp) 보존(drawRibbon 0) - 타격감: Assets/WL/Feel(WLHitFeel · 히트스톱 0.03 · 셰이크 0.10 m · 몹 펀치 1.12 · Actor.Get_Damage 훅 1줄 · 원본 RealCamera 셰이크 결함 대체) - 배경/맵: LMHPOLY Demo_01~10 → WL_Nature01~10(프리팹·씬·NavMesh·스포너·BattleMapConfig) · 물(ToonWaterU) · 포스트 블룸 0.9/0.3 · 잔디(BruteForce·드레싱) 제거 · 마젠타 머티리얼 URP 변환 - UI: 세로 HUD(WL_HUD · 하단 5메뉴 폭 전체 · 채팅/전투 패드 숨김 · WLIngameUiOverride) · Title/TitleInfo 1080×1920 Expand + 배경 높이 fit(WLBackgroundFit) · 로딩 SortOrder_5(WLRawImageAspectSync · 초점표 8장) · Loading1~8 ASTC 6×6 - 도구: AgentScripts/*(LightProbe · WL_MapSwitch · WL760~WL800 프로브/집행/검증 · 상단 사용법 주석) · 에디터 락 프로토콜 파일(staging) - 제외(별도 커밋 예정): Assets/LMHPOLY(703 MB) · Assets/Feel(422 MB) · Assets/Shinabro(300 MB) — 에셋 스토어/구 WL 팩 원본 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 23:24:25 +00:00
}
public IEnumerator Co(MyActor me, int classId, string tag, float dist, bool noPet)
{
var sb = new StringBuilder();
System.IO.Directory.CreateDirectory(OutDir);
if (noPet) SuppressPets(true);
var pc = me as PCActor;
if (classId > 0 && pc != null)
{
var data = table_classconfig.Ins.Get_Data_orNull(classId);
if (data == null) { sb.AppendLine("class data null " + classId); Done(tag, sb); yield break; }
pc.Change_Class(data, true);
yield return new WaitForSeconds(1.5f);
}
var anim = me.GetComponentInChildren<Animator>();
sb.AppendLine("class=" + classId + " ctrl=" + (anim != null && anim.runtimeAnimatorController != null ? anim.runtimeAnimatorController.name : "(null)") + " scene=" + UnityEngine.SceneManagement.SceneManager.GetActiveScene().name
+ " pets_active=" + UnityEngine.Object.FindObjectsByType<PetActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None).Length);
var mobs = UnityEngine.Object.FindObjectsByType<MobActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None)
.Where(m => HP(m) > 0).OrderBy(m => Vector3.Distance(m.transform.position, me.transform.position)).ToArray();
if (mobs.Length == 0) { sb.AppendLine("no live MobActor"); Done(tag, sb); yield break; }
var t = mobs[0];
var dir = t.transform.position - me.transform.position; dir.y = 0f;
if (Mathf.Abs(dir.magnitude - dist) > 0.1f)
{
var pos = t.transform.position - dir.normalized * dist;
var na = me.GetComponent<NavMeshAgent>();
if (na != null && na.enabled) na.Warp(pos); else me.transform.position = pos;
}
me.transform.LookAt(new Vector3(t.transform.position.x, me.transform.position.y, t.transform.position.z));
var setT = typeof(Actor).GetMethod("Change_Target", BF);
if (setT != null) { try { setT.Invoke(me, new object[] { false, (Actor)t, false }); } catch (Exception e) { sb.AppendLine("Change_Target ex " + e.GetType().Name); } }
yield return null;
// 반경 6 m 몹 전원 추적(펫이 꺼져 있으면 모든 HP 변화 = PC 귀속)
var watch = UnityEngine.Object.FindObjectsByType<MobActor>(FindObjectsInactive.Exclude, FindObjectsSortMode.None)
.Where(m => HP(m) > 0 && Vector3.Distance(m.transform.position, me.transform.position) < 6f).ToList();
var lastHpAll = watch.ToDictionary(m => m, m => HP(m));
double hp0 = HP(t);
sb.AppendLine("target=" + t.name + " hp0=" + hp0.ToString("F0") + " d=" + Vector3.Distance(me.transform.position, t.transform.position).ToString("F2")
+ " pcTarget=" + TargetName(me) + " watched=" + watch.Count);
double aspd = 1.0;
try
{
var fi = typeof(Actor).GetField("m_Stat", BF);
var stat = fi != null ? fi.GetValue(me) : null;
var gm = stat != null ? stat.GetType().GetMethod("Get_Stat", new[] { typeof(eStat) }) : null;
if (gm != null) aspd = Convert.ToDouble(gm.Invoke(stat, new object[] { eStat.FinalAttackSpeed }));
}
catch { }
me.Play_Attack(0, (float)aspd);
sb.AppendLine("Play_Attack(0," + aspd.ToString("F2") + ")");
float t0 = Time.time; string lastClip = ""; int caps = 0;
var seenMasks = new HashSet<int>();
var clipLog = new List<string>(); var hpLog = new List<string>(); var maskLog = new List<string>(); var trailLog = new List<string>();
float nextCapAt = -1f; string capClip = ""; string lastTrail = "";
while (Time.time - t0 < 3.8f)
{
if (noPet) SuppressPets(true);
float el = Time.time - t0;
string clip = "(none)"; float nt = 0f;
if (anim != null && anim.layerCount > 0)
{
var ci = anim.GetCurrentAnimatorClipInfo(0);
if (ci.Length > 0) { clip = ci[0].clip.name; nt = anim.GetCurrentAnimatorStateInfo(0).normalizedTime; }
}
if (clip != lastClip)
{
clipLog.Add(el.ToString("F2") + "s " + clip);
lastClip = clip;
if (clip.IndexOf("Attack", StringComparison.OrdinalIgnoreCase) >= 0) { nextCapAt = el + 0.22f; capClip = clip; }
}
foreach (var m in watch)
{
if (m == null) continue;
double hp = HP(m); double prev = lastHpAll[m];
if (Math.Abs(hp - prev) > 0.01)
{
hpLog.Add(el.ToString("F2") + "s " + m.name + " " + prev.ToString("F0") + " -> " + hp.ToString("F0") + " (" + clip + " n=" + nt.ToString("F2") + " pcTarget=" + TargetName(me) + ")");
lastHpAll[m] = hp;
}
}
foreach (var m in UnityEngine.Object.FindObjectsByType<WL.Combat.SlashCrescentMask>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
{
int id = m.GetInstanceID();
if (seenMasks.Add(id)) maskLog.Add(el.ToString("F2") + "s " + m.gameObject.name + " :: " + m.DumpState());
}
var ts = TrailState();
if (ts != lastTrail && trailLog.Count < 60) { trailLog.Add(el.ToString("F2") + "s " + ts); lastTrail = ts; }
if (nextCapAt > 0f && el >= nextCapAt)
{
nextCapAt = -1f;
yield return new WaitForEndOfFrame();
Texture2D tex = null;
try { tex = ScreenCapture.CaptureScreenshotAsTexture(); } catch (Exception e) { trailLog.Add("cap ex " + e.GetType().Name); }
if (tex != null)
{
string safe = capClip.Replace("&", "n").Replace("/", "_");
var path = System.IO.Path.Combine(OutDir, "seq_" + tag + "_" + (++caps) + "_" + safe + ".png");
System.IO.File.WriteAllBytes(path, tex.EncodeToPNG());
UnityEngine.Object.Destroy(tex);
trailLog.Add(el.ToString("F2") + "s CAP " + path);
}
continue;
}
yield return null;
}
sb.AppendLine("== clips =="); foreach (var s in clipLog) sb.AppendLine(" " + s);
sb.AppendLine("== hp changes (" + hpLog.Count + ") =="); foreach (var s in hpLog) sb.AppendLine(" " + s);
sb.AppendLine("== slash masks (" + maskLog.Count + ") == lastMaskPrefab=" + (WL.Combat.WeaponTrailDriver.LastMaskPrefab ?? "(none)"));
foreach (var s in maskLog) sb.AppendLine(" " + s);
sb.AppendLine("== trail =="); foreach (var s in trailLog) sb.AppendLine(" " + s);
sb.AppendLine("final target hp=" + HP(t).ToString("F0") + " dmgTotal=" + (hp0 - HP(t)).ToString("F0") + " hits(all watched)=" + hpLog.Count
+ " pcPos=" + me.transform.position.ToString("F2") + " dNow=" + (t != null ? Vector3.Distance(me.transform.position, t.transform.position).ToString("F2") : "?"));
if (noPet) SuppressPets(false);
Done(tag, sb);
}
// BladeTrail 오브젝트는 HideFlags.DontSave 라 FindObjectsByType 에 잡히지 않는다(실측) → 드라이버의 공개 GetTrail(i) 로 읽는다.
static string TrailState()
{
var drivers = UnityEngine.Object.FindObjectsByType<WL.Combat.WeaponTrailDriver>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
var sb = new StringBuilder("drv=" + drivers.Length);
foreach (var d in drivers)
{
sb.Append(" swing=" + d.IsSwinging + " slots=" + d.ActiveSlotCount);
for (int i = 0; i < d.ActiveSlotCount; i++)
{
var tr = d.GetTrail(i);
if (tr == null) { sb.Append(" [slot" + i + " trail=NULL]"); continue; }
var mr = tr.GetComponent<MeshRenderer>(); var mf = tr.GetComponent<MeshFilter>();
sb.Append(" [" + tr.gameObject.name + " on=" + (mr != null && mr.enabled) + " samples=" + tr.SampleCount
+ " verts=" + (mf != null && mf.sharedMesh != null ? mf.sharedMesh.vertexCount : 0)
+ " mat=" + (mr != null && mr.sharedMaterial != null ? mr.sharedMaterial.name + "/" + (mr.sharedMaterial.shader != null ? mr.sharedMaterial.shader.name : "?") : "-") + "]");
}
}
return sb.ToString();
}
void Done(string tag, StringBuilder sb)
{
System.IO.File.WriteAllText(System.IO.Path.Combine(OutDir, "seq_" + tag + ".txt"), sb.ToString());
Destroy(gameObject);
}
}
}