937 lines
32 KiB
C#
937 lines
32 KiB
C#
using cfg.ShowCfg;
|
||
using Cysharp.Threading.Tasks;
|
||
using Framework;
|
||
using Gameplay.Emoji;
|
||
using PhxhSDK;
|
||
using Sirenix.OdinInspector;
|
||
using Sirenix.Utilities;
|
||
using SRF;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEngine;
|
||
using UnityEngine.Experimental.Playables;
|
||
using UnityEngine.Playables;
|
||
using UnityEngine.Timeline;
|
||
|
||
namespace Gameplay.Show
|
||
{
|
||
public sealed class ShowController : IShow
|
||
{
|
||
/// <summary>
|
||
/// 当前状态
|
||
/// </summary>
|
||
private enum E_CurState
|
||
{
|
||
None = 0,
|
||
/// <summary>
|
||
/// 加载角色
|
||
/// </summary>
|
||
LoadingCharacters,
|
||
/// <summary>
|
||
/// 当前
|
||
/// </summary>
|
||
Present,
|
||
}
|
||
|
||
private ShowComponent showComponent;
|
||
|
||
/// <summary>
|
||
/// 演出Timeline路径
|
||
/// </summary>
|
||
private const string SHOW_TIMELINE_PATH = "Assets/Art/Show/";
|
||
/// <summary>
|
||
/// 道具Timeline上角色轨道名
|
||
/// </summary>
|
||
private const string ITEM_TIMELINE_TRACK_NAME = "Character";
|
||
/// <summary>
|
||
/// 角色Activation轨道名
|
||
/// </summary>
|
||
private const string CHARACTER_ACTIVATION_TRACK_NAME = "characterActivationTrack";
|
||
|
||
/// <summary>
|
||
/// 当前场景所有角色演出点
|
||
/// </summary>
|
||
private List<Transform> listCharacterShowPoint = new();
|
||
/// <summary>
|
||
/// 当前场景所有道具演出点
|
||
/// </summary>
|
||
private List<Transform> listItemShowPoint = new();
|
||
|
||
/// <summary>
|
||
/// 当前场景所有演出组字典 key:组id value:演出组数据
|
||
/// </summary>
|
||
private readonly Dictionary<int, ShowGroupData> dicShowGroup = new();
|
||
/// <summary>
|
||
/// 最终的演出点数据
|
||
/// </summary>
|
||
private readonly List<ShowPointResult> listShowPointResult = new();
|
||
/// <summary>
|
||
/// Timeline资源字典
|
||
/// </summary>
|
||
private readonly Dictionary<string, TimelineAsset> dicTimeLineAsset = new();
|
||
/// <summary>
|
||
/// 道具字典,部分Timeline挂载到道具上,优先使用道具上的Timeline
|
||
/// </summary>
|
||
private readonly Dictionary<string, Stack<GameObject>> dicItemModel = new();
|
||
/// <summary>
|
||
/// 角色模型字典
|
||
/// </summary>
|
||
private readonly Dictionary<int, GameObject> dicCharacterModel = new();
|
||
/// <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>
|
||
private E_CurState currState = E_CurState.None;
|
||
|
||
#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, showComponent.CharacterMaxCount, listCharacterShowPoint.Count); }
|
||
}
|
||
|
||
public E_ShowSceneType ShowSceneType => showComponent.ShowSceneTyp;
|
||
|
||
public void Destory()
|
||
{
|
||
dicTimeLineAsset.Clear();
|
||
dicCharacterModel.Clear();
|
||
dicItemModel.Clear();
|
||
dicItemOffset.Clear();
|
||
|
||
foreach (string path in setAssetToUnload)
|
||
{
|
||
AssetManager.Instance.Unload(path);
|
||
}
|
||
|
||
foreach (var unitEmojiManager in listCacheEmoji)
|
||
{
|
||
unitEmojiManager.Dispose();
|
||
}
|
||
}
|
||
|
||
public void SetInfo(ShowComponent showComponent)
|
||
{
|
||
this.showComponent = showComponent;
|
||
|
||
#region 获取角色演出点
|
||
showComponent.GetCharacterShowPoint(ref listCharacterShowPoint);
|
||
#endregion
|
||
|
||
#region 获取道具演出点
|
||
showComponent.GetItemShowPoint(ref listItemShowPoint);
|
||
#endregion
|
||
|
||
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);
|
||
|
||
group.Add(showConfig);
|
||
dicShowGroup[groupID] = group;
|
||
}
|
||
|
||
foreach (ShowGroupData group in dicShowGroup.Values)
|
||
{
|
||
group.Shuffle();
|
||
}
|
||
}
|
||
|
||
public void PlayeCameraAnim(Action callback, params string[] args)
|
||
{
|
||
if (null == showComponent.CameraPlayable)
|
||
{
|
||
DebugUtil.LogError("相机Playable未赋值");
|
||
return;
|
||
}
|
||
|
||
showComponent.CameraAction = callback;
|
||
|
||
showComponent.CameraPlayable.Play();
|
||
}
|
||
|
||
public 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 (showComponent.IsIgnoreKanban)
|
||
{
|
||
MainPanelSceneStoreData storeData = StorageMgr.Instance.GetStorage<MainPanelSceneStoreData>("MainPanelSceneStoreData");
|
||
if (storeData == null)
|
||
DebugUtil.LogError("没有看板娘数据");
|
||
else
|
||
kanbanbanId = storeData.PosterID;
|
||
}
|
||
#endregion
|
||
|
||
foreach (CharacterDataInfo characterDataInfo in CharacterDataInfoManager.Instance.DataList)
|
||
{
|
||
if (showComponent.IsIgnoreKanban && 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()
|
||
{
|
||
listShowPointResult.Clear();
|
||
|
||
List<ShowPointResult> listTempResult = new(); // 临时存放抽取的结果
|
||
|
||
if (dicShowGroup.TryGetValue(30, out ShowGroupData value1))
|
||
{
|
||
linkShowGroup.Remove(value1);
|
||
CheckShowGroup(ref listTempResult, value1, false);
|
||
}
|
||
|
||
if (dicShowGroup.TryGetValue(31, out ShowGroupData value31))
|
||
{
|
||
linkShowGroup.Remove(value31);
|
||
CheckShowGroup(ref listTempResult, value31, false);
|
||
}
|
||
|
||
if (dicShowGroup.TryGetValue(32, out ShowGroupData value32))
|
||
{
|
||
linkShowGroup.Remove(value32);
|
||
CheckShowGroup(ref listTempResult, value32, false);
|
||
}
|
||
|
||
if (dicShowGroup.TryGetValue(33, out ShowGroupData value33))
|
||
{
|
||
linkShowGroup.Remove(value33);
|
||
CheckShowGroup(ref listTempResult, value33, false);
|
||
}
|
||
|
||
if (dicShowGroup.TryGetValue(34, out ShowGroupData value34))
|
||
{
|
||
linkShowGroup.Remove(value34);
|
||
CheckShowGroup(ref listTempResult, value34, false);
|
||
}
|
||
|
||
if (dicShowGroup.TryGetValue(35, out ShowGroupData value35))
|
||
{
|
||
linkShowGroup.Remove(value31);
|
||
CheckShowGroup(ref listTempResult, value35, false);
|
||
}
|
||
|
||
while (linkShowGroup.First != null)
|
||
{
|
||
ShowGroupData groupData = linkShowGroup.First.Value;
|
||
linkShowGroup.RemoveFirst();
|
||
|
||
CheckShowGroup(ref listTempResult, groupData);
|
||
}
|
||
|
||
setUseShowPointIndex.Clear();
|
||
setUseCharactrtId.Clear();
|
||
}
|
||
|
||
private void CheckShowGroup(ref List<ShowPointResult> listTempResult, ShowGroupData groupData, bool isCheck = true)
|
||
{
|
||
if (isCheck)
|
||
{
|
||
// 如果组里的演出点和当前已经使用的演出点重复,则踢出该组
|
||
if (IsShowPointExist(groupData))
|
||
return;
|
||
|
||
// 如果是固定角色的组的角色已经被使用,则踢出该组
|
||
if (!IsCanUseFixCharacter(groupData))
|
||
return;
|
||
}
|
||
|
||
listTempResult.Clear();
|
||
ExtractRecord extractRecord = new(groupData.GroupID);
|
||
foreach (DataShowConfig dataShowConfig in groupData.ListConfig)
|
||
{
|
||
// 如果当前没有剩余的演员,则直接跳出抽取
|
||
if (linkCharacter.First == null)
|
||
break;
|
||
|
||
#region 抽取timeline
|
||
string timelineName = CommonUtils.GetRandomItem(dataShowConfig.TimelineNames);
|
||
ExtractRecord.SinglePointRecord singlePointRecord = new()
|
||
{
|
||
timelineName = timelineName
|
||
};
|
||
extractRecord.Add(singlePointRecord);
|
||
|
||
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.IsMustExist && groupData.IsMustHasCharacter && listTempResult.Count < groupData.ListConfig.Count)
|
||
{
|
||
// 如果该组必须满员但没满员
|
||
// 取出来的CharacterDataInfo归还
|
||
foreach (ShowPointResult result in listTempResult)
|
||
{
|
||
listRemindCharacter.Add(result.CharacterData);
|
||
}
|
||
}
|
||
else // 添加到最后的result列表中
|
||
{
|
||
foreach (ShowPointResult result in listTempResult)
|
||
{
|
||
listShowPointResult.Add(result);
|
||
setUseCharactrtId.Add((int)result.CharacterData.ID);
|
||
setUseShowPointIndex.Add(result.ShowPointIndex);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行演出结果
|
||
/// </summary>
|
||
private async UniTask ExecuteShowResult()
|
||
{
|
||
if (listShowPointResult.Count == 0)
|
||
return;
|
||
|
||
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)
|
||
{
|
||
Transform tsItemShowPoint = listItemShowPoint[itemShowPointIndex].transform; // 获取道具演出点,有道具演出
|
||
GameObject goFixItemModel = await GetItemModel(result.ItemName); // 加载固定道具
|
||
if (goFixItemModel != null)
|
||
goFixItemModel.transform.SetPositionAndRotation(tsItemShowPoint.position, tsItemShowPoint.rotation);
|
||
}
|
||
|
||
GameObject goCharacterModel = await GetCharacterModel(result.CharacterData);
|
||
if (goCharacterModel == null)
|
||
continue;
|
||
|
||
goCharacterModel.SetActive(true);
|
||
goCharacterModel.transform.SetPositionAndRotation(tsShowPoint.position, tsShowPoint.rotation);
|
||
|
||
GameObject goItemModel = await GetItemModel(result.TimelineName);// 优先使用道具上的Timeline
|
||
if (goItemModel == null) // 没有道具,直接加载Timeline
|
||
{
|
||
TimelineAsset timelineAsset = await GetTimeLineAsset(result.TimelineName);
|
||
if (timelineAsset == null)
|
||
continue;
|
||
|
||
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>());
|
||
}
|
||
|
||
foreach (TrackAsset trackAsset in timelineAsset.GetOutputTracks())
|
||
{
|
||
if (trackAsset.name.Equals(CHARACTER_ACTIVATION_TRACK_NAME))
|
||
playableDirector.SetGenericBinding(trackAsset, goCharacterModel.transform.GetChild(0)?.gameObject);
|
||
}
|
||
|
||
playableDirector.enabled = true;
|
||
playableDirector.time = UnityEngine.Random.Range(0f, (float)playableDirector.duration);
|
||
playableDirector.Play();
|
||
}
|
||
else // 有道具,不加载Timeline
|
||
{
|
||
#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>());
|
||
|
||
if (trackAsset.name.Equals(CHARACTER_ACTIVATION_TRACK_NAME))
|
||
{
|
||
Transform tsGo = goCharacterModel.transform.GetChild(0);
|
||
if (null == tsGo)
|
||
DebugUtil.LogError("赋值空的角色到Timeline轨道上");
|
||
else
|
||
playableDirector.SetGenericBinding(trackAsset, tsGo.gameObject);
|
||
}
|
||
}
|
||
|
||
playableDirector.time = UnityEngine.Random.Range(0f, (float)playableDirector.duration);
|
||
playableDirector.Play();
|
||
}
|
||
}
|
||
|
||
#region 放回道具
|
||
foreach (var kv in dicTempGoItem)
|
||
{
|
||
if (!dicItemModel.TryGetValue(kv.Key, out Stack<GameObject> stack))
|
||
continue;
|
||
|
||
stack ??= new();
|
||
|
||
while (kv.Value.Count > 0)
|
||
{
|
||
stack.Push(kv.Value.Pop());
|
||
}
|
||
}
|
||
|
||
dicTempGoItem.Clear();
|
||
#endregion
|
||
}
|
||
|
||
/// <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 : Framework.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;
|
||
var unitEmojiManager = new UnitEmojiManager(cObj, eyesColor, eyebowsType, eyebowsColor);
|
||
unitEmojiManager.SwitchEmoji(config.DefaultDisplayEmojiId);
|
||
|
||
return unitEmojiManager;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 异步加载资源
|
||
/// </summary>
|
||
/// <typeparam name="T"></typeparam>
|
||
/// <param name="path"></param>
|
||
/// <returns></returns>
|
||
private async UniTask<T> LoadAssetAsync<T>(string path) where T : UnityEngine.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>
|
||
private async UniTask<GameObject> GetCharacterModel(CharacterDataInfo characterDataInfo)
|
||
{
|
||
if (!dicCharacterModel.TryGetValue(characterDataInfo.Cfg.RoleID, out GameObject goModel))
|
||
{
|
||
string prefabPath = CommonUtils.GetFightCharacterModelPath(characterDataInfo);
|
||
goModel = await LoadAssetAsync<GameObject>(prefabPath);
|
||
if (goModel == null)
|
||
{
|
||
DebugUtil.LogError($"找不到模型, path:{prefabPath}");
|
||
return null;
|
||
}
|
||
|
||
goModel = GameObject.Instantiate(goModel, showComponent.TsShowPointRoot);
|
||
goModel.SetLayerEx(Framework.Constants.Layer.UIVIEW);
|
||
HideCharacterWeapon(goModel);
|
||
|
||
dicCharacterModel.Add(characterDataInfo.Cfg.RoleID, goModel);
|
||
}
|
||
|
||
return goModel;
|
||
}
|
||
|
||
/// <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)
|
||
{
|
||
string itemPath = $"{SHOW_TIMELINE_PATH}{ShowSceneType}/{name}.prefab";
|
||
|
||
if (!AssetManager.Instance.CanLocateAsset<GameObject>(itemPath))
|
||
return null;
|
||
|
||
stackItem ??= new();
|
||
|
||
GameObject goItem = await LoadAssetAsync<GameObject>(itemPath);
|
||
if (goItem == null)
|
||
return null;
|
||
|
||
goItem = GameObject.Instantiate(goItem, showComponent.TsItemShowPointRoot);
|
||
goItem.SetLayerEx(Framework.Constants.Layer.UIVIEW);
|
||
dicItemModel[name] = stackItem;
|
||
dicItemOffset[goItem.GetInstanceID()] = goItem.transform.position;
|
||
|
||
return goItem;
|
||
}
|
||
|
||
return stackItem.Pop();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏角色武器
|
||
/// </summary>
|
||
private void HideCharacterWeapon(GameObject goCharacter)
|
||
{
|
||
if (goCharacter.transform.childCount < 1)
|
||
{
|
||
DebugUtil.LogError("角色节点错误:" + goCharacter.name);
|
||
return;
|
||
}
|
||
// TODO 临时隐藏武器方式
|
||
Transform tsRoot = goCharacter.transform.GetChild(0).Find("Root");
|
||
if (null == tsRoot)
|
||
return;
|
||
|
||
Transform tsWeaponRoot = tsRoot.Find("Bip001/Bip001 Spine/Bip001 Spine1/Bip001 R Clavicle/Bip001 R UpperArm/Bip001 R Forearm/Bip001 R Hand/Grip_point01");
|
||
if (null == tsWeaponRoot)
|
||
return;
|
||
|
||
tsWeaponRoot.gameObject.IsScaleShow(false);
|
||
for (int i = 0; i < tsWeaponRoot.childCount; ++i)
|
||
{
|
||
tsWeaponRoot.GetChild(i).gameObject.IsScaleShow(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取Timeline资源
|
||
/// </summary>
|
||
/// <param name="timelineName"></param>
|
||
/// <returns></returns>
|
||
private async UniTask<TimelineAsset> GetTimeLineAsset(string timelineName)
|
||
{
|
||
if (!dicTimeLineAsset.TryGetValue(timelineName, out TimelineAsset timelineAsset))
|
||
{
|
||
string timelinePath = $"{SHOW_TIMELINE_PATH}{ShowSceneType}/{timelineName}.playable";
|
||
if (string.IsNullOrWhiteSpace(timelinePath))
|
||
{
|
||
DebugUtil.LogError($"找不到timelinePath,{nameof(timelineName)}:{timelineName}");
|
||
return null;
|
||
}
|
||
|
||
timelineAsset = await LoadAssetAsync<TimelineAsset>(timelinePath);
|
||
if (timelineAsset == null)
|
||
{
|
||
DebugUtil.LogError($"找不到TimelineAsset, {nameof(timelineName)}:{timelineName} path:{timelinePath}");
|
||
return null;
|
||
}
|
||
|
||
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)
|
||
{
|
||
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>
|
||
[Serializable]
|
||
public class ExtractRecord
|
||
{
|
||
/// <summary>
|
||
/// 单个演出点记录
|
||
/// </summary>
|
||
[Serializable]
|
||
public struct SinglePointRecord
|
||
{
|
||
[LabelText("演出点ID")]
|
||
public int showPoint;
|
||
|
||
public string timelineName;
|
||
|
||
public uint characterID;
|
||
}
|
||
|
||
[LabelText("组ID")]
|
||
private int groupID;
|
||
|
||
[LabelText("角色记录")]
|
||
private List<SinglePointRecord> listRecord;
|
||
|
||
public ExtractRecord(int groupID)
|
||
{
|
||
this.groupID = groupID;
|
||
|
||
listRecord = new();
|
||
}
|
||
|
||
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 bool isMustExist;
|
||
/// <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 bool IsMustExist { get { return isMustExist; } }
|
||
|
||
/// <summary>
|
||
/// 该组演出点配置数据
|
||
/// </summary>
|
||
public readonly List<DataShowConfig> ListConfig
|
||
{
|
||
get { return listConfig; }
|
||
}
|
||
|
||
public ShowGroupData(int groupId)
|
||
{
|
||
this.groupId = groupId;
|
||
|
||
isMustHasCharacter = false;
|
||
isMustExist = false;
|
||
listConfig = new();
|
||
}
|
||
|
||
public void Add(DataShowConfig dataShowConfig)
|
||
{
|
||
isMustHasCharacter |= dataShowConfig.HasCharacter;
|
||
isMustExist |= dataShowConfig.IsMustExist;
|
||
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>
|
||
/// Timeline名
|
||
/// </summary>
|
||
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; }
|
||
}
|
||
|
||
public string TimelineName
|
||
{
|
||
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;
|
||
this.timelineName = timelineName;
|
||
this.characterData = characterData;
|
||
this.itemPointIndex = itemPointIndex;
|
||
this.itemName = itemName;
|
||
}
|
||
}
|
||
} |