2024-01-10 18:30:01 +08:00
|
|
|
|
using System;
|
2024-01-10 14:56:43 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
2024-01-11 18:32:08 +08:00
|
|
|
|
using System.Linq;
|
2024-01-10 18:30:01 +08:00
|
|
|
|
using cfg.CampCfg;
|
2024-01-11 18:32:08 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
2024-01-10 18:30:01 +08:00
|
|
|
|
using Framework;
|
2024-01-11 18:32:08 +08:00
|
|
|
|
using Gameplay;
|
|
|
|
|
|
using PhxhSDK;
|
2024-01-10 14:56:43 +08:00
|
|
|
|
using Sirenix.OdinInspector;
|
|
|
|
|
|
using UnityEngine;
|
2024-01-11 18:32:08 +08:00
|
|
|
|
using UnityEngine.Playables;
|
2024-01-10 18:30:01 +08:00
|
|
|
|
using UnityEngine.Serialization;
|
2024-01-11 18:32:08 +08:00
|
|
|
|
using UnityEngine.Timeline;
|
|
|
|
|
|
using Object = UnityEngine.Object;
|
2024-01-10 18:30:01 +08:00
|
|
|
|
|
|
|
|
|
|
public class CampShowConfigGroup
|
|
|
|
|
|
{
|
|
|
|
|
|
public List<DataCampShowConfig> cfgs = new();
|
2024-01-11 18:32:08 +08:00
|
|
|
|
|
|
|
|
|
|
public bool hasToBeFull => cfgs.Any(cfg => cfg.HasCharacter);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class CampShowPointResult
|
|
|
|
|
|
{
|
|
|
|
|
|
public int showPoint;
|
|
|
|
|
|
|
|
|
|
|
|
public int timelineID;
|
|
|
|
|
|
|
|
|
|
|
|
public CharacterDataInfo characterDataInfo;
|
2024-01-10 18:30:01 +08:00
|
|
|
|
}
|
2024-01-10 14:56:43 +08:00
|
|
|
|
|
|
|
|
|
|
public class CampSceneManager : MonoBehaviour
|
|
|
|
|
|
{
|
2024-01-11 18:32:08 +08:00
|
|
|
|
private const string TIMELINE_ASSET_PATH_PREFIX = "Assets/Art/Camp/Timeline/camp_timeline_{0}.playable";
|
2024-01-10 18:30:01 +08:00
|
|
|
|
|
2024-01-10 19:01:07 +08:00
|
|
|
|
[LabelText("抽取角色数")]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
private int _characterMaxCount = 20;
|
2024-01-10 18:30:01 +08:00
|
|
|
|
|
2024-01-11 18:32:08 +08:00
|
|
|
|
[LabelText("timeline导演")]
|
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
private PlayableDirector _director;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("角色根节点")]
|
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
private Transform _characterRoot;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("营地物品根节点")]
|
|
|
|
|
|
[HideInInspector]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
private Transform _campObjectsRoot;
|
|
|
|
|
|
|
|
|
|
|
|
[LabelText("演出点")]
|
|
|
|
|
|
[FormerlySerializedAs("interactionPoints")]
|
|
|
|
|
|
[ListDrawerSettings(ShowIndexLabels = true, AlwaysAddDefaultValue = true)]
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
|
private List<GameObject> _showPoints = new();
|
2024-01-10 18:30:01 +08:00
|
|
|
|
|
|
|
|
|
|
private List<CharacterDataInfo> _allCharacterInfos = new();
|
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<int, CampShowConfigGroup> _allCampShowConfigGroups = new();
|
|
|
|
|
|
|
2024-01-11 18:32:08 +08:00
|
|
|
|
private List<CampShowConfigGroup> _remindCampShowConfigGroups = new();
|
|
|
|
|
|
|
|
|
|
|
|
private List<CharacterDataInfo> _remindCharacters = new();
|
|
|
|
|
|
|
|
|
|
|
|
private List<CampShowPointResult> _campShowPointResults = new();
|
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<CharacterDataInfo, GameObject> _models = new();
|
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<int, TimelineAsset> _timeLines = new();
|
|
|
|
|
|
|
|
|
|
|
|
private TimelineAsset _mainTimeline;
|
|
|
|
|
|
|
|
|
|
|
|
//asset相关
|
|
|
|
|
|
private HashSet<string> _assetToUnload = new();
|
|
|
|
|
|
|
|
|
|
|
|
private int CharacterMaxCount => Mathf.Min(_allCharacterInfos.Count, _characterMaxCount);
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
_mainTimeline = _director.playableAsset as TimelineAsset;
|
|
|
|
|
|
LoadData();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var path in _assetToUnload)
|
|
|
|
|
|
{
|
|
|
|
|
|
AssetManager.Instance.Unload(path);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async UniTask Refresh()
|
2024-01-10 18:30:01 +08:00
|
|
|
|
{
|
|
|
|
|
|
RefreshCampObjects();
|
2024-01-11 18:32:08 +08:00
|
|
|
|
await RefreshCampShow();
|
2024-01-10 18:30:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshCampObjects()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-11 18:32:08 +08:00
|
|
|
|
private async UniTask RefreshCampShow()
|
2024-01-10 18:30:01 +08:00
|
|
|
|
{
|
|
|
|
|
|
RefreshCampShowData();
|
2024-01-11 18:32:08 +08:00
|
|
|
|
await ExecuteCampShow();
|
2024-01-10 18:30:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-11 18:32:08 +08:00
|
|
|
|
private void LoadData()
|
2024-01-10 18:30:01 +08:00
|
|
|
|
{
|
|
|
|
|
|
_allCharacterInfos = new List<CharacterDataInfo>(CharacterDataInfoManager.Instance.DataList);
|
|
|
|
|
|
var campShowConfigList = TableManager.Instance.Tables.CampShowConfig.DataList;
|
|
|
|
|
|
_allCampShowConfigGroups.Clear();
|
2024-01-11 18:32:08 +08:00
|
|
|
|
|
2024-01-10 18:30:01 +08:00
|
|
|
|
foreach (var campShowConfig in campShowConfigList)
|
|
|
|
|
|
{
|
|
|
|
|
|
var groupID = campShowConfig.GroupID;
|
|
|
|
|
|
if (!_allCampShowConfigGroups.TryGetValue(groupID, out var group))
|
|
|
|
|
|
{
|
|
|
|
|
|
group = new();
|
|
|
|
|
|
_allCampShowConfigGroups.Add(groupID, group);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
group.cfgs.Add(campShowConfig);
|
|
|
|
|
|
}
|
2024-01-11 18:32:08 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var group in _allCampShowConfigGroups.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
//有指定ID的先选
|
|
|
|
|
|
group.cfgs.Sort((a, b) => b.CharacterID.CompareTo(a.CharacterID));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RefreshCampShowData()
|
|
|
|
|
|
{
|
|
|
|
|
|
_remindCampShowConfigGroups.Clear();
|
|
|
|
|
|
_remindCharacters.Clear();
|
|
|
|
|
|
_campShowPointResults.Clear();
|
|
|
|
|
|
|
|
|
|
|
|
_remindCampShowConfigGroups = new(_allCampShowConfigGroups.Values);
|
|
|
|
|
|
_remindCharacters = new(_allCharacterInfos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async UniTask ExecuteCampShow()
|
|
|
|
|
|
{
|
|
|
|
|
|
Extract();
|
|
|
|
|
|
await ExecuteResult();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//抽取
|
|
|
|
|
|
private void Extract()
|
|
|
|
|
|
{
|
|
|
|
|
|
List<CampShowPointResult> _tempResultList = new();
|
|
|
|
|
|
while (_campShowPointResults.Count < CharacterMaxCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
var randomGroup = CommonUtils.GetRandomItem(_remindCampShowConfigGroups, true);
|
|
|
|
|
|
if (randomGroup == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
//如果所有组都抽完了,则直接返回
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//如果组里的演出点和当前已经使用的演出点重复,则跳过该组
|
|
|
|
|
|
if (IsShowPointExist(randomGroup))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
//如果组里有限定演员,但演员已使用,则跳过该组
|
|
|
|
|
|
if (!CanUseCharacter(randomGroup))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
//临时存放抽取的结果
|
|
|
|
|
|
_tempResultList.Clear();
|
|
|
|
|
|
foreach (var cfg in randomGroup.cfgs)
|
|
|
|
|
|
{
|
|
|
|
|
|
//如果当前没有剩余的演员,则直接跳出抽取
|
|
|
|
|
|
if (_remindCharacters.Count == 0)
|
|
|
|
|
|
break;
|
|
|
|
|
|
//抽取timeline
|
|
|
|
|
|
var timelineID = CommonUtils.GetRandomItem(cfg.TimelineIDs);
|
|
|
|
|
|
if (timelineID == 0)
|
|
|
|
|
|
//说明不站人
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
CharacterDataInfo characterDataInfo = null;
|
|
|
|
|
|
if (cfg.CharacterID > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
//抽取指定演员
|
|
|
|
|
|
var index = _remindCharacters.FindIndex(characterInfo => characterInfo.ID == cfg.CharacterID);
|
|
|
|
|
|
characterDataInfo = _remindCharacters[index];
|
|
|
|
|
|
_remindCharacters.RemoveAt(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//随机抽取演员
|
|
|
|
|
|
characterDataInfo = CommonUtils.GetRandomItem(_remindCharacters, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CampShowPointResult result = new()
|
|
|
|
|
|
{
|
|
|
|
|
|
showPoint = cfg.PointID,
|
|
|
|
|
|
timelineID = timelineID,
|
|
|
|
|
|
characterDataInfo = characterDataInfo
|
|
|
|
|
|
};
|
|
|
|
|
|
_tempResultList.Add(result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (randomGroup.hasToBeFull && _tempResultList.Count < randomGroup.cfgs.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
//如果该组必须满员但没满员
|
|
|
|
|
|
//取出来的CharacterDataInfo归还
|
|
|
|
|
|
foreach (var result in _tempResultList)
|
|
|
|
|
|
{
|
|
|
|
|
|
_remindCharacters.Add(result.characterDataInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//添加到最后的result列表中
|
|
|
|
|
|
_campShowPointResults.AddRange(_tempResultList);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//执行抽取结果
|
|
|
|
|
|
private async UniTask ExecuteResult()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_campShowPointResults.Count == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
foreach (var result in _campShowPointResults)
|
|
|
|
|
|
{
|
|
|
|
|
|
var showPointID = result.showPoint;
|
|
|
|
|
|
if (showPointID < 0 || showPointID >= _showPoints.Count || _showPoints[showPointID] == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"找不到演出点!演出点ID:{showPointID}");
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var showPointTransform = _showPoints[showPointID];
|
|
|
|
|
|
|
|
|
|
|
|
var model = await GetModel(result.characterDataInfo);
|
|
|
|
|
|
if (model == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
model = Instantiate(model, _characterRoot);
|
|
|
|
|
|
model.transform.position = showPointTransform.transform.position;
|
|
|
|
|
|
model.transform.rotation = showPointTransform.transform.rotation;
|
|
|
|
|
|
|
|
|
|
|
|
var timelineAsset = await GetTimeLineAsset(result.timelineID);
|
|
|
|
|
|
if (timelineAsset == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var groupTrack = _mainTimeline.CreateTrack<GroupTrack>();
|
|
|
|
|
|
groupTrack.name = timelineAsset.name;
|
|
|
|
|
|
foreach (var trackAsset in timelineAsset.GetRootTracks())
|
|
|
|
|
|
{
|
|
|
|
|
|
trackAsset.SetGroup(groupTrack);
|
|
|
|
|
|
//trackAsset.outputs
|
|
|
|
|
|
//_director.SetGenericBinding();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async UniTask<GameObject> GetModel(CharacterDataInfo characterDataInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_models.TryGetValue(characterDataInfo, out var model))
|
|
|
|
|
|
{
|
|
|
|
|
|
string prefabPath = characterDataInfo.PrefabPath;
|
|
|
|
|
|
model = await AssetManager.Instance.LoadAssetAsync<GameObject>(prefabPath);
|
|
|
|
|
|
if (model == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"找不到模型, path:{prefabPath}");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_assetToUnload.Add(prefabPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_models.Add(characterDataInfo, model);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return model;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async UniTask<TimelineAsset> GetTimeLineAsset(int timelineID)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_timeLines.TryGetValue(timelineID, out var timelineAsset))
|
|
|
|
|
|
{
|
|
|
|
|
|
string timelinePath = string.Format(TIMELINE_ASSET_PATH_PREFIX, timelineID);
|
|
|
|
|
|
timelineAsset = await AssetManager.Instance.LoadAssetAsync<TimelineAsset>(timelinePath);
|
|
|
|
|
|
if (timelineAsset == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"找不到TimelineAsset, timelineID:{timelineID} path:{timelinePath}");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_assetToUnload.Add(timelinePath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_timeLines.Add(timelineID, timelineAsset);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return timelineAsset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool IsShowPointExist(CampShowConfigGroup group)
|
|
|
|
|
|
{
|
|
|
|
|
|
return group.cfgs.Any(cfg => IsShowPointExist(cfg.PointID));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool IsShowPointExist(int showPointID)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _campShowPointResults.Any(result => result.showPoint == showPointID);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool CanUseCharacter(CampShowConfigGroup group)
|
|
|
|
|
|
{
|
|
|
|
|
|
return !group.cfgs.Any(cfg => cfg.CharacterID > 0 && !CanUseCharacter(cfg.CharacterID));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool CanUseCharacter(int characterID)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _remindCharacters.Any(characterInfo => characterInfo.ID == characterID);
|
2024-01-10 18:30:01 +08:00
|
|
|
|
}
|
2024-01-10 19:01:07 +08:00
|
|
|
|
|
2024-01-10 18:30:01 +08:00
|
|
|
|
public float GetRefreshProcess()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 100;
|
|
|
|
|
|
}
|
2024-01-10 14:56:43 +08:00
|
|
|
|
}
|