using System.Collections; using System.Collections.Generic; using AibisDream.Framework; using AibisDream.SaveSystem; using UnityEngine; namespace AibisDream { public class ActorAnimaEx : AbsActor { private const string IsTalkingParam = "Is Talking"; private Animator _animator; private string _currentStateName; private string _currentFaceName; private Dictionary _blendTreeDict; protected override void InitInternal() { _animator = GetComponent(); base.InitInternal(); _actorType = ActorType.AnimaEx; var controller = ResourceKit.LoadAssetSync($"Animation/{ActorName}"); _animator.runtimeAnimatorController = controller; ParseBlendTreeInfos(); } private void ParseBlendTreeInfos() { _blendTreeDict = new Dictionary(); var configText = ResourceKit.LoadAssetSync($"AnimationConfig/{ActorName}"); if (configText == null) return; var blendTreeConfig = AnimatorKit.ParseBlendTreeConfigFromJson(configText.text); if (blendTreeConfig?.blendTrees == null) return; foreach (var info in blendTreeConfig.blendTrees) { _blendTreeDict[info.name] = info; } _currentStateName = blendTreeConfig.defaultStateName; } public override void ChangeState(string stateName) { StartCoroutine(ChangeStateAsync(stateName)); } public override IEnumerator ChangeStateAsync(string stateName) { _currentStateName = stateName; _animator.SetTrigger(stateName); while (!_animator.GetCurrentAnimatorStateInfo(0).IsName(stateName)) { yield return null; } _animator.ResetTrigger(stateName); } public override void SetTalkingState(bool isTalking) { _animator.SetFloat(IsTalkingParam, isTalking ? 1 : 0); } public override void SetFaceState(string faceName) { _currentFaceName = faceName; if (!_blendTreeDict.TryGetValue(_currentStateName, out var blendTreeInfo)) { Debug.LogWarning($"当前状态{_currentStateName}的混合树信息不存在"); return; } if (blendTreeInfo.type == "1D") { var clipInfo = blendTreeInfo.GetClipInfo(faceName); if (clipInfo != null) { _animator.SetFloat(blendTreeInfo.blendParameter, clipInfo.threshold); } } else { var clipInfo = blendTreeInfo.GetClipInfo(faceName); if (clipInfo != null) { _animator.SetFloat(blendTreeInfo.blendParameter, clipInfo.position.x); } } } public override ActorEntrySnapshotDto CaptureEntry() { var entry = new ActorEntrySnapshotDto(); FillBaseEntry(entry); entry.stateName = _currentStateName; entry.faceName = _currentFaceName; entry.isTalking = _animator.GetFloat(IsTalkingParam) > 0.5f; return entry; } public override IEnumerator ApplyEntryAsync(ActorEntrySnapshotDto entry) { ApplyAlphaFromEntry(entry); if (!string.IsNullOrEmpty(entry.stateName)) { yield return ChangeStateAsync(entry.stateName); } if (!string.IsNullOrEmpty(entry.faceName)) { SetFaceState(entry.faceName); } SetTalkingState(entry.isTalking); } } }