Files
udxandClaude Opus 5.5 89e0fa246f Add formal enemies, remaining formal partners and synthesized UI SFX
- UI SFX v3: procedurally synthesized one-shots (Tools/synth_ui_sfx.py) wired to
  buttons, rewards, errors and red dots via UiSfx, gated by the SFX setting.
- Five formal enemies (Hornlet, Dashlet, Shellhorn, HornCaptain, GreatHorn):
  Hunyuan 50k -> 2000-tri XPbr, DGXA TokenRig, Idle/Walk/Attack, nested per type
  in PrototypeArena; PrototypeBattle.Enemy gains presentation-only Moving/Strikes.
- Formal partners for all ten pets in the arena and portraits, including new
  VineSprite, ThunderLeopard and TideWhale.
- Pipeline fixes: reject local TokenRig fallback, drop loose mesh islands,
  configurable Unity run_script timeout, companion static stage.
- Also includes concurrent work from another tool in this working tree
  (FlameLion, enemy combat FX, challenge mode, home explorer, server updates).
- Resources registered in Doc/ResDesc_*.md; verified on isolated :18081.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 12:23:55 +08:00

105 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using YooAsset.Editor;
// Pipeline: import UI SFX WAVs under Bundles/Sound/SFX/UI and register Art/Sound collector.
public static class ImportUiSfx
{
const string Folder = "Assets/Bundles/Sound/SFX/UI";
public static string ConfigureAndVerify()
{
if (EditorApplication.isPlaying)
throw new InvalidOperationException("Import UI SFX in Edit Mode.");
string repo = Directory.GetParent(Application.dataPath).Parent.FullName;
string designDir = Path.Combine(repo, "Doc/Design/Sound/UiSfx");
Directory.CreateDirectory(designDir);
string[] guids = AssetDatabase.FindAssets("t:AudioClip", new[] { Folder });
if (guids.Length == 0)
throw new Exception("No AudioClips under " + Folder);
var items = new List<object>();
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var importer = AssetImporter.GetAtPath(path) as AudioImporter;
if (importer == null)
throw new Exception("AudioImporter missing: " + path);
var sample = importer.defaultSampleSettings;
sample.loadType = AudioClipLoadType.DecompressOnLoad;
sample.compressionFormat = AudioCompressionFormat.PCM;
sample.sampleRateSetting = AudioSampleRateSetting.PreserveSampleRate;
sample.preloadAudioData = true;
importer.defaultSampleSettings = sample;
importer.forceToMono = false;
importer.loadInBackground = false;
importer.SaveAndReimport();
var clip = AssetDatabase.LoadAssetAtPath<AudioClip>(path);
if (clip == null || clip.channels < 1 || clip.frequency != 44100)
throw new Exception("Unexpected AudioClip: " + path);
items.Add(new {
asset = path,
guid,
address = Path.GetFileNameWithoutExtension(path),
clip.length,
clip.samples,
clip.channels,
clip.frequency,
loadType = importer.defaultSampleSettings.loadType.ToString(),
compression = importer.defaultSampleSettings.compressionFormat.ToString()
});
}
var package = BundleCollectorSettingData.Setting.Packages.Find(p => p.PackageName == "Art");
if (package == null)
throw new Exception("Existing Art package missing.");
var group = package.Groups.Find(g => g.GroupName == "Sound");
if (group == null)
group = BundleCollectorSettingData.CreateGroup(package, "Sound");
group.ActiveRuleName = nameof(EnableGroup);
group.AssetTags = "art";
BundleCollectorSettingData.ModifyGroup(package, group);
var collector = group.Collectors.Find(c => c.CollectPath == Folder);
if (collector == null)
{
collector = new BundleCollector {
CollectPath = Folder,
CollectorGUID = AssetDatabase.AssetPathToGUID(Folder),
CollectorType = ECollectorType.MainAssetCollector,
AddressRuleName = nameof(AddressByFileName),
PackRuleName = nameof(PackSeparately),
FilterRuleName = nameof(CollectAll),
AssetTags = "art"
};
BundleCollectorSettingData.CreateCollector(group, collector);
}
package.CheckConfigError();
BundleCollectorSettingData.SaveFile();
var report = new {
folder = Folder,
count = items.Count,
items,
package = "Art",
group = "Sound",
packRule = collector.PackRuleName,
runtimePlaybackWired = false,
bundleBuilt = false,
verifiedUtc = DateTime.UtcNow.ToString("o")
};
string json = JsonConvert.SerializeObject(report, Formatting.Indented);
File.WriteAllText(Path.Combine(designDir, "unity_validation.json"), json);
return json;
}
}