diff --git a/Assets/Scenes/PeipeiFixScene.unity b/Assets/Scenes/PeipeiFixScene.unity index f9aaf0d03..9d56c98e5 100644 --- a/Assets/Scenes/PeipeiFixScene.unity +++ b/Assets/Scenes/PeipeiFixScene.unity @@ -10337,15 +10337,15 @@ SpriteRenderer: m_SortingLayerID: 1034535805 m_SortingLayer: 9 m_SortingOrder: 100 - m_Sprite: {fileID: 4684698178741017078, guid: 043026da884677749bd2b9a2ecf10c79, type: 3} + m_Sprite: {fileID: -6067141311677397656, guid: fbc29369d0505384cadd5488b4933d4e, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 0} m_FlipX: 0 m_FlipY: 0 m_DrawMode: 0 - m_Size: {x: 5.3348837, y: 9.2} + m_Size: {x: 6.837209, y: 9.232558} m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 - m_WasSpriteAssigned: 0 + m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!114 &1261507409 diff --git a/Assets/Scripts/MiniGame/Peipei/UF/Editor.meta b/Assets/Scripts/MiniGame/Peipei/UF/Editor.meta new file mode 100644 index 000000000..8bce287bb --- /dev/null +++ b/Assets/Scripts/MiniGame/Peipei/UF/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: abb5f01e5e4a41a40b87f06d776d61cb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MiniGame/Peipei/UF/Editor/FixPeipeiUfFaceSprite.cs b/Assets/Scripts/MiniGame/Peipei/UF/Editor/FixPeipeiUfFaceSprite.cs new file mode 100644 index 000000000..616ba6674 --- /dev/null +++ b/Assets/Scripts/MiniGame/Peipei/UF/Editor/FixPeipeiUfFaceSprite.cs @@ -0,0 +1,143 @@ +using System.Linq; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace AibisDream.EditorTools +{ + /// + /// PP2 通用动画 aseprite 重导入后,PeipeiFixScene 里 UF_face(垂手)若仍指向旧子资源 ID 会丢图。 + /// 本工具改绑到「佩佩像素版-默认」aseprite 的 Frame_0。 + /// + public static class FixPeipeiUfFaceSprite + { + private const string ScenePath = "Assets/Scenes/PeipeiFixScene.unity"; + // 垂手姿态用「默认」aseprite,避免依赖被 PP2 重导过的通用动画子资源 ID。 + private const string AsepritePath = + "Assets/RawResources/Actor/\u4f69\u4f69/\u4f69\u4f69\u50cf\u7d20\u7248-\u9ed8\u8ba4.aseprite"; + private const string FaceObjectName = "\u5782\u624b (1)"; // 垂手 (1) + + [MenuItem("AIBIS/Fix/Rebind Peipei UF Face Sprite")] + public static void RebindFromMenu() + { + if (!Rebind(out var message)) + { + EditorUtility.DisplayDialog("Rebind UF Face", message, "OK"); + return; + } + + EditorUtility.DisplayDialog("Rebind UF Face", message, "OK"); + } + + /// Unity batchmode: -executeMethod AibisDream.EditorTools.FixPeipeiUfFaceSprite.RebindBatch + public static void RebindBatch() + { + if (!Rebind(out var message)) + { + Debug.LogError("[FixPeipeiUfFaceSprite] " + message); + EditorApplication.Exit(1); + return; + } + + Debug.Log("[FixPeipeiUfFaceSprite] " + message); + EditorApplication.Exit(0); + } + + private static bool Rebind(out string message) + { + var sprites = AssetDatabase.LoadAllAssetsAtPath(AsepritePath) + .OfType() + .ToArray(); + if (sprites.Length == 0) + { + message = "No sprites found in: " + AsepritePath; + return false; + } + + var sprite = sprites.FirstOrDefault(s => s != null && s.name.Contains("Frame_0")) + ?? sprites.FirstOrDefault(s => s != null); + if (sprite == null) + { + message = "Could not pick a sprite from aseprite."; + return false; + } + + var sceneAlreadyOpen = false; + for (var i = 0; i < EditorSceneManager.sceneCount; i++) + { + if (EditorSceneManager.GetSceneAt(i).path == ScenePath) + { + sceneAlreadyOpen = true; + break; + } + } + + var scene = sceneAlreadyOpen + ? EditorSceneManager.GetSceneByPath(ScenePath) + : EditorSceneManager.OpenScene(ScenePath, OpenSceneMode.Additive); + + GameObject faceGo = null; + foreach (var root in scene.GetRootGameObjects()) + { + foreach (var t in root.GetComponentsInChildren(true)) + { + if (t.gameObject.name == FaceObjectName) + { + faceGo = t.gameObject; + break; + } + } + + if (faceGo != null) + { + break; + } + } + + if (faceGo == null) + { + if (!sceneAlreadyOpen) + { + EditorSceneManager.CloseScene(scene, true); + } + + message = "Face object not found: " + FaceObjectName; + return false; + } + + var renderer = faceGo.GetComponent(); + if (renderer == null) + { + if (!sceneAlreadyOpen) + { + EditorSceneManager.CloseScene(scene, true); + } + + message = "SpriteRenderer missing on " + FaceObjectName; + return false; + } + + Undo.RecordObject(renderer, "Rebind UF Face Sprite"); + renderer.sprite = sprite; + EditorUtility.SetDirty(renderer); + EditorSceneManager.MarkSceneDirty(scene); + EditorSceneManager.SaveScene(scene); + + if (!sceneAlreadyOpen) + { + EditorSceneManager.CloseScene(scene, true); + } + + AssetDatabase.TryGetGUIDAndLocalFileIdentifier( + (Object)sprite, out var guid, out long localId); + + message = string.Format( + "Rebound {0} -> {1} (guid={2} fileID={3})", + FaceObjectName, + sprite.name, + guid, + localId); + return true; + } + } +} diff --git a/Assets/Scripts/MiniGame/Peipei/UF/Editor/FixPeipeiUfFaceSprite.cs.meta b/Assets/Scripts/MiniGame/Peipei/UF/Editor/FixPeipeiUfFaceSprite.cs.meta new file mode 100644 index 000000000..e2e226486 --- /dev/null +++ b/Assets/Scripts/MiniGame/Peipei/UF/Editor/FixPeipeiUfFaceSprite.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f988c46355a846d4daeb2b647a500c82 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MiniGame/Peipei/UF/UFSystem.cs b/Assets/Scripts/MiniGame/Peipei/UF/UFSystem.cs index 8b4082d0a..c601e51dc 100644 --- a/Assets/Scripts/MiniGame/Peipei/UF/UFSystem.cs +++ b/Assets/Scripts/MiniGame/Peipei/UF/UFSystem.cs @@ -135,6 +135,17 @@ public class UFSystem : MonoBehaviour [YarnCommand("UF_faceIn")] public IEnumerator UF_faceIn(float duration = 1.5f) { + if (face == null) + { + Debug.LogWarning("[UFSystem] UF_faceIn: face SpriteRenderer 未绑定。", this); + yield break; + } + + if (face.sprite == null) + { + Debug.LogWarning("[UFSystem] UF_faceIn: face.sprite 为空(可能是 aseprite 重导入后子资源 ID 失效)。", this); + } + face.gameObject.SetActive(true); face.DOFade(1f, duration); yield return new WaitForSeconds(duration); @@ -143,6 +154,11 @@ public class UFSystem : MonoBehaviour [YarnCommand("UF_faceOut")] public IEnumerator UF_faceOut(float duration = 1.5f) { + if (face == null) + { + yield break; + } + face.DOFade(0f, duration); yield return new WaitForSeconds(duration); face.gameObject.SetActive(false); @@ -290,6 +306,8 @@ public class UFSystem : MonoBehaviour public void OpenUFView() { ClearUnifiedUfSpriteWeights(); + // 先于 EyeSystem.OnEnter:UF 段 SwitchState / sprite 极密,禁止 autoBlink 与过渡眨眼 + eyeSystem?.SetNonExplicitBlinkSuppressed(true); if (FullAscillVolume != null && !FullAscillVolume.gameObject.activeInHierarchy) { @@ -335,6 +353,7 @@ public class UFSystem : MonoBehaviour } ClearUnifiedUfSpriteWeights(); + eyeSystem?.SetNonExplicitBlinkSuppressed(false); } public void OpenCover()