动画工具
This commit is contained in:
@@ -433,7 +433,7 @@ namespace AibisDream.SystemEditor
|
||||
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
|
||||
}
|
||||
|
||||
// 创建AnimationClip
|
||||
// 创建或更新 AnimationClip(若已存在则在原资源上就地更新,避免引用丢失)
|
||||
public static AnimationClip CreateAnimationClip(
|
||||
ProcessedAnimationClip animationData,
|
||||
List<FrameData> frames,
|
||||
@@ -441,7 +441,28 @@ namespace AibisDream.SystemEditor
|
||||
string outputPath,
|
||||
bool isImageAnimation = false)
|
||||
{
|
||||
AnimationClip clip = new AnimationClip();
|
||||
// 先计算目标资源路径
|
||||
string fullPath = Path.Combine(outputPath, $"{animationData.name}.anim");
|
||||
string assetPath = fullPath.Replace('\\', '/');
|
||||
if (!assetPath.StartsWith("Assets/"))
|
||||
{
|
||||
// 转换为相对路径
|
||||
string projectPath = Application.dataPath.Replace("Assets", "");
|
||||
if (assetPath.StartsWith(projectPath))
|
||||
{
|
||||
assetPath = assetPath.Substring(projectPath.Length);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果已经存在同名 AnimationClip,则复用该资源,在其上就地更新
|
||||
AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(assetPath);
|
||||
bool isNewClip = false;
|
||||
if (clip == null)
|
||||
{
|
||||
clip = new AnimationClip();
|
||||
isNewClip = true;
|
||||
}
|
||||
|
||||
clip.name = animationData.name;
|
||||
|
||||
// 设置采样率
|
||||
@@ -512,20 +533,18 @@ namespace AibisDream.SystemEditor
|
||||
settings.loopTime = animationData.loop;
|
||||
AnimationUtility.SetAnimationClipSettings(clip, settings);
|
||||
|
||||
// 保存AnimationClip
|
||||
string fullPath = Path.Combine(outputPath, $"{animationData.name}.anim");
|
||||
string assetPath = fullPath.Replace('\\', '/');
|
||||
if (!assetPath.StartsWith("Assets/"))
|
||||
// 保存 / 更新 AnimationClip 资源
|
||||
if (isNewClip)
|
||||
{
|
||||
// 转换为相对路径
|
||||
string projectPath = Application.dataPath.Replace("Assets", "");
|
||||
if (assetPath.StartsWith(projectPath))
|
||||
{
|
||||
assetPath = assetPath.Substring(projectPath.Length);
|
||||
}
|
||||
// 不存在则创建新资源
|
||||
AssetDatabase.CreateAsset(clip, assetPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 已存在则标记为已修改,保持原 GUID 与引用
|
||||
EditorUtility.SetDirty(clip);
|
||||
}
|
||||
|
||||
AssetDatabase.CreateAsset(clip, assetPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
return clip;
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace AibisDream.SystemEditor
|
||||
private List<BlendTreeInfo> _blendTreeInfos;
|
||||
private Vector2 _scrollPosition;
|
||||
private string _resultText = "";
|
||||
private bool _includeNested = false; // 是否包含嵌套混合树,默认不提取
|
||||
private string _defaultStateName = ""; // 控制器默认 State 名称
|
||||
|
||||
[MenuItem("Tools/Animator BlendTree Parser")]
|
||||
public static void ShowWindow()
|
||||
@@ -33,6 +35,17 @@ namespace AibisDream.SystemEditor
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// 解析选项
|
||||
EditorGUILayout.LabelField("解析选项", EditorStyles.boldLabel);
|
||||
_includeNested = EditorGUILayout.Toggle("包含嵌套混合树", _includeNested);
|
||||
EditorGUILayout.HelpBox(
|
||||
_includeNested
|
||||
? "将提取所有层级的混合树(包括嵌套在子混合树中的混合树)"
|
||||
: "仅提取第一层混合树(不包含嵌套在子混合树中的混合树)",
|
||||
MessageType.Info);
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// 解析按钮
|
||||
EditorGUI.BeginDisabledGroup(_selectedController == null);
|
||||
if (GUILayout.Button("解析混合树", GUILayout.Height(30)))
|
||||
@@ -84,13 +97,27 @@ namespace AibisDream.SystemEditor
|
||||
|
||||
try
|
||||
{
|
||||
// 调用解析方法(不输出到控制台,只返回结果)
|
||||
_blendTreeInfos = AnimatorKit.ParseBlendTree(_selectedController);
|
||||
// 解析默认 State 名称(默认使用第 0 层的默认状态)
|
||||
if (_selectedController.layers != null && _selectedController.layers.Length > 0)
|
||||
{
|
||||
var baseLayer = _selectedController.layers[0];
|
||||
_defaultStateName = baseLayer.stateMachine?.defaultState != null
|
||||
? baseLayer.stateMachine.defaultState.name
|
||||
: string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
_defaultStateName = string.Empty;
|
||||
}
|
||||
|
||||
// 调用解析方法,传入 includeNested 选项
|
||||
_blendTreeInfos = AnimatorKit.ParseBlendTree(_selectedController, _includeNested);
|
||||
|
||||
// 格式化结果显示文本
|
||||
FormatResultText();
|
||||
|
||||
Debug.Log($"解析完成: 找到 {_blendTreeInfos.Count} 个混合树");
|
||||
Debug.Log(
|
||||
$"解析完成: 找到 {_blendTreeInfos.Count} 个混合树 (包含嵌套: {_includeNested}),默认 State: {_defaultStateName}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -111,6 +138,7 @@ namespace AibisDream.SystemEditor
|
||||
|
||||
var lines = new List<string>();
|
||||
lines.Add($"=== 控制器 {_selectedController.name} 的混合树信息 ===");
|
||||
lines.Add($"默认 State: {_defaultStateName}");
|
||||
lines.Add($"共找到 {_blendTreeInfos.Count} 个混合树\n");
|
||||
|
||||
for (int i = 0; i < _blendTreeInfos.Count; i++)
|
||||
@@ -211,8 +239,15 @@ namespace AibisDream.SystemEditor
|
||||
Formatting = Formatting.Indented
|
||||
};
|
||||
|
||||
// 组装配置对象(包含默认 State 名称和混合树列表)
|
||||
var config = new BlendTreeConfig
|
||||
{
|
||||
defaultStateName = _defaultStateName,
|
||||
blendTrees = _blendTreeInfos
|
||||
};
|
||||
|
||||
// 序列化为 JSON
|
||||
string jsonContent = JsonConvert.SerializeObject(_blendTreeInfos, settings);
|
||||
string jsonContent = JsonConvert.SerializeObject(config, settings);
|
||||
|
||||
// 写入文件(如果已存在则覆盖)
|
||||
File.WriteAllText(jsonPath, jsonContent, System.Text.Encoding.UTF8);
|
||||
|
||||
@@ -21,17 +21,17 @@ AnimationClip:
|
||||
- serializedVersion: 2
|
||||
curve:
|
||||
- time: 0
|
||||
value: {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.3
|
||||
value: {fileID: 4571778429836060549, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.5
|
||||
value: {fileID: 5925744834341221605, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.55
|
||||
value: {fileID: 3417067792297643795, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.75
|
||||
value: {fileID: 8029721251602746815, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 1.15
|
||||
value: {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
value: {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.4
|
||||
value: {fileID: -6190755443841108145, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.6
|
||||
value: {fileID: -8109228470294260414, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.65000004
|
||||
value: {fileID: 6617401414338900246, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.85
|
||||
value: {fileID: 245859675350752340, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 1.1500001
|
||||
value: {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
attribute: m_Sprite
|
||||
path:
|
||||
classID: 212
|
||||
@@ -54,12 +54,12 @@ AnimationClip:
|
||||
isIntCurve: 0
|
||||
isSerializeReferenceCurve: 0
|
||||
pptrCurveMapping:
|
||||
- {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 4571778429836060549, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 5925744834341221605, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 3417067792297643795, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 8029721251602746815, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -6190755443841108145, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -8109228470294260414, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 6617401414338900246, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 245859675350752340, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
|
||||
@@ -88,8 +88,8 @@
|
||||
"size": { "w": 444, "h": 300 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
{ "name": "俯身动作", "from": 0, "to": 4, "direction": "forward" },
|
||||
{ "name": "起身动作", "from": 5, "to": 9, "direction": "forward" }
|
||||
{ "name": "起身动作", "from": 0, "to": 4, "direction": "forward" },
|
||||
{ "name": "俯身动作", "from": 5, "to": 9, "direction": "forward" }
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "调酒妹", "opacity": 255, "blendMode": "normal" }
|
||||
|
||||
@@ -21,17 +21,17 @@ AnimationClip:
|
||||
- serializedVersion: 2
|
||||
curve:
|
||||
- time: 0
|
||||
value: {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.4
|
||||
value: {fileID: -6190755443841108145, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.6
|
||||
value: {fileID: -8109228470294260414, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.65000004
|
||||
value: {fileID: 6617401414338900246, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.85
|
||||
value: {fileID: 245859675350752340, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 1.1500001
|
||||
value: {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
value: {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.3
|
||||
value: {fileID: 4571778429836060549, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.5
|
||||
value: {fileID: 5925744834341221605, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.55
|
||||
value: {fileID: 3417067792297643795, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 0.75
|
||||
value: {fileID: 8029721251602746815, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- time: 1.15
|
||||
value: {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
attribute: m_Sprite
|
||||
path:
|
||||
classID: 212
|
||||
@@ -54,12 +54,12 @@ AnimationClip:
|
||||
isIntCurve: 0
|
||||
isSerializeReferenceCurve: 0
|
||||
pptrCurveMapping:
|
||||
- {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -6190755443841108145, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -8109228470294260414, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 6617401414338900246, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 245859675350752340, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 7719310255684422536, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 4571778429836060549, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 5925744834341221605, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 3417067792297643795, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: 8029721251602746815, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
- {fileID: -8686660269677207458, guid: 25ade8fcabe12234e947eb2fd1faf797, type: 3}
|
||||
m_AnimationClipSettings:
|
||||
serializedVersion: 2
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
|
||||
@@ -15,6 +15,50 @@ BlendTree:
|
||||
m_UseAutomaticThresholds: 1
|
||||
m_NormalizedBlendValues: 0
|
||||
m_BlendType: 0
|
||||
--- !u!1101 &-8756764537236975013
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions: []
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 4025084367579902075}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1101 &-8393837749183813681
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions: []
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: -1585003012359330868}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!206 &-8129769959329347800
|
||||
BlendTree:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -30,31 +74,6 @@ BlendTree:
|
||||
m_UseAutomaticThresholds: 1
|
||||
m_NormalizedBlendValues: 0
|
||||
m_BlendType: 0
|
||||
--- !u!1101 &-7332683429446511761
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: "\u7AD9\u7ACB"
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 2000764964157969243}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!206 &-7090401831593733310
|
||||
BlendTree:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -70,6 +89,31 @@ BlendTree:
|
||||
m_UseAutomaticThresholds: 1
|
||||
m_NormalizedBlendValues: 0
|
||||
m_BlendType: 0
|
||||
--- !u!1101 &-6924652291709804553
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: "\u4FEF\u8EAB"
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 7455082539712181259}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!206 &-5506951507918232734
|
||||
BlendTree:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -322,6 +366,31 @@ BlendTree:
|
||||
m_UseAutomaticThresholds: 1
|
||||
m_NormalizedBlendValues: 0
|
||||
m_BlendType: 0
|
||||
--- !u!1101 &-1840047729121099618
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: "\u7AD9\u7ACB"
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 2000764964157969243}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1102 &-1585003012359330868
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
@@ -333,7 +402,7 @@ AnimatorState:
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: 7615406609444337958}
|
||||
- {fileID: -6924652291709804553}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
@@ -349,28 +418,6 @@ AnimatorState:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1101 &-1160214663374449175
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions: []
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 4025084367579902075}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!206 &-1010760190615495790
|
||||
BlendTree:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -557,25 +604,25 @@ AnimatorController:
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
m_Controller: {fileID: 0}
|
||||
- m_Name: Is Talking
|
||||
m_Type: 1
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
m_Controller: {fileID: 0}
|
||||
- m_Name: "\u7AD9\u7ACB"
|
||||
m_Type: 9
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
m_Controller: {fileID: 0}
|
||||
- m_Name: "\u4FEF\u8EAB"
|
||||
m_Type: 9
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 9100000}
|
||||
m_Controller: {fileID: 0}
|
||||
m_AnimatorLayers:
|
||||
- serializedVersion: 5
|
||||
m_Name: Base Layer
|
||||
@@ -670,7 +717,7 @@ AnimatorState:
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: 6437050022299151312}
|
||||
- {fileID: -8393837749183813681}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
@@ -693,11 +740,11 @@ AnimatorState:
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: "\u4FEF\u8EAB2D\u6DF7\u5408"
|
||||
m_Name: "\u4FEF\u8EAB"
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: -7332683429446511761}
|
||||
- {fileID: -1840047729121099618}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
@@ -744,28 +791,6 @@ BlendTree:
|
||||
m_UseAutomaticThresholds: 1
|
||||
m_NormalizedBlendValues: 0
|
||||
m_BlendType: 0
|
||||
--- !u!1101 &6437050022299151312
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions: []
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: -1585003012359330868}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!1107 &6533160500192696812
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 6
|
||||
@@ -777,16 +802,16 @@ AnimatorStateMachine:
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -1585003012359330868}
|
||||
m_Position: {x: 400, y: 140, z: 0}
|
||||
m_Position: {x: 390, y: 120, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 4025084367579902075}
|
||||
m_Position: {x: 400, y: 580, z: 0}
|
||||
m_Position: {x: 390, y: 560, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 7455082539712181259}
|
||||
m_Position: {x: 400, y: 330, z: 0}
|
||||
m_Position: {x: 390, y: 310, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: 2000764964157969243}
|
||||
m_Position: {x: 400, y: 380, z: 0}
|
||||
m_Position: {x: 390, y: 360, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -4513199141124557387}
|
||||
m_Position: {x: 800, y: 580, z: 0}
|
||||
@@ -826,7 +851,7 @@ AnimatorState:
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions:
|
||||
- {fileID: -1160214663374449175}
|
||||
- {fileID: -8756764537236975013}
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
@@ -842,31 +867,6 @@ AnimatorState:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1101 &7615406609444337958
|
||||
AnimatorStateTransition:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_Conditions:
|
||||
- m_ConditionMode: 1
|
||||
m_ConditionEvent: "\u4FEF\u8EAB"
|
||||
m_EventTreshold: 0
|
||||
m_DstStateMachine: {fileID: 0}
|
||||
m_DstState: {fileID: 7455082539712181259}
|
||||
m_Solo: 0
|
||||
m_Mute: 0
|
||||
m_IsExit: 0
|
||||
serializedVersion: 3
|
||||
m_TransitionDuration: 0.25
|
||||
m_TransitionOffset: 0
|
||||
m_ExitTime: 0.75
|
||||
m_HasExitTime: 1
|
||||
m_HasFixedDuration: 1
|
||||
m_InterruptionSource: 0
|
||||
m_OrderedInterruption: 1
|
||||
m_CanTransitionToSelf: 1
|
||||
--- !u!206 &7733507570337176853
|
||||
BlendTree:
|
||||
m_ObjectHideFlags: 1
|
||||
|
||||
+283
-435
@@ -1,462 +1,310 @@
|
||||
[
|
||||
{
|
||||
"name": "站立",
|
||||
"type": "1D",
|
||||
"clipCount": 8,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "IDLE",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"defaultStateName": "站立",
|
||||
"blendTrees": [
|
||||
{
|
||||
"name": "站立",
|
||||
"type": "1D",
|
||||
"clipCount": 8,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "IDLE",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "1 伤心聆听",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 伤心聆听",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.142857149
|
||||
},
|
||||
"threshold": 0.142857149
|
||||
},
|
||||
{
|
||||
"clipName": "1 强颜欢笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 强颜欢笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.2857143
|
||||
},
|
||||
"threshold": 0.2857143
|
||||
},
|
||||
{
|
||||
"clipName": "1 眯眼笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 眯眼笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.428571433
|
||||
},
|
||||
"threshold": 0.428571433
|
||||
},
|
||||
{
|
||||
"clipName": "1 聆听",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 聆听",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.5714286
|
||||
},
|
||||
"threshold": 0.5714286
|
||||
},
|
||||
{
|
||||
"clipName": "1 苦笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 苦笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.714285731
|
||||
},
|
||||
"threshold": 0.714285731
|
||||
},
|
||||
{
|
||||
"clipName": "1 闭眼笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 闭眼笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.857142866
|
||||
},
|
||||
"threshold": 0.857142866
|
||||
},
|
||||
{
|
||||
"clipName": "1 难过",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "1 难过",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Face Param",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "俯身",
|
||||
"type": "2D",
|
||||
"clipCount": 0,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 俯身A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Face Param",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "俯身",
|
||||
"type": "2D",
|
||||
"clipCount": 0,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 俯身A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
{
|
||||
"clipName": "2 俯身B",
|
||||
"position": {
|
||||
"x": 0.25,
|
||||
"y": 0.0,
|
||||
"normalized": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"magnitude": 0.25,
|
||||
"sqrMagnitude": 0.0625
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 俯身B",
|
||||
"position": {
|
||||
"x": 0.25,
|
||||
"y": 0.0,
|
||||
"normalized": {
|
||||
{
|
||||
"clipName": "2 微笑",
|
||||
"position": {
|
||||
"x": 0.5,
|
||||
"y": 0.0,
|
||||
"normalized": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"magnitude": 0.5,
|
||||
"sqrMagnitude": 0.25
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼A",
|
||||
"position": {
|
||||
"x": 0.75,
|
||||
"y": 0.0,
|
||||
"normalized": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"magnitude": 0.75,
|
||||
"sqrMagnitude": 0.5625
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼B",
|
||||
"position": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"magnitude": 0.25,
|
||||
"sqrMagnitude": 0.0625
|
||||
"threshold": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 微笑",
|
||||
"position": {
|
||||
"x": 0.5,
|
||||
"y": 0.0,
|
||||
"normalized": {
|
||||
{
|
||||
"clipName": "2 俯身谈话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 俯身谈话",
|
||||
"position": {
|
||||
"x": 0.25,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.242535636,
|
||||
"y": 0.970142543,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.00000012
|
||||
},
|
||||
"magnitude": 1.03077638,
|
||||
"sqrMagnitude": 1.0625
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 微笑对话",
|
||||
"position": {
|
||||
"x": 0.5,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.4472136,
|
||||
"y": 0.8944272,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"magnitude": 1.118034,
|
||||
"sqrMagnitude": 1.25
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼对话",
|
||||
"position": {
|
||||
"x": 0.75,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.6,
|
||||
"y": 0.8,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"magnitude": 1.25,
|
||||
"sqrMagnitude": 1.5625
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼对话",
|
||||
"position": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.707106769,
|
||||
"y": 0.707106769,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 0.99999994
|
||||
},
|
||||
"magnitude": 1.41421354,
|
||||
"sqrMagnitude": 2.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Face Param",
|
||||
"blendParameterY": "Is Talking"
|
||||
},
|
||||
{
|
||||
"name": "俯身嵌套",
|
||||
"type": "1D",
|
||||
"clipCount": 5,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "俯身A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"magnitude": 0.5,
|
||||
"sqrMagnitude": 0.25
|
||||
"threshold": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼A",
|
||||
"position": {
|
||||
"x": 0.75,
|
||||
"y": 0.0,
|
||||
"normalized": {
|
||||
"x": 1.0,
|
||||
{
|
||||
"clipName": "俯身B",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"magnitude": 0.75,
|
||||
"sqrMagnitude": 0.5625
|
||||
"threshold": 0.25
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼B",
|
||||
"position": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 俯身谈话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 俯身谈话",
|
||||
"position": {
|
||||
"x": 0.25,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.242535636,
|
||||
"y": 0.970142543,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.00000012
|
||||
{
|
||||
"clipName": "微笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"magnitude": 1.03077638,
|
||||
"sqrMagnitude": 1.0625
|
||||
"threshold": 0.5
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 微笑对话",
|
||||
"position": {
|
||||
"x": 0.5,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.4472136,
|
||||
"y": 0.8944272,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
{
|
||||
"clipName": "眯眼A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"magnitude": 1.118034,
|
||||
"sqrMagnitude": 1.25
|
||||
"threshold": 0.75
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼对话",
|
||||
"position": {
|
||||
"x": 0.75,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.6,
|
||||
"y": 0.8,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 1.0
|
||||
{
|
||||
"clipName": "眯眼B",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"magnitude": 1.25,
|
||||
"sqrMagnitude": 1.5625
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼对话",
|
||||
"position": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"normalized": {
|
||||
"x": 0.707106769,
|
||||
"y": 0.707106769,
|
||||
"magnitude": 1.0,
|
||||
"sqrMagnitude": 0.99999994
|
||||
},
|
||||
"magnitude": 1.41421354,
|
||||
"sqrMagnitude": 2.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Face Param",
|
||||
"blendParameterY": "Is Talking"
|
||||
},
|
||||
{
|
||||
"name": "俯身A",
|
||||
"type": "1D",
|
||||
"clipCount": 2,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 俯身A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 俯身谈话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Is Talking",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "俯身B",
|
||||
"type": "1D",
|
||||
"clipCount": 2,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 俯身B",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 俯身谈话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Is Talking",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "微笑",
|
||||
"type": "1D",
|
||||
"clipCount": 2,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 微笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 微笑对话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Is Talking",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "眯眼A",
|
||||
"type": "1D",
|
||||
"clipCount": 2,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 眯眼A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼对话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Is Talking",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "眯眼B",
|
||||
"type": "1D",
|
||||
"clipCount": 2,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "2 眯眼B",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "2 眯眼对话",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Is Talking",
|
||||
"blendParameterY": "Blend"
|
||||
},
|
||||
{
|
||||
"name": "俯身嵌套",
|
||||
"type": "1D",
|
||||
"clipCount": 5,
|
||||
"clips": [
|
||||
{
|
||||
"clipName": "俯身A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.0
|
||||
},
|
||||
{
|
||||
"clipName": "俯身B",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.25
|
||||
},
|
||||
{
|
||||
"clipName": "微笑",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.5
|
||||
},
|
||||
{
|
||||
"clipName": "眯眼A",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 0.75
|
||||
},
|
||||
{
|
||||
"clipName": "眯眼B",
|
||||
"position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"magnitude": 0.0,
|
||||
"sqrMagnitude": 0.0
|
||||
},
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Face Param",
|
||||
"blendParameterY": "Is Talking"
|
||||
}
|
||||
]
|
||||
"threshold": 1.0
|
||||
}
|
||||
],
|
||||
"minThreshold": 0.0,
|
||||
"maxThreshold": 1.0,
|
||||
"blendParameter": "Face Param",
|
||||
"blendParameterY": "Is Talking"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -18,8 +18,9 @@ namespace AibisDream.Framework
|
||||
/// 解析 AnimatorController 下的所有混合树
|
||||
/// </summary>
|
||||
/// <param name="controller">AnimatorController 资产</param>
|
||||
/// <param name="includeNested">是否包含嵌套的混合树(子混合树),默认为 true</param>
|
||||
/// <returns>混合树信息列表</returns>
|
||||
public static List<BlendTreeInfo> ParseBlendTree(AnimatorController controller)
|
||||
public static List<BlendTreeInfo> ParseBlendTree(AnimatorController controller, bool includeNested = true)
|
||||
{
|
||||
if (controller == null)
|
||||
{
|
||||
@@ -34,7 +35,7 @@ namespace AibisDream.Framework
|
||||
{
|
||||
if (layer.stateMachine != null)
|
||||
{
|
||||
CollectBlendTreesFromStateMachine(layer.stateMachine, blendTreeInfos);
|
||||
CollectBlendTreesFromStateMachine(layer.stateMachine, blendTreeInfos, includeNested);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace AibisDream.Framework
|
||||
/// <summary>
|
||||
/// 从状态机中收集混合树(递归处理子状态机)
|
||||
/// </summary>
|
||||
private static void CollectBlendTreesFromStateMachine(AnimatorStateMachine stateMachine, List<BlendTreeInfo> blendTreeInfos)
|
||||
private static void CollectBlendTreesFromStateMachine(AnimatorStateMachine stateMachine, List<BlendTreeInfo> blendTreeInfos, bool includeNested)
|
||||
{
|
||||
if (stateMachine == null) return;
|
||||
|
||||
@@ -53,7 +54,7 @@ namespace AibisDream.Framework
|
||||
{
|
||||
if (state.state?.motion is BlendTree blendTree)
|
||||
{
|
||||
CollectBlendTreeInfo(blendTree, blendTreeInfos);
|
||||
CollectBlendTreeInfo(blendTree, blendTreeInfos, includeNested);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,15 +63,18 @@ namespace AibisDream.Framework
|
||||
{
|
||||
if (subStateMachine.stateMachine != null)
|
||||
{
|
||||
CollectBlendTreesFromStateMachine(subStateMachine.stateMachine, blendTreeInfos);
|
||||
CollectBlendTreesFromStateMachine(subStateMachine.stateMachine, blendTreeInfos, includeNested);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集混合树信息(递归处理子混合树)
|
||||
/// 收集混合树信息(可选递归处理子混合树)
|
||||
/// </summary>
|
||||
private static void CollectBlendTreeInfo(BlendTree blendTree, List<BlendTreeInfo> blendTreeInfos)
|
||||
/// <param name="blendTree">混合树</param>
|
||||
/// <param name="blendTreeInfos">混合树信息列表</param>
|
||||
/// <param name="includeNested">是否包含嵌套的混合树(子混合树)</param>
|
||||
private static void CollectBlendTreeInfo(BlendTree blendTree, List<BlendTreeInfo> blendTreeInfos, bool includeNested)
|
||||
{
|
||||
if (blendTree == null) return;
|
||||
|
||||
@@ -103,10 +107,10 @@ namespace AibisDream.Framework
|
||||
};
|
||||
info.clips.Add(clipInfo);
|
||||
|
||||
// 如果子 Motion 也是 BlendTree,递归处理
|
||||
if (child.motion is BlendTree childBlendTree)
|
||||
// 如果子 Motion 也是 BlendTree,根据 includeNested 参数决定是否递归处理
|
||||
if (includeNested && child.motion is BlendTree childBlendTree)
|
||||
{
|
||||
CollectBlendTreeInfo(childBlendTree, blendTreeInfos);
|
||||
CollectBlendTreeInfo(childBlendTree, blendTreeInfos, includeNested);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,10 +136,10 @@ namespace AibisDream.Framework
|
||||
};
|
||||
info.clips.Add(clipInfo);
|
||||
|
||||
// 如果子 Motion 也是 BlendTree,递归处理
|
||||
if (child.motion is BlendTree childBlendTree)
|
||||
// 如果子 Motion 也是 BlendTree,根据 includeNested 参数决定是否递归处理
|
||||
if (includeNested && child.motion is BlendTree childBlendTree)
|
||||
{
|
||||
CollectBlendTreeInfo(childBlendTree, blendTreeInfos);
|
||||
CollectBlendTreeInfo(childBlendTree, blendTreeInfos, includeNested);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,16 +156,16 @@ namespace AibisDream.Framework
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 从 JSON 字符串解析混合树信息列表
|
||||
/// 从 JSON 字符串解析混合树配置(包含默认状态名和混合树列表)
|
||||
/// </summary>
|
||||
/// <param name="jsonString">JSON 字符串</param>
|
||||
/// <returns>混合树信息列表</returns>
|
||||
public static List<BlendTreeInfo> ParseBlendTreeFromJson(string jsonString)
|
||||
/// <returns>混合树配置</returns>
|
||||
public static BlendTreeConfig ParseBlendTreeConfigFromJson(string jsonString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsonString))
|
||||
{
|
||||
Debug.LogWarning("JSON 字符串为空");
|
||||
return new List<BlendTreeInfo>();
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -172,21 +176,31 @@ namespace AibisDream.Framework
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
|
||||
};
|
||||
|
||||
// 反序列化 JSON
|
||||
var blendTreeInfos = JsonConvert.DeserializeObject<List<BlendTreeInfo>>(jsonString, settings);
|
||||
|
||||
if (blendTreeInfos == null)
|
||||
// 优先按新结构(包含默认状态名)反序列化
|
||||
var config = JsonConvert.DeserializeObject<BlendTreeConfig>(jsonString, settings);
|
||||
if (config != null && config.blendTrees != null && config.blendTrees.Count > 0)
|
||||
{
|
||||
Debug.LogWarning("JSON 反序列化结果为 null");
|
||||
return new List<BlendTreeInfo>();
|
||||
return config;
|
||||
}
|
||||
|
||||
return blendTreeInfos;
|
||||
// 兼容旧结构:仅为 List<BlendTreeInfo>
|
||||
var blendTreeInfos = JsonConvert.DeserializeObject<List<BlendTreeInfo>>(jsonString, settings);
|
||||
if (blendTreeInfos != null)
|
||||
{
|
||||
return new BlendTreeConfig
|
||||
{
|
||||
defaultStateName = string.Empty,
|
||||
blendTrees = blendTreeInfos
|
||||
};
|
||||
}
|
||||
|
||||
Debug.LogWarning("JSON 反序列化结果为 null");
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"从 JSON 解析混合树信息失败: {e.Message}");
|
||||
return new List<BlendTreeInfo>();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,11 +210,22 @@ namespace AibisDream.Framework
|
||||
/// <param name="jsonFilePath">JSON 文件路径(可以是 Assets 相对路径或绝对路径)</param>
|
||||
/// <returns>混合树信息列表</returns>
|
||||
public static List<BlendTreeInfo> ParseBlendTreeFromJsonFile(string jsonFilePath)
|
||||
{
|
||||
var config = ParseBlendTreeConfigFromJsonFile(jsonFilePath);
|
||||
return config?.blendTrees ?? new List<BlendTreeInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 JSON 文件路径解析混合树配置(包含默认状态名和混合树列表)
|
||||
/// </summary>
|
||||
/// <param name="jsonFilePath">JSON 文件路径(可以是 Assets 相对路径或绝对路径)</param>
|
||||
/// <returns>混合树配置</returns>
|
||||
public static BlendTreeConfig ParseBlendTreeConfigFromJsonFile(string jsonFilePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsonFilePath))
|
||||
{
|
||||
Debug.LogWarning("JSON 文件路径为空");
|
||||
return new List<BlendTreeInfo>();
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -224,23 +249,40 @@ namespace AibisDream.Framework
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Debug.LogWarning($"JSON 文件不存在: {fullPath}");
|
||||
return new List<BlendTreeInfo>();
|
||||
return null;
|
||||
}
|
||||
|
||||
// 读取文件内容
|
||||
string jsonContent = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);
|
||||
|
||||
// 调用字符串解析方法
|
||||
return ParseBlendTreeFromJson(jsonContent);
|
||||
return ParseBlendTreeConfigFromJson(jsonContent);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"从 JSON 文件解析混合树信息失败: {e.Message}");
|
||||
return new List<BlendTreeInfo>();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 混合树配置(包含默认状态名和混合树列表)
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class BlendTreeConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// AnimatorController 的默认 State 名称
|
||||
/// </summary>
|
||||
public string defaultStateName;
|
||||
|
||||
/// <summary>
|
||||
/// 混合树信息列表
|
||||
/// </summary>
|
||||
public List<BlendTreeInfo> blendTrees;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 混合树信息数据结构
|
||||
/// </summary>
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace AibisDream
|
||||
var controller = ResourceKit.LoadAssetSync<RuntimeAnimatorController>($"Animation/{ActorName}");
|
||||
_animator.runtimeAnimatorController = controller;
|
||||
|
||||
_blendTreeDict = ParseBlendTreeInfos();
|
||||
ParseBlendTreeInfos();
|
||||
|
||||
// 保存事件
|
||||
actorData.onSave.AddListener(() =>
|
||||
@@ -40,20 +40,21 @@ namespace AibisDream
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, BlendTreeInfo> ParseBlendTreeInfos()
|
||||
private void ParseBlendTreeInfos()
|
||||
{
|
||||
var dict = new Dictionary<string, BlendTreeInfo>();
|
||||
_blendTreeDict = new Dictionary<string, BlendTreeInfo>();
|
||||
// 解析混合树
|
||||
var configText = ResourceKit.LoadAssetSync<TextAsset>($"AnimationConfig/{ActorName}");
|
||||
if (configText != null)
|
||||
{
|
||||
var blendTreeInfos = AnimatorKit.ParseBlendTreeFromJson(configText.text);
|
||||
foreach (var info in blendTreeInfos)
|
||||
var blendTreeConfig = AnimatorKit.ParseBlendTreeConfigFromJson(configText.text);
|
||||
foreach (var info in blendTreeConfig.blendTrees)
|
||||
{
|
||||
dict[info.name] = info;
|
||||
_blendTreeDict[info.name] = info;
|
||||
}
|
||||
|
||||
_currentStateName = blendTreeConfig.defaultStateName;
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,30 +62,34 @@ namespace AibisDream
|
||||
/// </summary>
|
||||
/// <param name="stateName"></param>
|
||||
public override void ChangeState(string stateName)
|
||||
{
|
||||
StartCoroutine(ChangeStateAsync(stateName));
|
||||
}
|
||||
|
||||
public override IEnumerator ChangeStateAsync(string stateName)
|
||||
{
|
||||
// 记录当前状态
|
||||
_currentStateName = stateName;
|
||||
|
||||
// 切换站姿
|
||||
_animator.SetTrigger(stateName);
|
||||
}
|
||||
|
||||
public override IEnumerator ChangeStateAsync(string stateName)
|
||||
{
|
||||
ChangeState(stateName);
|
||||
// 等待动作切换完成
|
||||
while (!_animator.GetCurrentAnimatorStateInfo(0).IsName(stateName))
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
var info = _animator.GetCurrentAnimatorStateInfo(0);
|
||||
yield return new WaitForSeconds(info.length);
|
||||
// var info = _animator.GetCurrentAnimatorStateInfo(0);
|
||||
// yield return new WaitForSeconds(info.length);
|
||||
|
||||
_animator.ResetTrigger(stateName);
|
||||
|
||||
Debug.Log($"当前状态{_currentStateName}");
|
||||
}
|
||||
|
||||
public override void SetTalkingState(bool isTalking)
|
||||
{
|
||||
_animator.SetBool("Is Talking", isTalking);
|
||||
_animator.SetFloat("Is Talking", isTalking ? 1 : 0);
|
||||
}
|
||||
|
||||
public override void SetFaceState(string faceName)
|
||||
@@ -92,6 +97,7 @@ namespace AibisDream
|
||||
// 先读取当前混合树信息
|
||||
if (_blendTreeDict.TryGetValue(_currentStateName, out var blendTreeInfo))
|
||||
{
|
||||
Debug.Log($"当前状态{_currentStateName}的混合树信息存在");
|
||||
if (blendTreeInfo.type == "1D")
|
||||
{
|
||||
var clipInfo = blendTreeInfo.GetClipInfo(faceName);
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace AibisDream
|
||||
}
|
||||
|
||||
[YarnCommand("set_actor_face")]
|
||||
public static void SetFaceState(string actorName = ClinicSlotName, string faceName = "默认")
|
||||
public static void SetFaceState(string faceName, string actorName = ClinicSlotName)
|
||||
{
|
||||
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
|
||||
{
|
||||
|
||||
@@ -182,8 +182,8 @@ namespace AibisDream.Test
|
||||
return;
|
||||
}
|
||||
|
||||
_blendTreeInfos = AnimatorKit.ParseBlendTreeFromJson(configText.text);
|
||||
|
||||
_blendTreeInfos = AnimatorKit.ParseBlendTreeConfigFromJson(configText.text).blendTrees;
|
||||
|
||||
if (_blendTreeInfos == null || _blendTreeInfos.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("混合树配置为空或解析失败");
|
||||
@@ -191,7 +191,8 @@ namespace AibisDream.Test
|
||||
}
|
||||
|
||||
// 提取状态名称列表
|
||||
_stateNames = _blendTreeInfos.Select(info => info.name).ToList();
|
||||
// _stateNames = _blendTreeInfos.Select(info => info.name).ToList();
|
||||
_stateNames = new List<string> {"站立", "俯身"};
|
||||
|
||||
// 为每个状态提取表情名称列表
|
||||
_faceNamesByState.Clear();
|
||||
@@ -235,6 +236,9 @@ namespace AibisDream.Test
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新索引
|
||||
_currentStateIndex = (_currentStateIndex + 1) % _stateNames.Count;
|
||||
|
||||
// 循环切换到下一个状态
|
||||
string nextState = _stateNames[_currentStateIndex];
|
||||
Debug.Log($"=== 测试 2: 切换状态到 '{nextState}' ===");
|
||||
@@ -242,9 +246,6 @@ namespace AibisDream.Test
|
||||
_testActor.ChangeState(nextState);
|
||||
|
||||
Debug.Log($"✓ 状态已切换到: {nextState}");
|
||||
|
||||
// 更新索引
|
||||
_currentStateIndex = (_currentStateIndex + 1) % _stateNames.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user