177 lines
5.8 KiB
C#
177 lines
5.8 KiB
C#
![]() |
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Threading;
|
||
|
using System.Threading.Tasks;
|
||
|
using BITKit;
|
||
|
using BITKit.IO;
|
||
|
using Cysharp.Threading.Tasks;
|
||
|
using Microsoft.Extensions.Logging;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Experimental.Rendering;
|
||
|
using UnityEngine.SceneManagement;
|
||
|
using YooAsset;
|
||
|
|
||
|
namespace Project.B.Map
|
||
|
{
|
||
|
public class GameMapService : IGameMapService,IDisposable
|
||
|
{
|
||
|
public bool PreloadShaders { get; set; } = true;
|
||
|
private readonly ILogger<GameMapService> _logger;
|
||
|
private const string MenuScene = "map_menu";
|
||
|
private readonly ValidHandle _isBusy = new();
|
||
|
public TaskStatus TaskStatus
|
||
|
{
|
||
|
get => _taskStatus;
|
||
|
private set
|
||
|
{
|
||
|
if (_taskStatus == value) return;
|
||
|
OnTaskStatusChanged?.Invoke(_taskStatus, value);
|
||
|
_taskStatus = value;
|
||
|
}
|
||
|
}
|
||
|
private TaskStatus _taskStatus;
|
||
|
|
||
|
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
||
|
|
||
|
public GameMapService(ILogger<GameMapService> logger)
|
||
|
{
|
||
|
_logger = logger;
|
||
|
}
|
||
|
|
||
|
public string CurrentMap { get;private set; }
|
||
|
|
||
|
public UniTask<string> GetMapAsync()
|
||
|
{
|
||
|
return UniTask.FromResult(CurrentMap);
|
||
|
}
|
||
|
|
||
|
public async UniTask StartMapAsync(string map)
|
||
|
{
|
||
|
await _isBusy;
|
||
|
|
||
|
using var _ = _isBusy.GetHandle();
|
||
|
|
||
|
TaskStatus = TaskStatus.Running;
|
||
|
|
||
|
SceneHandle handle = null;
|
||
|
|
||
|
ResourcePackage mapPackage = null;
|
||
|
|
||
|
CurrentMap = map;
|
||
|
|
||
|
await OnMapChange.UniTaskFunc(map);
|
||
|
|
||
|
await UniTask.NextFrame();
|
||
|
|
||
|
foreach (var resourcePackage in YooAssetUtils.RegisteredResourcePackages)
|
||
|
{
|
||
|
if (YooAssetModHelper.PackagesManifestDictionary[resourcePackage.PackageName].Contains(map) is false)
|
||
|
continue;
|
||
|
|
||
|
var assetInfo = resourcePackage.GetAssetInfo(map);
|
||
|
|
||
|
mapPackage = resourcePackage;
|
||
|
handle = resourcePackage.LoadSceneAsync(assetInfo.AssetPath);
|
||
|
}
|
||
|
|
||
|
if (handle is null)
|
||
|
{
|
||
|
throw new Exception($"找不到地图:{map}");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
while (handle.IsDone is false && handle.IsValid)
|
||
|
{
|
||
|
await UniTask.NextFrame();
|
||
|
OnMapLoadingProgress?.Invoke(Guid.Empty, handle.Progress, "正在加载地图");
|
||
|
//if(_cancellationTokenSource.IsCancellationRequested)return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if (PreloadShaders)
|
||
|
{
|
||
|
OnMapLoadingProgress?.Invoke(Guid.Empty, 1, "地图加载完成,正在查找着色器...");
|
||
|
|
||
|
if (YooAssetModHelper.PackagesManifestDictionary[mapPackage.PackageName].Contains("MyShaderVariants"))
|
||
|
{
|
||
|
var shaderAssetInfo = mapPackage.GetAssetInfo("MyShaderVariants");
|
||
|
|
||
|
var hashset = new HashSet<Material>();
|
||
|
|
||
|
_logger.LogInformation("已找到着色器,加载中...");
|
||
|
OnMapLoadingProgress?.Invoke(Guid.Empty, 1, "找到着色器,正在初始化...");
|
||
|
var assetHandle = mapPackage.LoadAssetSync(shaderAssetInfo);
|
||
|
var shader = (ShaderVariantCollection)assetHandle.AssetObject;
|
||
|
shader.WarmUp();
|
||
|
|
||
|
|
||
|
foreach (var gameObject in handle.SceneObject.GetRootGameObjects())
|
||
|
{
|
||
|
foreach (var meshRenderer in gameObject.GetComponentsInChildren<MeshRenderer>())
|
||
|
{
|
||
|
foreach (var material in meshRenderer.sharedMaterials)
|
||
|
{
|
||
|
hashset.Add(material);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach (var terrain in gameObject.GetComponentsInChildren<Terrain>())
|
||
|
{
|
||
|
hashset.Add(terrain.materialTemplate);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach (var material in hashset)
|
||
|
{
|
||
|
if (!material) continue;
|
||
|
if (material.shader is null) continue;
|
||
|
material.shader = Shader.Find(material.shader.name);
|
||
|
}
|
||
|
|
||
|
|
||
|
_logger.LogInformation($"着色器加载完成,有Shader{shader.shaderCount}个,Variant:{shader.variantCount}个");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_logger.LogInformation("未找到着色器,跳过加载...");
|
||
|
}
|
||
|
|
||
|
OnMapLoadingProgress?.Invoke(Guid.Empty, 1, "着色器预热完成,准备就绪");
|
||
|
|
||
|
TaskStatus = TaskStatus.RanToCompletion;
|
||
|
|
||
|
await OnMapChanging.UniTaskFunc(map);
|
||
|
|
||
|
OnMapChanged?.Invoke(Guid.Empty, CurrentMap);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public async UniTask StopMapAsync()
|
||
|
{
|
||
|
await _isBusy;
|
||
|
using var _ = _isBusy.GetHandle();
|
||
|
|
||
|
TaskStatus = TaskStatus.WaitingForActivation;
|
||
|
//if(_cancellationTokenSource.IsCancellationRequested)return;
|
||
|
await YooAssets.LoadSceneAsync(MenuScene);
|
||
|
|
||
|
OnMapChanged?.Invoke(Guid.Empty, string.Empty);
|
||
|
}
|
||
|
|
||
|
public event Action<TaskStatus, TaskStatus> OnTaskStatusChanged;
|
||
|
public event Func<string, UniTask> OnMapChange;
|
||
|
public event Func<string, UniTask> OnMapChanging;
|
||
|
public event Action<Guid, string> OnMapChanged;
|
||
|
public event Action<Guid, float, string> OnMapLoadingProgress;
|
||
|
|
||
|
public void Dispose()
|
||
|
{
|
||
|
_cancellationTokenSource.Cancel();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|