280 lines
8.4 KiB
C#
280 lines
8.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AibisDream.Kit;
|
|
using AibisDream.SaveSystem;
|
|
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
|
|
|
|
public override void OnSingletonInit()
|
|
{
|
|
InitRefs();
|
|
DestroyEditorTemp();
|
|
InitDefaultActor();
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
public ActorSnapshotDto CaptureSnapshot()
|
|
{
|
|
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
|
|
});
|
|
}
|
|
|
|
return dto;
|
|
}
|
|
|
|
public IEnumerator RestoreSnapshot(ActorSnapshotDto dto)
|
|
{
|
|
if (dto?.actors == null) yield break;
|
|
|
|
DestroyEditorTemp();
|
|
|
|
foreach (var entry in dto.actors)
|
|
{
|
|
if (!Enum.TryParse<ActorType>(entry.actorType, out var actorType))
|
|
{
|
|
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} 不存在");
|
|
continue;
|
|
}
|
|
|
|
var actor = _actorFactory.CreateActor(actorData, slot);
|
|
if (actor == null) continue;
|
|
|
|
_actorDict.Add(actorData.actorName, actor);
|
|
ApplyActorVisualState(actor, actorData);
|
|
}
|
|
|
|
yield break;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
#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);
|
|
|
|
return actor;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|