NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/Show/ShowComponent.cs

1156 lines
35 KiB
C#
Raw Normal View History

using cfg.ShowCfg;
using Cysharp.Threading.Tasks;
using Framework;
using Gameplay;
using PhxhSDK;
using Sirenix.OdinInspector;
2024-03-29 16:57:35 +08:00
using Sirenix.Utilities;
using SRF;
using System;
using System.Collections.Generic;
using Gameplay.Emoji;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using static ShowComponent;
using Constants = Framework.Constants;
using Object = UnityEngine.Object;
using System.Linq;
2024-05-13 14:25:57 +08:00
using Random = UnityEngine.Random;
/// <summary>
/// 演出组件
/// </summary>
2024-04-19 19:32:11 +08:00
public class ShowComponent : MonoBehaviour, IShow
{
/// <summary>
/// 当前状态
/// </summary>
2024-04-19 19:32:11 +08:00
protected enum E_CurState
{
None = 0,
/// <summary>
/// 加载角色
/// </summary>
LoadingCharacters,
/// <summary>
/// 当前
/// </summary>
Present,
}
/// <summary>
/// 被弃用的原因
/// </summary>
public enum E_DisposeReason
{
None,
/// <summary>
/// 演出点重复
/// </summary>
[LabelText("演出点重复")]
ShowPointRepeat,
/// <summary>
/// 组内人数不满
/// </summary>
[LabelText("组内人数不满")]
CharacterCountNotFull,
/// <summary>
/// 固定角色不存在
/// </summary>
[LabelText("固定角色不存在")]
FixedCharacterNotExist,
}
#region 外部序列化字段
/// <summary>
/// 演出场景类型
/// </summary>
[LabelText("演出场景类型")]
[SerializeField]
private E_ShowSceneType showSceneType;
/// <summary>
/// 角色根节点
/// </summary>
[LabelText("角色根节点")]
[SerializeField]
private Transform tsCharacterRoot;
2024-04-26 14:48:47 +08:00
/// <summary>
/// 道具根节点
/// </summary>
[LabelText("道具根节点")]
[SerializeField]
private Transform tsItemRoot;
/// <summary>
2024-04-01 17:51:56 +08:00
/// 收集演出点根节点
/// </summary>
2024-04-01 17:51:56 +08:00
[LabelText("收集演出点的根节点")]
[SerializeField]
2024-04-01 17:51:56 +08:00
private Transform tsCollectRoot;
/// <summary>
/// 角色演出点根节点
/// </summary>
[LabelText("角色演出点根节点")]
[SerializeField]
private Transform tsCharacterShowPointRoot;
/// <summary>
/// 道具演出点根节点
/// </summary>
[LabelText("道具演出点根节点")]
[SerializeField]
private Transform tsItemShowPointRoot;
/// <summary>
/// 最大抽取角色数量
/// </summary>
[LabelText("最大抽取角色数")]
[SerializeField]
private int characterMaxCount = 20;
/// <summary>
/// 是否忽略看板娘
/// </summary>
[LabelText("是否忽略看板娘")]
[SerializeField]
private bool IsIgnoreKanbanban;
/// <summary>
2024-05-29 19:16:38 +08:00
/// 相机Timeline
/// </summary>
2024-05-29 19:16:38 +08:00
[LabelText("相机PlayableDirector")]
[SerializeField]
2024-05-29 19:16:38 +08:00
private PlayableDirector cameraPlayable;
/// <summary>
/// 抽取记录
/// </summary>
[ReadOnly]
[LabelText("抽取记录")]
[SerializeField]
[ShowIf("@listExtractRecord.Count > 0")]
private List<ExtractRecord> listExtractRecord = new();
#endregion
2024-04-26 14:48:47 +08:00
/// <summary>
/// 演出Timeline路径
/// </summary>
private const string SHOW_TIMELINE_PATH = "Assets/Art/Show/";
/// <summary>
/// 道具Timeline上角色轨道名
/// </summary>
private const string ITEM_TIMELINE_TRACK_NAME = "Character";
2024-05-21 18:53:53 +08:00
/// <summary>
/// 角色Activation轨道名
/// </summary>
private const string CHARACTER_ACTIVATION_TRACK_NAME = "characterActivationTrack";
2024-04-26 14:48:47 +08:00
/// <summary>
/// 当前场景所有角色演出点
/// </summary>
private List<Transform> listCharacterShowPoint;
/// <summary>
/// 当前场景所有道具演出点
/// </summary>
private List<Transform> listItemShowPoint;
/// <summary>
/// 当前场景所有演出组字典 key:组id value:演出组数据
/// </summary>
private readonly Dictionary<int, ShowGroupData> dicShowGroup = new();
/// <summary>
/// 最终的演出点数据
/// </summary>
private readonly List<ShowPointResult> listShowPointResult = new();
/// <summary>
/// Timeline资源字典
/// </summary>
2024-03-29 16:57:35 +08:00
private readonly Dictionary<string, TimelineAsset> dicTimeLineAsset = new();
/// <summary>
2024-04-26 14:48:47 +08:00
/// 道具字典部分Timeline挂载到道具上优先使用道具上的Timeline
/// </summary>
2024-04-26 14:48:47 +08:00
private readonly Dictionary<string, Stack<GameObject>> dicItemModel = new();
/// <summary>
/// 角色模型字典
/// </summary>
private readonly Dictionary<int, GameObject> dicCharacterModel = new();
2024-04-26 14:48:47 +08:00
/// <summary>
/// 道具相对于角色的相对位置
/// </summary>
private readonly Dictionary<int, Vector3> dicItemOffset = new();
/// <summary>
/// 缓存的表情
/// </summary>
private readonly List<UnitEmojiManager> listCacheEmoji = new();
/// <summary>
/// 已经加载的资源集合
/// </summary>
private readonly HashSet<string> setAssetToUnload = new();
/// <summary>
/// 当前状态
/// </summary>
2024-04-19 19:32:11 +08:00
protected E_CurState currState = E_CurState.None;
2024-05-29 19:16:38 +08:00
/// <summary>
/// 相机动画回调
/// </summary>
private Action cameraAction;
#region (刷新数据,抽取)过程临时变量
/// <summary>
/// 可以抽取的演出组数据(排序用)
/// </summary>
private readonly List<ShowGroupData> listRemindShowGroup = new();
/// <summary>
/// 可以抽取演出的角色数据(排序用)
/// </summary>
private readonly List<CharacterDataInfo> listRemindCharacter = new();
/// <summary>
/// 随机抽取的演出组链表
/// </summary>
private LinkedList<ShowGroupData> linkShowGroup;
/// <summary>
/// 随机抽取的角色链表
/// </summary>
private LinkedList<CharacterDataInfo> linkCharacter;
/// <summary>
/// 已经抽取的演出点索引集合
/// </summary>
private readonly HashSet<int> setUseShowPointIndex = new();
/// <summary>
/// 已经抽取的角色id
/// </summary>
private readonly HashSet<int> setUseCharactrtId = new();
#endregion
/// <summary>
/// 可以抽取的角色最大数量
/// </summary>
public int CharacterMaxCount
{
get { return Mathf.Min(listRemindCharacter.Count, characterMaxCount, listCharacterShowPoint.Count); }
}
public E_ShowSceneType ShowSceneTyp
{
get { return showSceneType; }
}
#if UNITY_EDITOR
/// <summary>
/// 角色演出点根节点
/// </summary>
2024-04-01 17:51:56 +08:00
public Transform TsShowPointRoot
{
2024-04-01 17:51:56 +08:00
get { return tsCharacterShowPointRoot; }
}
/// <summary>
/// 道具演出点根节点
/// </summary>
public Transform TsItemShowPointRoot
{
get { return tsItemShowPointRoot; }
}
#endif
private void Awake()
{
if (!CommonUtils.IsInGame())
return;
2024-03-18 17:41:46 +08:00
ShowManager.Instance.Add(this);
currState = E_CurState.None;
#region 初始化数据
#region 获取角色演出点
2024-04-01 17:51:56 +08:00
if (tsCharacterShowPointRoot == null)
listCharacterShowPoint = new();
else
{
listCharacterShowPoint = new(tsCharacterShowPointRoot.childCount);
2024-04-01 17:51:56 +08:00
for (int i = 0; i < tsCharacterShowPointRoot.childCount; ++i)
{
listCharacterShowPoint.Add(tsCharacterShowPointRoot.GetChild(i));
}
}
#endregion
#region 获取道具演出点
if (tsItemShowPointRoot == null)
listItemShowPoint = new();
else
{
listItemShowPoint = new(tsItemShowPointRoot.childCount);
for (int i = 0; i < tsItemShowPointRoot.childCount; ++i)
{
listItemShowPoint.Add(tsItemShowPointRoot.GetChild(i));
}
}
#endregion
#region 获取演出组配置
List<DataShowConfig> listShowConfig = TableManager.Instance.Tables.ShowConfig.DataList;
foreach (DataShowConfig showConfig in listShowConfig)
{
if (showSceneType != showConfig.ShowSceneType)
continue;
int groupID = showConfig.GroupID;
if (!dicShowGroup.TryGetValue(groupID, out ShowGroupData group))
{
group = new(groupID);
dicShowGroup.Add(groupID, group);
}
group.Add(showConfig);
}
foreach (ShowGroupData group in dicShowGroup.Values)
{
group.Shuffle();
}
#endregion
#endregion
}
private void OnDestroy()
{
2024-04-26 14:48:47 +08:00
dicTimeLineAsset.Clear();
dicCharacterModel.Clear();
dicItemModel.Clear();
dicItemOffset.Clear();
foreach (string path in setAssetToUnload)
{
AssetManager.Instance.Unload(path);
}
2024-04-26 14:48:47 +08:00
foreach (var unitEmojiManager in listCacheEmoji)
{
unitEmojiManager.Dispose();
}
}
/// <summary>
/// 刷新演出
/// </summary>
2024-04-19 19:32:11 +08:00
public virtual async UniTask RefreshShow(object data = null)
{
currState = E_CurState.LoadingCharacters;
RefreshShowData();
ExtractShowCharacter();
await ExecuteShowResult();
currState = E_CurState.Present;
}
/// <summary>
/// 刷新演出数据
/// </summary>
private void RefreshShowData()
{
listRemindShowGroup.Clear();
listRemindCharacter.Clear();
listRemindShowGroup.AddRange(dicShowGroup.Values);
#region 获取看板娘id
int kanbanbanId = 0;
if (IsIgnoreKanbanban)
{
MainPanelSceneStoreData storeData = StorageMgr.Instance.GetStorage<MainPanelSceneStoreData>("MainPanelSceneStoreData");
if (storeData == null)
DebugUtil.LogError("没有看板娘数据");
else
kanbanbanId = storeData.PosterID;
}
#endregion
foreach (CharacterDataInfo characterDataInfo in CharacterDataInfoManager.Instance.DataList)
{
2024-04-01 17:51:56 +08:00
if (IsIgnoreKanbanban && characterDataInfo.Cfg.RoleID == kanbanbanId)
continue; // TODO 看板娘不加进可以演出的抽取列表
listRemindCharacter.Add(characterDataInfo);
}
CommonUtils.Shuffle(listRemindShowGroup);
CommonUtils.Shuffle(listRemindCharacter);
linkShowGroup = new(listRemindShowGroup);
linkCharacter = new(listRemindCharacter);
#region 隐藏之前的角色模型
foreach (GameObject go in dicCharacterModel.Values)
{
go.SetActive(false);
}
#endregion
}
/// <summary>
/// 抽取演出角色
/// </summary>
private void ExtractShowCharacter()
{
listExtractRecord.Clear();
listShowPointResult.Clear();
List<ShowPointResult> listTempResult = new(); // 临时存放抽取的结果
while (linkShowGroup.First != null)
{
ShowGroupData groupData = linkShowGroup.First.Value;
linkShowGroup.RemoveFirst();
// 如果组里的演出点和当前已经使用的演出点重复,则踢出该组
if (IsShowPointExist(groupData))
{
listExtractRecord.Add(new ExtractRecord(groupData.GroupID, E_DisposeReason.ShowPointRepeat));
continue;
}
// 如果是固定角色的组的角色已经被使用,则踢出该组
if (!IsCanUseFixCharacter(groupData))
{
listExtractRecord.Add(new ExtractRecord(groupData.GroupID, E_DisposeReason.FixedCharacterNotExist));
continue;
}
listTempResult.Clear();
ExtractRecord extractRecord = new(groupData.GroupID, E_DisposeReason.None);
foreach (DataShowConfig dataShowConfig in groupData.ListConfig)
{
// 如果当前没有剩余的演员,则直接跳出抽取
if (linkCharacter.First == null)
break;
#region 抽取timeline
2024-03-29 16:57:35 +08:00
string timelineName = CommonUtils.GetRandomItem(dataShowConfig.TimelineNames);
ExtractRecord.SinglePointRecord singlePointRecord = new()
{
2024-03-29 16:57:35 +08:00
timelineName = timelineName
};
extractRecord.Add(singlePointRecord);
2024-03-29 16:57:35 +08:00
if (timelineName == "0" || timelineName.IsNullOrWhitespace()) // 说明不站人
continue;
#endregion
#region 角色抽取
CharacterDataInfo characterDataInfo = null;
if (ValueValidator.IsIdValid(dataShowConfig.CharacterID)) // 抽取指定演员
{
foreach (CharacterDataInfo character in linkCharacter)
{
if ((int)character.ID == dataShowConfig.CharacterID)
{
characterDataInfo = character;
break;
}
}
if (characterDataInfo == null)
continue;
else
linkCharacter.Remove(characterDataInfo);
}
else
{
characterDataInfo = linkCharacter.First.Value;
linkCharacter.RemoveFirst();
}
#endregion
ShowPointResult result;
// 道具抽取
if (dataShowConfig.ItemNames.Count() > 0)
{
string itemName = CommonUtils.GetRandomItem(dataShowConfig.ItemNames);
result = new(groupData.GroupID,
dataShowConfig.PointID,
timelineName,
characterDataInfo,
dataShowConfig.ItemPointId,
itemName);
}
else
{
result = new(groupData.GroupID,
dataShowConfig.PointID,
timelineName,
characterDataInfo,
dataShowConfig.ItemPointId,
string.Empty);
}
singlePointRecord.showPoint = dataShowConfig.PointID;
singlePointRecord.characterID = characterDataInfo.ID;
listTempResult.Add(result);
}
if (groupData.IsMustHasCharacter && listTempResult.Count < groupData.ListConfig.Count)
{
// 如果该组必须满员但没满员
// 取出来的CharacterDataInfo归还
foreach (ShowPointResult result in listTempResult)
{
listRemindCharacter.Add(result.CharacterData);
}
listExtractRecord.Add(new ExtractRecord(groupData.GroupID, E_DisposeReason.CharacterCountNotFull));
}
else // 添加到最后的result列表中
{
foreach (ShowPointResult result in listTempResult)
{
listShowPointResult.Add(result);
setUseCharactrtId.Add((int)result.CharacterData.ID);
setUseShowPointIndex.Add(result.ShowPointIndex);
}
}
}
setUseShowPointIndex.Clear();
setUseCharactrtId.Clear();
}
/// <summary>
/// 执行演出结果
/// </summary>
2024-04-19 19:32:11 +08:00
protected virtual async UniTask ExecuteShowResult()
{
if (listShowPointResult.Count == 0)
return;
2024-04-26 14:48:47 +08:00
Dictionary<string, Stack<GameObject>> dicTempGoItem = new(); // 临时道具字典
foreach (ShowPointResult result in listShowPointResult)
{
#region 获取角色演出点
int showPointIndex = result.ShowPointIndex;
if (showPointIndex < 0 || showPointIndex >= listCharacterShowPoint.Count || listCharacterShowPoint[showPointIndex] == null)
{
DebugUtil.LogError($"找不到演出点!演出点索引:{showPointIndex}");
continue;
}
Transform tsShowPoint = listCharacterShowPoint[showPointIndex].transform;
#endregion
int itemShowPointIndex = result.ItemPointIndex;
if (itemShowPointIndex >= 0 && itemShowPointIndex < listItemShowPoint.Count && listItemShowPoint[itemShowPointIndex] != null)
{
2024-04-28 17:55:51 +08:00
Transform tsItemShowPoint = listItemShowPoint[itemShowPointIndex].transform; // 获取道具演出点,有道具演出
2024-04-28 19:01:20 +08:00
GameObject goFixItemModel = await GetItemModel(result.ItemName); // 加载固定道具
2024-04-28 17:55:51 +08:00
if (goFixItemModel != null)
goFixItemModel.transform.SetPositionAndRotation(tsItemShowPoint.position, tsItemShowPoint.rotation);
}
2024-04-26 14:48:47 +08:00
GameObject goCharacterModel = await GetCharacterModel(result.CharacterData);
if (goCharacterModel == null)
continue;
2024-04-26 14:48:47 +08:00
goCharacterModel.SetActive(true);
goCharacterModel.transform.SetPositionAndRotation(tsShowPoint.position, tsShowPoint.rotation);
2024-04-26 14:48:47 +08:00
GameObject goItemModel = await GetItemModel(result.TimelineName);// 优先使用道具上的Timeline
if (goItemModel == null) // 没有道具,直接加载Timeline
{
TimelineAsset timelineAsset = await GetTimeLineAsset(result.TimelineName);
if (timelineAsset == null)
continue;
2024-04-26 14:48:47 +08:00
PlayableDirector playableDirector = goCharacterModel.GetComponentOrAdd<PlayableDirector>();
playableDirector.playableAsset = timelineAsset;
playableDirector.extrapolationMode = DirectorWrapMode.Loop;
foreach (PlayableBinding playableBinding in timelineAsset.outputs)
{
playableDirector.SetGenericBinding(playableBinding.sourceObject, goCharacterModel.GetComponentInChildren<Animator>());
}
2024-05-21 18:53:53 +08:00
foreach (TrackAsset trackAsset in timelineAsset.GetOutputTracks())
{
if (trackAsset.name.Equals(CHARACTER_ACTIVATION_TRACK_NAME))
playableDirector.SetGenericBinding(trackAsset, goCharacterModel.transform.GetChild(0)?.gameObject);
}
2024-04-26 14:48:47 +08:00
playableDirector.enabled = true;
2024-05-13 14:25:57 +08:00
playableDirector.time = Random.Range(0f, (float)playableDirector.duration);
2024-04-26 14:48:47 +08:00
playableDirector.Play();
}
else // 有道具,不加载Timeline
{
2024-04-26 14:48:47 +08:00
#region 临时记录使用过的道具GameObject,方便后续归还给池子
if (!dicTempGoItem.TryGetValue(result.TimelineName, out Stack<GameObject> goStack))
{
goStack = new();
dicTempGoItem[result.TimelineName] = goStack;
}
goStack.Push(goItemModel);
#endregion
PlayableDirector playableDirector = goItemModel.GetComponentOrAdd<PlayableDirector>();
TimelineAsset timelineAsset = playableDirector.playableAsset as TimelineAsset;
if (timelineAsset == null)
{
DebugUtil.LogError($"{goItemModel.name} 没有TimelineAsset");
continue;
}
if (dicItemOffset.TryGetValue(goItemModel.GetInstanceID(), out Vector3 offset))
goItemModel.transform.SetPositionAndRotation(goCharacterModel.transform.position + offset, Quaternion.identity);
else
goItemModel.transform.SetPositionAndRotation(goCharacterModel.transform.position, Quaternion.identity);
goItemModel.transform.RotateAround(goCharacterModel.transform.position, Vector3.up, goCharacterModel.transform.localEulerAngles.y);
PlayableDirector cPlayableDirector = goCharacterModel.GetComponentOrAdd<PlayableDirector>();
cPlayableDirector.enabled = false;
foreach (TrackAsset trackAsset in timelineAsset.GetOutputTracks())
{
if (trackAsset.name.Equals(ITEM_TIMELINE_TRACK_NAME))
playableDirector.SetGenericBinding(trackAsset, goCharacterModel.GetComponentInChildren<Animator>());
2024-05-21 18:53:53 +08:00
if (trackAsset.name.Equals(CHARACTER_ACTIVATION_TRACK_NAME))
2024-09-05 18:43:40 +08:00
{
Transform tsGo = goCharacterModel.transform.GetChild(0);
if (null == tsGo)
DebugUtil.LogError("赋值空的角色到Timeline轨道上");
else
playableDirector.SetGenericBinding(trackAsset, tsGo.gameObject);
}
2024-04-26 14:48:47 +08:00
}
2024-05-13 14:25:57 +08:00
playableDirector.time = Random.Range(0f, (float)playableDirector.duration);
2024-04-26 14:48:47 +08:00
playableDirector.Play();
}
2024-04-26 14:48:47 +08:00
}
#region 放回道具
2024-04-26 14:48:47 +08:00
foreach (var kv in dicTempGoItem)
{
if (!dicItemModel.TryGetValue(kv.Key, out Stack<GameObject> stack))
continue;
2024-04-26 14:48:47 +08:00
stack ??= new();
while (kv.Value.Count > 0)
{
2024-04-26 14:48:47 +08:00
stack.Push(kv.Value.Pop());
}
}
2024-04-26 14:48:47 +08:00
dicTempGoItem.Clear();
#endregion
}
2024-04-26 14:48:47 +08:00
/// <summary>
/// 初始化emoji
/// </summary>
/// <param name="cObj"></param>
/// <param name="dataInfo"></param>
/// <returns></returns>
private UnitEmojiManager InitEmoji(GameObject cObj, CharacterDataInfo dataInfo)
{
var config = dataInfo.Cfg;
var skinID = dataInfo.SkinID > 0 ? (int)dataInfo.SkinID : Constants.DEFULT_SKINID;
var skinData = TableManager.Instance.Tables.SkinCfg.Get(skinID, dataInfo.Cfg.RoleID);
if (skinData == null)
{
DebugUtil.LogError($"找不到皮肤数据, skinID:{skinID}, roleID:{dataInfo.Cfg.RoleID}");
return null;
}
var eyebowsType = string.IsNullOrEmpty(config.EmojiEyeBowsType) ? "1" : config.EmojiEyeBowsType;
var eyesColor = string.IsNullOrEmpty(config.EmojiEyesColor) ? "#ff0000" : config.EmojiEyesColor;
var eyebowsColor = string.IsNullOrEmpty(config.EmojiEyeBowsColor) ? "#ff0000" : config.EmojiEyeBowsColor;
2024-06-18 16:52:21 +08:00
var unitEmojiManager = new UnitEmojiManager(cObj, eyesColor, eyebowsType, eyebowsColor);
unitEmojiManager.SwitchEmoji(config.DefaultDisplayEmojiId);
return unitEmojiManager;
}
/// <summary>
/// 播放相机动画
/// </summary>
/// <exception cref="NotImplementedException"></exception>
2024-06-19 13:59:31 +08:00
public void PlayeCameraAnim(Action callbackAction, params string[] args)
{
2024-05-29 19:16:38 +08:00
if (null == cameraPlayable)
{
2024-05-29 19:16:38 +08:00
DebugUtil.LogError("相机Playable未赋值");
return;
}
2024-05-29 19:16:38 +08:00
cameraAction = callbackAction;
2024-05-29 19:16:38 +08:00
cameraPlayable.Play();
}
2024-05-29 19:16:38 +08:00
/// <summary>
/// 相机动画播放完成
/// </summary>
public void OnPlayCameraAnimStop()
{
cameraAction?.Invoke();
cameraAction = null;
}
/// <summary>
/// 异步加载资源
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="path"></param>
/// <returns></returns>
private async UniTask<T> LoadAssetAsync<T>(string path) where T : Object
{
T res = await AssetManager.Instance.LoadAssetAsync<T>(path);
if (res != null)
setAssetToUnload.Add(path);
return res;
}
/// <summary>
/// 获取角色模型
/// </summary>
/// <param name="characterDataInfo"></param>
/// <returns></returns>
2024-04-26 14:48:47 +08:00
private async UniTask<GameObject> GetCharacterModel(CharacterDataInfo characterDataInfo)
{
if (!dicCharacterModel.TryGetValue(characterDataInfo.Cfg.RoleID, out GameObject goModel))
{
string prefabPath = characterDataInfo.PrefabPath;
goModel = await LoadAssetAsync<GameObject>(prefabPath);
if (goModel == null)
{
DebugUtil.LogError($"找不到模型, path:{prefabPath}");
return null;
}
goModel = Instantiate(goModel, tsCharacterRoot);
2024-04-26 14:48:47 +08:00
goModel.SetLayerEx(Constants.Layer.UIVIEW);
HideCharacterWeapon(goModel);
UnitEmojiManager unitEmojiManager = InitEmoji(goModel, characterDataInfo);
if (unitEmojiManager != null)
{
// 缓存起来
2024-04-26 14:48:47 +08:00
listCacheEmoji.Add(unitEmojiManager);
}
dicCharacterModel.Add(characterDataInfo.Cfg.RoleID, goModel);
}
return goModel;
}
2024-04-26 14:48:47 +08:00
/// <summary>
/// 获取道具模型
/// </summary>
/// <param name="characterDataInfo"></param>
/// <returns></returns>
private async UniTask<GameObject> GetItemModel(string name)
{
if (!dicItemModel.TryGetValue(name, out Stack<GameObject> stackItem) || stackItem.Count <=0)
{
2024-04-28 19:01:20 +08:00
string itemPath = $"{SHOW_TIMELINE_PATH}{showSceneType}/{name}.prefab";
2024-04-26 14:48:47 +08:00
if (!AssetManager.Instance.CanLocateAsset<GameObject>(itemPath))
return null;
stackItem ??= new();
GameObject goItem = await LoadAssetAsync<GameObject>(itemPath);
if (goItem == null)
return null;
goItem = Instantiate(goItem, tsItemRoot);
goItem.SetLayerEx(Constants.Layer.UIVIEW);
dicItemModel[name] = stackItem;
dicItemOffset[goItem.GetInstanceID()] = goItem.transform.position;
return goItem;
}
return stackItem.Pop();
}
2024-04-03 19:11:09 +08:00
/// <summary>
/// 隐藏角色武器
/// </summary>
private void HideCharacterWeapon(GameObject goCharacter)
{
if (goCharacter.transform.childCount < 1)
{
2024-08-29 15:24:20 +08:00
DebugUtil.LogError("角色节点错误:" + goCharacter.name);
2024-04-03 19:11:09 +08:00
return;
}
// TODO 临时隐藏武器方式
Transform tsRoot = goCharacter.transform.GetChild(0).Find("Root");
2024-08-16 13:55:00 +08:00
if (null == tsRoot)
return;
2024-04-03 19:11:09 +08:00
Transform tsWeaponRoot = tsRoot.Find("Bip001/Bip001 Spine/Bip001 Spine1/Bip001 R Clavicle/Bip001 R UpperArm/Bip001 R Forearm/Bip001 R Hand/Grip_point01");
if (tsWeaponRoot != null)
tsWeaponRoot.gameObject.SetActive(false);
}
/// <summary>
/// 获取Timeline资源
/// </summary>
2024-03-29 16:57:35 +08:00
/// <param name="timelineName"></param>
/// <returns></returns>
2024-03-29 16:57:35 +08:00
private async UniTask<TimelineAsset> GetTimeLineAsset(string timelineName)
{
2024-03-29 16:57:35 +08:00
if (!dicTimeLineAsset.TryGetValue(timelineName, out TimelineAsset timelineAsset))
{
2024-04-28 19:35:49 +08:00
string timelinePath = $"{SHOW_TIMELINE_PATH}{showSceneType}/{timelineName}.playable";
if (string.IsNullOrWhiteSpace(timelinePath))
{
2024-03-29 19:47:34 +08:00
DebugUtil.LogError($"找不到timelinePath,{nameof(timelineName)}:{timelineName}");
return null;
}
timelineAsset = await LoadAssetAsync<TimelineAsset>(timelinePath);
if (timelineAsset == null)
{
2024-03-29 19:47:34 +08:00
DebugUtil.LogError($"找不到TimelineAsset, {nameof(timelineName)}:{timelineName} path:{timelinePath}");
return null;
}
2024-03-29 16:57:35 +08:00
dicTimeLineAsset.Add(timelineName, timelineAsset);
}
return timelineAsset;
}
/// <summary>
/// 演出点是否重复
/// </summary>
/// <param name="group"></param>
/// <returns></returns>
private bool IsShowPointExist(ShowGroupData group)
{
foreach (DataShowConfig showConfig in group.ListConfig)
{
if (setUseShowPointIndex.Contains(showConfig.PointID))
return true;
}
return false;
}
/// <summary>
/// 是否可以使用限定角色
/// </summary>
/// <param name="group"></param>
/// <returns></returns>
private bool IsCanUseFixCharacter(ShowGroupData group)
{
2024-04-01 17:51:56 +08:00
foreach (DataShowConfig showConfig in group.ListConfig)
{
if (!ValueValidator.IsIdValid(showConfig.CharacterID) && !IsCanUseCharacter(showConfig.CharacterID))
return false;
}
return true;
}
/// <summary>
/// 角色是否可用
/// </summary>
/// <param name="characterId"></param>
/// <returns></returns>
private bool IsCanUseCharacter(int characterId)
{
return !setUseCharactrtId.Contains(characterId);
}
/// <summary>
/// 获取进度
/// </summary>
/// <returns>0f-1f</returns>
public float GetRefreshProcess()
{
return currState switch
{
E_CurState.None => 0f,
E_CurState.LoadingCharacters => (float)listShowPointResult.Count / CharacterMaxCount,
E_CurState.Present => 1f,
_ => 0f,
};
}
2024-04-01 17:51:56 +08:00
/// <summary>
/// 收集演出点
/// </summary>
[Button("收集演出点")]
public void CollectShowPoint()
{
if (tsCharacterShowPointRoot == null)
{
Debug.LogError("角色演出点为空");
return;
}
if (tsItemShowPointRoot == null)
{
Debug.LogError("道具演出点为空");
return;
}
#region 先清除原有演出点
Transform[] tsShowPoints = tsCharacterShowPointRoot.GetComponentsInChildren<Transform>();
foreach (Transform ts in tsShowPoints)
{
if (ts == tsCharacterShowPointRoot)
continue;
DestroyImmediate(ts.gameObject);
}
tsShowPoints = tsItemShowPointRoot.GetComponentsInChildren<Transform>();
foreach (Transform ts in tsShowPoints)
{
if (ts == tsItemShowPointRoot)
continue;
DestroyImmediate(ts.gameObject);
}
#endregion
ShowPoint[] showPoints = tsCollectRoot.GetComponentsInChildren<ShowPoint>();
2024-04-01 18:24:46 +08:00
int characterIndex = 0;
int itemIndex = 0;
2024-04-01 17:51:56 +08:00
foreach (ShowPoint showPoint in showPoints)
{
switch (showPoint.ShowPointType)
{
case E_ShowPointType.Character:
{
2024-04-03 19:11:09 +08:00
GameObject go = new($"{characterIndex++:D3}_{showPoint.Name}");
2024-04-01 18:24:46 +08:00
go.transform.SetPositionAndRotation(showPoint.gameObject.transform.position, showPoint.gameObject.transform.rotation);
2024-04-01 17:51:56 +08:00
go.transform.parent = tsCharacterShowPointRoot;
}
break;
case E_ShowPointType.Item:
{
2024-04-03 19:11:09 +08:00
GameObject go = new($"{itemIndex++:D3}_{showPoint.Name}");
2024-04-01 18:24:46 +08:00
go.transform.SetPositionAndRotation(showPoint.gameObject.transform.position, showPoint.gameObject.transform.rotation);
2024-04-01 17:51:56 +08:00
go.transform.parent = tsItemShowPointRoot;
}
break;
default:
{
Debug.LogError("未处理类型");
}
break;
}
}
}
}
/// <summary>
/// 抽取流程的记录
/// </summary>
[Serializable]
2024-04-26 14:48:47 +08:00
public class ExtractRecord
{
/// <summary>
/// 单个演出点记录
/// </summary>
[Serializable]
public struct SinglePointRecord
{
[LabelText("演出点ID")]
public int showPoint;
2024-03-29 16:57:35 +08:00
public string timelineName;
public uint characterID;
}
[LabelText("组ID")]
private int groupID;
[LabelText("抛弃原因")]
[ShowIf("isDispose")]
private E_DisposeReason disposeReason;
[LabelText("角色记录")]
private List<SinglePointRecord> listRecord;
public ExtractRecord(int groupID, E_DisposeReason disposeReason)
{
this.groupID = groupID;
this.disposeReason = disposeReason;
listRecord = new();
}
2024-04-26 14:48:47 +08:00
public void Add(SinglePointRecord singlePointRecord)
{
listRecord.Add(singlePointRecord);
}
}
/// <summary>
/// 演出组数据
/// </summary>
public struct ShowGroupData
{
/// <summary>
/// 演出组id
/// </summary>
private readonly int groupId;
/// <summary>
/// 是否必须有角色
/// </summary>
private bool isMustHasCharacter;
/// <summary>
/// 该组演出点配置数据
/// </summary>
private readonly List<DataShowConfig> listConfig;
/// <summary>
/// 演出组id
/// </summary>
public readonly int GroupID
{
get { return groupId; }
}
/// <summary>
/// 是否必须有角色
/// </summary>
public readonly bool IsMustHasCharacter { get { return isMustHasCharacter; } }
/// <summary>
/// 该组演出点配置数据
/// </summary>
public readonly List<DataShowConfig> ListConfig
{
get { return listConfig; }
}
public ShowGroupData(int groupId)
{
this.groupId = groupId;
isMustHasCharacter = false;
listConfig = new();
}
public void Add(DataShowConfig dataShowConfig)
{
isMustHasCharacter |= dataShowConfig.HasCharacter;
listConfig.Add(dataShowConfig);
}
/// <summary>
/// 打乱顺序
/// </summary>
public readonly void Shuffle()
{
CommonUtils.Shuffle(listConfig);
}
}
/// <summary>
/// 演出点结果
/// </summary>
public readonly struct ShowPointResult
{
/// <summary>
/// 演出组id
/// </summary>
private readonly int groupID;
/// <summary>
/// 演出点索引
/// </summary>
private readonly int showPointIndex;
/// <summary>
/// 道具演出点索引
/// </summary>
private readonly int itemPointIndex;
/// <summary>
2024-03-29 16:57:35 +08:00
/// Timeline名
/// </summary>
2024-03-29 16:57:35 +08:00
private readonly string timelineName;
/// <summary>
/// 道具名
/// </summary>
private readonly string itemName;
/// <summary>
/// 角色数据
/// </summary>
private readonly CharacterDataInfo characterData;
#region 属性
public int GroupID
{
get { return groupID; }
}
public int ShowPointIndex
{
get { return showPointIndex; }
}
2024-03-29 16:57:35 +08:00
public string TimelineName
{
2024-03-29 16:57:35 +08:00
get { return timelineName; }
}
public int ItemPointIndex
{
get { return itemPointIndex; }
}
public string ItemName
{
get { return itemName; }
}
public CharacterDataInfo CharacterData
{
get { return characterData; }
}
#endregion
public ShowPointResult(int groupID,
int showPointIndex,
string timelineName,
CharacterDataInfo characterData,
int itemPointIndex,
string itemName)
{
this.groupID = groupID;
this.showPointIndex = showPointIndex;
2024-03-29 16:57:35 +08:00
this.timelineName = timelineName;
this.characterData = characterData;
this.itemPointIndex = itemPointIndex;
this.itemName = itemName;
}
}