Files
aibis-dream/Assets/Scripts/SceneManagement/ActorKit/ActorManager.cs
T
2026-01-06 18:51:59 +08:00

264 lines
7.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Framework;
using AibisDream.Kit;
using UnityEngine;
using Yarn.Unity;
namespace AibisDream
{
public class ActorManager : Singleton<ActorManager>
{
#region 索引
private Transform _actorRoot;
private Dictionary<string, ActorSlot> _slotDict;
private Dictionary<string, AbsActor> _actorDict;
private ActorFactory _actorFactory;
#endregion
private ActorSystemData _actorSystemData;
public override void OnSingletonInit()
{
InitRefs();
DestroyEditorTemp();
InitDefaultActor();
}
public override void OnSingletonDestroy()
{
_actorSystemData.OnLoad -= OnDataLoad;
StorageSystem.Instance.UnregisterData<ActorSystemData>();
}
public void DestroyEditorTemp()
{
foreach (Transform child in _actorRoot)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
DestroyImmediate(child.gameObject);
continue;
}
#endif
Destroy(child.gameObject);
}
_actorDict.Clear();
}
private void InitDefaultActor()
{
foreach (var slot in _slotDict.Values.Where(slot => slot.hasDefaultActor))
{
InitActor(slot.defaultActorName, slot.slotName, slot.defaultActorType);
}
}
private void InitRefs()
{
_actorRoot = transform.Find("ActorRoot");
_slotDict = new Dictionary<string, ActorSlot>();
foreach (var child in transform.Find("Slots").GetComponentsInChildren<ActorSlot>())
{
_slotDict[child.slotName] = child;
}
_actorDict = new Dictionary<string, AbsActor>();
_actorFactory = new ActorFactory(_actorRoot);
// 注册数据
_actorSystemData = new ActorSystemData();
_actorSystemData.OnLoad += OnDataLoad;
// StorageSystem.Instance.RegisterData(_actorSystemData);
}
private void OnDataLoad(ActorSystemData data)
{
Debug.Log("Actor Load");
foreach (var actorData in data.actorDataList)
{
InitActor(actorData);
}
}
#if UNITY_EDITOR
public void InitAllDefault()
{
InitRefs();
DestroyEditorTemp();
foreach (var slot in _slotDict.Values)
{
if (!string.IsNullOrEmpty(slot.defaultActorName))
{
var actor = InitActor(slot.defaultActorName, slot.slotName, slot.defaultActorType);
actor.Show();
}
else
{
Debug.Log($"slot {slot.slotName} 没有默认角色");
}
}
}
#endif
public AbsActor InitActor(string actorName, string slotName, ActorType actorType)
{
var slot = _slotDict[slotName];
// 生成新组件
var actor = _actorFactory.CreateActor(actorName, slot, actorType);
// 保存
_actorDict.Add(actorName, actor);
_actorSystemData.actorDataList.Add(actor.actorData);
return actor;
}
private void InitActor(ActorData actorData)
{
if (_slotDict.TryGetValue(actorData.slotName, out var slot))
{
// 生成新组件
var actor = _actorFactory.CreateActor(actorData, slot);
// 保存
_actorDict.Add(actorData.actorName, actor);
}
else
{
Debug.LogWarning($"slot {actorData.slotName} 不存在");
}
}
public bool TryFindActor(string actorOrSlot, out AbsActor actor)
{
if (_actorDict.TryGetValue(actorOrSlot, out actor))
{
return true;
}
actor = _actorDict.Values.FirstOrDefault(item => item.SlotName == actorOrSlot);
return actor != null;
}
public void ChangeSlot(string actorOrSlot, string targetSlot)
{
if (!_slotDict.TryGetValue(targetSlot, out var targetSlotObj)) return;
if (!TryFindActor(actorOrSlot, out var actor)) return;
actor.SetSlot(targetSlotObj);
}
}
public static class ActorYarnCommand
{
private const string ClinicSlotName = "clinic";
[YarnCommand("init_actor")]
public static void InitActor(string actorName, string slotName = ClinicSlotName, string actorType = "Anima")
{
if (Enum.TryParse<ActorType>(actorType, out var actorTypeEnum))
{
ActorManager.Instance.InitActor(actorName, slotName, actorTypeEnum);
}
else
{
Debug.Log($"Actor类型{actorType}有问题");
}
}
[YarnCommand("change_actor_state")]
public static void PlayAnima(string animaName, string slotOrActorName = ClinicSlotName)
{
if (ActorManager.Instance.TryFindActor(slotOrActorName, out var actor))
{
actor.ChangeState(animaName);
}
}
[YarnCommand("change_actor_state_async")]
public static IEnumerator PlayAnimaAsync(string animaName, string slotOrActorName = ClinicSlotName)
{
if (ActorManager.Instance.TryFindActor(slotOrActorName, out var actor))
{
yield return actor.ChangeStateAsync(animaName);
}
}
[YarnCommand("fade_in_actor")]
public static IEnumerator ActorFadeIn(string actorName = ClinicSlotName, float duration = 1)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
yield return actor.FadeInAsync(duration);
}
}
[YarnCommand("fade_out_actor")]
public static IEnumerator ActorFadeOut(string actorName = ClinicSlotName, float duration = 1)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
yield return actor.FadeOutAsync(duration);
}
}
[YarnCommand("change_actor_slot")]
public static void ChangeSlot(string actorOrSlot, string targetSlot)
{
ActorManager.Instance.ChangeSlot(actorOrSlot, targetSlot);
}
[YarnCommand("show_actor")]
public static void ShowActor(string actorName = ClinicSlotName)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
actor.Show();
}
}
[YarnCommand("hide_actor")]
public static void HideActor(string actorName = ClinicSlotName)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
actor.Hide();
}
}
[YarnCommand("set_actor_face")]
public static void SetFaceState(string faceName, string actorName = ClinicSlotName)
{
if (ActorManager.Instance.TryFindActor(actorName, out var actor))
{
actor.SetFaceState(faceName);
}
}
}
[Serializable]
public class ActorSystemData : IData
{
public List<ActorData> actorDataList = new();
public event Action<ActorSystemData> OnLoad;
public IEnumerator Load()
{
OnLoad?.Invoke(this);
yield break;
}
public void Save()
{
foreach (var actorData in actorDataList)
{
actorData.onSave.Invoke();
}
}
}
}