refactor(actor-kit): Actor 体系迁移为 DTO 快照与异步恢复
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using AibisDream.Kit;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.Framework
|
||||
{
|
||||
public class BubbleSlotKit : Singleton<BubbleSlotKit>
|
||||
public class BubbleSlotKit : SingletonBase<BubbleSlotKit>
|
||||
{
|
||||
private readonly Dictionary<BubbleSlotEnum, BubbleSlotGroup> _slotDict = new();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.SaveSystem
|
||||
@@ -6,7 +7,7 @@ namespace AibisDream.SaveSystem
|
||||
/// sections["actor"]:场景中各角色显隐、槽位、动画状态、透明度等(ActorManager)。
|
||||
/// RestoreOrder=40,依赖 scene 与 env 已就绪。
|
||||
/// </summary>
|
||||
public class ActorSnapshotProvider : ISyncSnapshotProvider
|
||||
public class ActorSnapshotProvider : IAsyncSnapshotProvider
|
||||
{
|
||||
public string SaveId => SnapshotProviderIds.Actor;
|
||||
public int RestoreOrder => 40;
|
||||
@@ -22,21 +23,21 @@ namespace AibisDream.SaveSystem
|
||||
return ActorManager.Instance.CaptureSnapshot();
|
||||
}
|
||||
|
||||
public void Restore(object dto, SnapshotRestoreContext context)
|
||||
public IEnumerator RestoreAsync(object dto, SnapshotRestoreContext context)
|
||||
{
|
||||
if (dto is not ActorSnapshotDto actors)
|
||||
{
|
||||
context.Warn("[ActorSnapshotProvider] DTO 类型不匹配,跳过还原。");
|
||||
return;
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (ActorManager.Instance == null)
|
||||
{
|
||||
context.Warn("[ActorSnapshotProvider] ActorManager 未初始化,跳过还原。");
|
||||
return;
|
||||
yield break;
|
||||
}
|
||||
|
||||
ActorManager.Instance.RestoreSnapshot(actors);
|
||||
yield return ActorManager.Instance.RestoreSnapshotAsync(actors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.SaveSystem;
|
||||
using AibisDream.Utility;
|
||||
using DG.Tweening;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace AibisDream
|
||||
@@ -16,47 +15,82 @@ namespace AibisDream
|
||||
/// </summary>
|
||||
public abstract class AbsActor : MonoBehaviour
|
||||
{
|
||||
public ActorData actorData;
|
||||
public string ActorName => actorData.actorName;
|
||||
public string SlotName => actorData.slotName;
|
||||
protected string _actorName;
|
||||
protected string _slotName;
|
||||
protected ActorType _actorType;
|
||||
protected float _alpha;
|
||||
protected SpriteRenderer spriteRenderer;
|
||||
|
||||
public void Init(string actorName, ActorSlot slot)
|
||||
{
|
||||
actorData = new ActorData
|
||||
{
|
||||
actorName = actorName,
|
||||
slotName = slot.slotName,
|
||||
alpha = 0
|
||||
};
|
||||
public string ActorName => _actorName;
|
||||
public string SlotName => _slotName;
|
||||
public ActorType ActorType => _actorType;
|
||||
|
||||
Init();
|
||||
public void Init(string actorName, ActorSlot slot, ActorType actorType)
|
||||
{
|
||||
_actorName = actorName;
|
||||
_slotName = slot.slotName;
|
||||
_actorType = actorType;
|
||||
_alpha = 0;
|
||||
|
||||
InitInternal();
|
||||
SetSlot(slot);
|
||||
}
|
||||
|
||||
public void Init(ActorData data, ActorSlot slot)
|
||||
public void InitFromEntry(ActorEntrySnapshotDto entry, ActorSlot slot)
|
||||
{
|
||||
actorData = data;
|
||||
Init();
|
||||
_actorName = entry.actorName;
|
||||
_slotName = entry.slotName;
|
||||
_alpha = entry.alpha;
|
||||
|
||||
if (!Enum.TryParse(entry.actorType, out _actorType))
|
||||
{
|
||||
_actorType = ActorType.Anima;
|
||||
}
|
||||
|
||||
InitInternal();
|
||||
SetSlot(slot);
|
||||
}
|
||||
|
||||
protected virtual void Init()
|
||||
protected virtual void InitInternal()
|
||||
{
|
||||
gameObject.name = ActorName;
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
spriteRenderer.SetAlpha(0);
|
||||
}
|
||||
|
||||
public abstract ActorEntrySnapshotDto CaptureEntry();
|
||||
|
||||
public abstract IEnumerator ApplyEntryAsync(ActorEntrySnapshotDto entry);
|
||||
|
||||
protected void FillBaseEntry(ActorEntrySnapshotDto entry)
|
||||
{
|
||||
entry.actorName = _actorName;
|
||||
entry.slotName = _slotName;
|
||||
entry.actorType = _actorType.ToString();
|
||||
entry.alpha = _alpha;
|
||||
}
|
||||
|
||||
protected void ApplyAlphaFromEntry(ActorEntrySnapshotDto entry)
|
||||
{
|
||||
if (entry.alpha <= 0.01f)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAlpha(Mathf.RoundToInt(entry.alpha));
|
||||
}
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
actorData.alpha = 1;
|
||||
_alpha = 1;
|
||||
spriteRenderer.SetAlpha(1);
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
actorData.alpha = 0;
|
||||
_alpha = 0;
|
||||
spriteRenderer.SetAlpha(0);
|
||||
}
|
||||
|
||||
@@ -66,24 +100,24 @@ namespace AibisDream
|
||||
spriteRenderer.sortingOrder = slot.sortingOrder;
|
||||
spriteRenderer.sortingLayerID = slot.sortingLayer;
|
||||
|
||||
actorData.slotName = slot.slotName;
|
||||
_slotName = slot.slotName;
|
||||
}
|
||||
|
||||
public IEnumerator FadeInAsync(float duration)
|
||||
{
|
||||
actorData.alpha = 1;
|
||||
_alpha = 1;
|
||||
yield return spriteRenderer.DOFade(1, duration).WaitForCompletion();
|
||||
}
|
||||
|
||||
public IEnumerator FadeOutAsync(float duration)
|
||||
{
|
||||
actorData.alpha = 0;
|
||||
_alpha = 0;
|
||||
yield return spriteRenderer.DOFade(0, duration).WaitForCompletion();
|
||||
}
|
||||
|
||||
public void SetAlpha(int alpha)
|
||||
{
|
||||
actorData.alpha = alpha;
|
||||
_alpha = alpha;
|
||||
spriteRenderer.SetAlpha(alpha);
|
||||
}
|
||||
|
||||
@@ -100,7 +134,6 @@ namespace AibisDream
|
||||
public virtual void SetFaceState(string faceName) {}
|
||||
}
|
||||
|
||||
// 工厂类
|
||||
public class ActorFactory
|
||||
{
|
||||
private readonly Transform _actorRoot;
|
||||
@@ -118,38 +151,40 @@ namespace AibisDream
|
||||
|
||||
public AbsActor CreateActor(string actorName, ActorSlot slot, ActorType actorType)
|
||||
{
|
||||
var actor = actorType switch
|
||||
var actor = InstantiateByType(actorType);
|
||||
if (actor)
|
||||
{
|
||||
actor.Init(actorName, slot, actorType);
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
public AbsActor CreateFromEntry(ActorEntrySnapshotDto entry, ActorSlot slot)
|
||||
{
|
||||
if (!Enum.TryParse<ActorType>(entry.actorType, out var actorType))
|
||||
{
|
||||
actorType = ActorType.Anima;
|
||||
}
|
||||
|
||||
var actor = InstantiateByType(actorType);
|
||||
if (actor)
|
||||
{
|
||||
actor.InitFromEntry(entry, slot);
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
private AbsActor InstantiateByType(ActorType actorType)
|
||||
{
|
||||
return actorType switch
|
||||
{
|
||||
ActorType.Sprite => Object.Instantiate(_spriteActorPrefab, _actorRoot).GetComponent<AbsActor>(),
|
||||
ActorType.Anima => Object.Instantiate(_actorAnimaPrefab, _actorRoot).GetComponent<AbsActor>(),
|
||||
ActorType.AnimaEx => Object.Instantiate(_actorAnimaExPrefab, _actorRoot).GetComponent<AbsActor>(),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (actor)
|
||||
{
|
||||
actor.Init(actorName, slot);
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
public AbsActor CreateActor(ActorData actorData, ActorSlot slot)
|
||||
{
|
||||
var actor = actorData.actorType switch
|
||||
{
|
||||
ActorType.Sprite => Object.Instantiate(_spriteActorPrefab, _actorRoot).GetComponent<AbsActor>(),
|
||||
ActorType.Anima => Object.Instantiate(_actorAnimaPrefab, _actorRoot).GetComponent<AbsActor>(),
|
||||
ActorType.AnimaEx => Object.Instantiate(_actorAnimaExPrefab, _actorRoot).GetComponent<AbsActor>(),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (actor)
|
||||
{
|
||||
actor.Init(actorData, slot);
|
||||
}
|
||||
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,17 +194,4 @@ namespace AibisDream
|
||||
Anima,
|
||||
AnimaEx
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ActorData
|
||||
{
|
||||
[JsonIgnore] public UnityEvent onSave = new();
|
||||
|
||||
public string actorName;
|
||||
public string slotName;
|
||||
public ActorType actorType;
|
||||
public string stateName;
|
||||
public float alpha;
|
||||
public float faceParam;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.SaveSystem;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
@@ -10,34 +11,23 @@ namespace AibisDream
|
||||
private const string HashPrefix = "#hash.";
|
||||
|
||||
private Animator _animator;
|
||||
private Dictionary<int, string> _stateNameDict;
|
||||
private Dictionary<int, string> _hashToStateName;
|
||||
|
||||
protected override void Init()
|
||||
protected override void InitInternal()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
// 设置基本信息
|
||||
base.Init();
|
||||
// 获取Controller
|
||||
actorData.actorType = ActorType.Anima;
|
||||
base.InitInternal();
|
||||
_actorType = ActorType.Anima;
|
||||
|
||||
var controller = ResourceKit.LoadAssetSync<RuntimeAnimatorController>($"Animation/{ActorName}");
|
||||
_animator.runtimeAnimatorController = controller;
|
||||
|
||||
// 保存事件
|
||||
actorData.onSave.AddListener(() =>
|
||||
{
|
||||
actorData.stateName =
|
||||
HashPrefix + _animator.GetCurrentAnimatorStateInfo(0).shortNameHash;
|
||||
});
|
||||
|
||||
// 加载初始状态
|
||||
if (!string.IsNullOrWhiteSpace(actorData.stateName))
|
||||
{
|
||||
ChangeState(actorData.stateName);
|
||||
}
|
||||
_hashToStateName = AnimatorKit.BuildStateHashToNameMap(controller);
|
||||
}
|
||||
|
||||
public override void ChangeState(string animaName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(animaName)) return;
|
||||
|
||||
if (animaName.StartsWith(HashPrefix))
|
||||
{
|
||||
var hash = int.Parse(animaName[HashPrefix.Length..]);
|
||||
@@ -51,12 +41,23 @@ namespace AibisDream
|
||||
|
||||
public override IEnumerator ChangeStateAsync(string animaName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(animaName))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (animaName.StartsWith(HashPrefix))
|
||||
{
|
||||
var hash = int.Parse(animaName[HashPrefix.Length..]);
|
||||
_animator.Play(hash);
|
||||
yield return null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
_animator.Play(animaName);
|
||||
|
||||
// 等待一帧确保动画状态切换完成
|
||||
yield return null;
|
||||
|
||||
// 等待直到动画状态名称匹配
|
||||
while (!_animator.GetCurrentAnimatorStateInfo(0).IsName(animaName))
|
||||
{
|
||||
yield return null;
|
||||
@@ -66,9 +67,48 @@ namespace AibisDream
|
||||
yield return new WaitForSeconds(info.length);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
public override ActorEntrySnapshotDto CaptureEntry()
|
||||
{
|
||||
actorData.onSave.RemoveAllListeners();
|
||||
var entry = new ActorEntrySnapshotDto();
|
||||
FillBaseEntry(entry);
|
||||
|
||||
var info = _animator.GetCurrentAnimatorStateInfo(0);
|
||||
entry.stateNormalizedTime = info.normalizedTime;
|
||||
|
||||
if (_hashToStateName != null
|
||||
&& _hashToStateName.TryGetValue(info.shortNameHash, out var name))
|
||||
{
|
||||
entry.stateName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.stateName = HashPrefix + info.shortNameHash;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
public override IEnumerator ApplyEntryAsync(ActorEntrySnapshotDto entry)
|
||||
{
|
||||
ApplyAlphaFromEntry(entry);
|
||||
|
||||
if (string.IsNullOrEmpty(entry.stateName))
|
||||
{
|
||||
yield return null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (entry.stateName.StartsWith(HashPrefix))
|
||||
{
|
||||
var hash = int.Parse(entry.stateName[HashPrefix.Length..]);
|
||||
_animator.Play(hash, 0, entry.stateNormalizedTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
_animator.Play(entry.stateName, 0, entry.stateNormalizedTime);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,41 @@
|
||||
using AibisDream.Framework;
|
||||
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<string, BlendTreeInfo> _blendTreeDict;
|
||||
|
||||
protected override void Init()
|
||||
protected override void InitInternal()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
// 设置基本信息
|
||||
base.Init();
|
||||
actorData.actorType = ActorType.AnimaEx;
|
||||
base.InitInternal();
|
||||
_actorType = ActorType.AnimaEx;
|
||||
|
||||
var controller = ResourceKit.LoadAssetSync<RuntimeAnimatorController>($"Animation/{ActorName}");
|
||||
_animator.runtimeAnimatorController = controller;
|
||||
|
||||
ParseBlendTreeInfos();
|
||||
|
||||
// 保存事件
|
||||
actorData.onSave.AddListener(() =>
|
||||
{
|
||||
actorData.stateName = _currentStateName;
|
||||
actorData.faceParam = _animator.GetFloat("Face Param");
|
||||
});
|
||||
|
||||
// 加载初始状态
|
||||
if (!string.IsNullOrWhiteSpace(actorData.stateName))
|
||||
{
|
||||
ChangeState(actorData.stateName);
|
||||
}
|
||||
if (actorData.faceParam >= 0)
|
||||
{
|
||||
_animator.SetFloat("Face Param", actorData.faceParam);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseBlendTreeInfos()
|
||||
{
|
||||
_blendTreeDict = new Dictionary<string, BlendTreeInfo>();
|
||||
// 解析混合树
|
||||
var configText = ResourceKit.LoadAssetSync<TextAsset>($"AnimationConfig/{ActorName}");
|
||||
if (configText != null)
|
||||
{
|
||||
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;
|
||||
@@ -55,12 +43,7 @@ namespace AibisDream
|
||||
|
||||
_currentStateName = blendTreeConfig.defaultStateName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换站姿
|
||||
/// </summary>
|
||||
/// <param name="stateName"></param>
|
||||
public override void ChangeState(string stateName)
|
||||
{
|
||||
StartCoroutine(ChangeStateAsync(stateName));
|
||||
@@ -68,36 +51,32 @@ namespace AibisDream
|
||||
|
||||
public override IEnumerator ChangeStateAsync(string stateName)
|
||||
{
|
||||
// 记录当前状态
|
||||
_currentStateName = stateName;
|
||||
|
||||
// 切换站姿
|
||||
_animator.SetTrigger(stateName);
|
||||
// 等待动作切换完成
|
||||
while (!_animator.GetCurrentAnimatorStateInfo(0).IsName(stateName))
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// var info = _animator.GetCurrentAnimatorStateInfo(0);
|
||||
// yield return new WaitForSeconds(info.length);
|
||||
|
||||
_animator.ResetTrigger(stateName);
|
||||
|
||||
Debug.Log($"当前状态{_currentStateName}");
|
||||
}
|
||||
|
||||
public override void SetTalkingState(bool isTalking)
|
||||
{
|
||||
_animator.SetFloat("Is Talking", isTalking ? 1 : 0);
|
||||
_animator.SetFloat(IsTalkingParam, isTalking ? 1 : 0);
|
||||
}
|
||||
|
||||
public override void SetFaceState(string faceName)
|
||||
{
|
||||
// 先读取当前混合树信息
|
||||
if (_blendTreeDict.TryGetValue(_currentStateName, out var blendTreeInfo))
|
||||
_currentFaceName = faceName;
|
||||
|
||||
if (!_blendTreeDict.TryGetValue(_currentStateName, out var blendTreeInfo))
|
||||
{
|
||||
Debug.Log($"当前状态{_currentStateName}的混合树信息存在");
|
||||
Debug.LogWarning($"当前状态{_currentStateName}的混合树信息不存在");
|
||||
return;
|
||||
}
|
||||
|
||||
if (blendTreeInfo.type == "1D")
|
||||
{
|
||||
var clipInfo = blendTreeInfo.GetClipInfo(faceName);
|
||||
@@ -112,14 +91,35 @@ namespace AibisDream
|
||||
if (clipInfo != null)
|
||||
{
|
||||
_animator.SetFloat(blendTreeInfo.blendParameter, clipInfo.position.x);
|
||||
// 不设置Y轴参数
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
public override ActorEntrySnapshotDto CaptureEntry()
|
||||
{
|
||||
Debug.LogWarning($"当前状态{_currentStateName}的混合树信息不存在");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,74 +71,45 @@ namespace AibisDream
|
||||
var dto = new ActorSnapshotDto();
|
||||
foreach (var actor in _actorDict.Values)
|
||||
{
|
||||
var data = actor.actorData;
|
||||
dto.actors.Add(new ActorEntrySnapshotDto
|
||||
{
|
||||
actorName = data.actorName,
|
||||
slotName = data.slotName,
|
||||
actorType = data.actorType.ToString(),
|
||||
stateName = data.stateName,
|
||||
alpha = data.alpha,
|
||||
faceParam = data.faceParam
|
||||
});
|
||||
dto.actors.Add(actor.CaptureEntry());
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
public void RestoreSnapshot(ActorSnapshotDto dto)
|
||||
public IEnumerator RestoreSnapshotAsync(ActorSnapshotDto dto)
|
||||
{
|
||||
if (dto?.actors == null) return;
|
||||
|
||||
DestroyEditorTemp();
|
||||
|
||||
if (dto?.actors == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var entry in dto.actors)
|
||||
{
|
||||
if (!Enum.TryParse<ActorType>(entry.actorType, out var actorType))
|
||||
if (!_slotDict.TryGetValue(entry.slotName, out var slot))
|
||||
{
|
||||
actorType = ActorType.Anima;
|
||||
}
|
||||
|
||||
var actorData = new ActorData
|
||||
{
|
||||
actorName = entry.actorName,
|
||||
slotName = entry.slotName,
|
||||
actorType = actorType,
|
||||
stateName = entry.stateName,
|
||||
alpha = entry.alpha,
|
||||
faceParam = entry.faceParam
|
||||
};
|
||||
|
||||
if (!_slotDict.TryGetValue(actorData.slotName, out var slot))
|
||||
{
|
||||
Debug.LogWarning($"slot {actorData.slotName} 不存在");
|
||||
Debug.LogWarning($"slot {entry.slotName} 不存在");
|
||||
continue;
|
||||
}
|
||||
|
||||
var actor = _actorFactory.CreateActor(actorData, slot);
|
||||
var actor = _actorFactory.CreateFromEntry(entry, slot);
|
||||
if (actor == null) continue;
|
||||
|
||||
_actorDict.Add(actorData.actorName, actor);
|
||||
ApplyActorVisualState(actor, actorData);
|
||||
UpsertActor(entry.actorName, actor);
|
||||
yield return actor.ApplyEntryAsync(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpsertActor(string actorName, AbsActor actor)
|
||||
{
|
||||
if (_actorDict.TryGetValue(actorName, out var existing) && existing != null)
|
||||
{
|
||||
Destroy(existing.gameObject);
|
||||
}
|
||||
|
||||
private static void ApplyActorVisualState(AbsActor actor, ActorData data)
|
||||
{
|
||||
if (data.alpha <= 0.01f)
|
||||
{
|
||||
actor.Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
actor.SetAlpha(Mathf.RoundToInt(data.alpha));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(data.stateName))
|
||||
{
|
||||
actor.ChangeState(data.stateName);
|
||||
}
|
||||
_actorDict[actorName] = actor;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
@@ -165,7 +136,7 @@ namespace AibisDream
|
||||
{
|
||||
var slot = _slotDict[slotName];
|
||||
var actor = _actorFactory.CreateActor(actorName, slot, actorType);
|
||||
_actorDict.Add(actorName, actor);
|
||||
UpsertActor(actorName, actor);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,49 @@
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.Utility;
|
||||
using System.Collections;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.SaveSystem;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class SpriteActor : AbsActor
|
||||
{
|
||||
protected override void Init()
|
||||
private string _stateName = "Idle";
|
||||
|
||||
protected override void InitInternal()
|
||||
{
|
||||
base.Init();
|
||||
actorData.actorType = ActorType.Sprite;
|
||||
// 赋值
|
||||
ChangeState(string.IsNullOrWhiteSpace(actorData.stateName) ? "Idle" : actorData.stateName);
|
||||
base.InitInternal();
|
||||
_actorType = ActorType.Sprite;
|
||||
ChangeState("Idle");
|
||||
}
|
||||
|
||||
public override void ChangeState(string stateName)
|
||||
{
|
||||
spriteRenderer.sprite = ResourceKit.LoadAssetSync<Sprite>($"Sprite/{ActorName}[{stateName}]");
|
||||
actorData.stateName = stateName;
|
||||
_stateName = string.IsNullOrWhiteSpace(stateName) ? "Idle" : stateName;
|
||||
spriteRenderer.sprite = ResourceKit.LoadAssetSync<Sprite>($"Sprite/{ActorName}[{_stateName}]");
|
||||
}
|
||||
|
||||
public override ActorEntrySnapshotDto CaptureEntry()
|
||||
{
|
||||
var entry = new ActorEntrySnapshotDto();
|
||||
FillBaseEntry(entry);
|
||||
entry.stateName = _stateName;
|
||||
return entry;
|
||||
}
|
||||
|
||||
public override IEnumerator ApplyEntryAsync(ActorEntrySnapshotDto entry)
|
||||
{
|
||||
ApplyAlphaFromEntry(entry);
|
||||
|
||||
if (!string.IsNullOrEmpty(entry.stateName))
|
||||
{
|
||||
ChangeState(entry.stateName);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeState("Idle");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user