NLDClient-yudde/ProjectNLD/Assets/Editor/Scene/PostProcesser/PostProcessor.cs

701 lines
22 KiB
C#
Raw Normal View History

2024-01-15 20:25:49 +08:00
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
2024-04-28 18:19:18 +08:00
using UnityEngine.Rendering;
2024-01-15 20:25:49 +08:00
using UnityEngine.SceneManagement;
2025-04-14 15:51:02 +08:00
using Object = UnityEngine.Object;
2024-01-15 20:25:49 +08:00
public abstract class PostProcessor
{
2025-05-08 11:59:40 +08:00
/// <summary>
/// 后处理命名后缀
/// </summary>
2024-01-15 20:25:49 +08:00
public const string SCENE_POST_PROCESS_NAME = "PostProcess";
2025-05-08 11:59:40 +08:00
/// <summary>
/// 合并网格后的节点
/// </summary>
2024-01-15 20:25:49 +08:00
private const string SCENE_COMBINED_NAME = "Combined";
2025-05-08 11:59:40 +08:00
/// <summary>
/// 后处理后存放地面贴图材质的文件夹命名
/// </summary>
private const string GROUND_TEXTURE_MAT_PATH = "Ground";
/// <summary>
/// 后处理后存放光照贴图和烘焙数据的文件夹命名
/// </summary>
2025-04-07 18:55:27 +08:00
private const string LIGHT_BAKE_NAME = "LightMaps";
2024-10-22 16:10:43 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 后处理预制体根路径
/// </summary>
protected const string PREFAB_POSTPROCESS_DIR = "Assets/Art_Out/AutoGen/PostProcessPrefabs";
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 场景资源分组路径 暂时舍弃没有使用Addressable
/// </summary>
2024-01-15 20:25:49 +08:00
protected const string SCENE_ADDRESSABLE_GROUP = "PostProcessScenes";
2025-05-08 11:59:40 +08:00
/// <summary>
/// 预制体资源分组路径 暂时舍弃没有使用Addressable
/// </summary>
2024-01-15 20:25:49 +08:00
protected const string PREFAB_ADDRESSABLE_GROUP = "PostProcessPrefabs";
2025-05-08 11:59:40 +08:00
/// <summary>
/// 区分剧情场景的文件夹前缀
/// </summary>
private const string STORY_SCENE_PREFIX = "story_";
2025-05-08 11:59:40 +08:00
/// <summary>
/// 切割地面贴图宽度
/// </summary>
2024-01-15 20:25:49 +08:00
private const int GROUND_SPLIT_WIDTH = 1024;
2025-05-08 11:59:40 +08:00
/// <summary>
/// 切割地面贴图高度
/// </summary>
private const int GROUND_SPLIT_HEIGHT = 1024;
2025-04-15 16:33:01 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 像素
/// </summary>
private const int UPP = 100;
2025-04-17 19:25:12 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 烘焙后需要替换shader的渲染器列表
/// </summary>
private readonly List<Renderer> needReplaceRenderers = new();
2025-04-17 19:25:12 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 烘焙后需要关闭产生阴影的渲染器列表
/// </summary>
private readonly List<Renderer> allBakeRenderers = new();
2025-04-17 19:25:12 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 实时灯光
/// </summary>
private readonly List<Light> realTimeLights = new();
2025-04-17 19:25:12 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 烘焙灯光
/// </summary>
private readonly List<Light> bakedLights = new();
2025-04-14 15:51:02 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 检查规范节点
/// </summary>
2024-10-22 16:10:43 +08:00
private readonly List<string> sceneRoots = new()
2025-04-07 18:55:27 +08:00
{
"Main Camera", "TerrainGridSystem", "Art", "SceneManager", "MapEditor", "LevelEditor", "TGSPreview",
"InputManager (Singleton)"
};
2025-04-15 16:33:01 +08:00
2025-04-17 19:25:12 +08:00
/// <summary>
/// 需要替换shader烘焙的节点
/// </summary>
2025-05-08 11:59:40 +08:00
private readonly List<string> bakeReplaceShaderRoot = new() { "CombinedRoot" };
2025-04-14 15:51:02 +08:00
/// <summary>
2025-05-08 11:59:40 +08:00
/// 需要烘焙的其他地面节点
2025-04-14 15:51:02 +08:00
/// </summary>
2025-05-08 11:59:40 +08:00
private readonly List<string> groundRoot = new() { "Ground_2" };
2024-10-22 16:10:43 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 后处理文件夹路径
/// </summary>
2024-01-15 20:25:49 +08:00
protected string ProcessedResourceDir => $"{ResourcesBaseDir}/{PostProcessFolderName}";
2025-05-08 11:59:40 +08:00
protected abstract string PostProcessFolderName { get; }
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
protected abstract string ResourcesBaseDir { get; }
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
protected abstract Object AssetToPostProcess { get; }
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
protected abstract string OutputAssetPath { get; }
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
private string LightBakeDir => $"{ProcessedResourceDir}/{LIGHT_BAKE_NAME}";
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
private string GroundSplitDir => $"{ProcessedResourceDir}/{GROUND_TEXTURE_MAT_PATH}";
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 是否完成复制场景
/// </summary>
2024-01-15 20:25:49 +08:00
private bool HasClone { get; set; }
2025-05-08 11:59:40 +08:00
/// <summary>
/// 原始场景路径
/// </summary>
private string OriginAssetPath => AssetDatabase.GetAssetPath(AssetToPostProcess);
2024-01-16 18:37:02 +08:00
2025-05-08 11:59:40 +08:00
protected PostProcessInstructor _processInstructor;
2024-10-22 16:10:43 +08:00
2025-05-08 11:59:40 +08:00
private PostProcessInstructor _clonedProcessInstructor;
2024-01-16 18:37:02 +08:00
2024-01-15 20:25:49 +08:00
private PostProcessInstructor PostProcessInstructor => HasClone ? _clonedProcessInstructor : _processInstructor;
2025-05-08 11:59:40 +08:00
/// <summary>
/// 用于处理后处理场景中的预制体
/// </summary>
private Transform _unpackedCombinedObjectsRoot;
2025-04-18 14:04:30 +08:00
2024-01-17 13:44:26 +08:00
private Transform CombinedObjectsRoot
2024-01-15 20:25:49 +08:00
{
get
{
2025-04-18 14:04:30 +08:00
if (_unpackedCombinedObjectsRoot != null && HasClone)
return _unpackedCombinedObjectsRoot;
2024-01-17 13:44:26 +08:00
if (PostProcessInstructor == null || PostProcessInstructor.combinedObjectsRoot == null)
2024-01-15 20:25:49 +08:00
{
2025-04-07 14:18:07 +08:00
Debug.LogError("找不到Art节点!");
2024-01-15 20:25:49 +08:00
return PostProcessInstructor.transform.parent;
}
2024-01-17 13:44:26 +08:00
return PostProcessInstructor.combinedObjectsRoot;
2024-01-15 20:25:49 +08:00
}
}
2025-05-08 11:59:40 +08:00
protected abstract PostProcessInstructor Clone();
2024-09-24 16:57:21 +08:00
2025-05-08 11:59:40 +08:00
protected abstract void AfterAll(bool destroyAfterPostProcess);
2024-01-15 20:25:49 +08:00
protected virtual void Init(PostProcessInstructor postProcessInstructor)
{
_processInstructor = postProcessInstructor;
}
2025-05-08 11:59:40 +08:00
public static PostProcessInstructor FindInstructorInScene(Scene scene)
{
var instructors = Object.FindObjectsOfType<PostProcessInstructor>();
return instructors.FirstOrDefault(pi => pi.gameObject.scene == scene);
}
2025-06-16 17:25:12 +08:00
#region 后处理多节点
/// <summary>
/// 后处理多节点场景 不烘焙 预制体不解包
/// </summary>
/// <param name="postProcessInstructors"></param>
/// <param name="destroyAfterPostProcess"></param>
public void PostProcessMore(PostProcessInstructor[] postProcessInstructors, bool destroyAfterPostProcess = false)
{
if (postProcessInstructors.Length <= 0)
return;
var firstPostProcessInstructor = postProcessInstructors[0];
if (!CheckPostProcessInstructor(firstPostProcessInstructor))
return;
Init(firstPostProcessInstructor);
HasClone = false;
EditorSceneManager.SaveOpenScenes();
// 创建文件夹
AssetDatabase.DeleteAsset(ProcessedResourceDir);
AssetDatabase.CreateFolder(ResourcesBaseDir, PostProcessFolderName);
AssetDatabase.CreateFolder(ProcessedResourceDir, GROUND_TEXTURE_MAT_PATH);
// 复制场景为后处理场景
Clone();
// 在后处理场景中重新获取 PostProcessInstructor 组
var newPostProcessInstructors = Object.FindObjectsOfType<PostProcessInstructor>();
var index = 0;
2025-06-16 17:25:12 +08:00
foreach (var postProcessInstructor in newPostProcessInstructors)
{
// DebugUtil.LogError($"重新获取的postProcessInstructor属于场景{postProcessInstructor.gameObject.scene.name}");
_processInstructor = postProcessInstructor;
if (PostProcessInstructor == null)
{
// DebugUtil.LogError($"PostProcessInstructor为空克隆参数{HasClone}");
continue;
}
var outputPath = SCENE_COMBINED_NAME + index++;
2025-06-16 17:25:12 +08:00
BakeCombinedGameObject(outputPath);
if (!PostProcessInstructor.enableSplitGround)
{
// 关闭切割地面 给地面添加BoxCollider
GroundAddBoxCollider();
ChangeMapTextureAndMatPath();
}
else
{
SplitGroundTexture();
}
SetFogPosition();
RemoveRedundant();
HideCamera();
DestroyUselessObject();
}
AfterAll(destroyAfterPostProcess);
PostProcessData.EditorInstance.AddPostProcessData(AssetToPostProcess, OutputAssetPath);
Debug.Log($"执行后处理成功,后处理资源源路径:{OriginAssetPath} 后处理后路径:{OutputAssetPath}");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
#endregion
#region 普通后处理
2025-05-08 11:59:40 +08:00
/// <summary>
/// 后处理
/// </summary>
/// <param name="postProcessInstructor"></param>
/// <param name="destroyAfterPostProcess"></param>
/// <param name="defaultCameraParam">是否为默认相机</param>
2025-04-07 18:55:27 +08:00
public void PostProcess(PostProcessInstructor postProcessInstructor, bool destroyAfterPostProcess = false,
bool defaultCameraParam = true)
2024-01-15 20:25:49 +08:00
{
if (!CheckPostProcessInstructor(postProcessInstructor))
return;
2025-06-16 17:25:12 +08:00
2024-01-15 20:25:49 +08:00
Init(postProcessInstructor);
HasClone = false;
EditorSceneManager.SaveOpenScenes();
PrepareFolders();
2025-04-15 16:33:01 +08:00
2025-05-08 11:59:40 +08:00
// 复制 ProcessInstructor 组件
2024-01-15 20:25:49 +08:00
_clonedProcessInstructor = Clone();
2024-01-16 14:23:05 +08:00
HasClone = true;
2024-01-15 20:25:49 +08:00
if (_clonedProcessInstructor == null)
{
Debug.LogError("_clonedProcessInstructor is null!");
return;
}
2025-04-15 16:33:01 +08:00
2025-05-15 19:27:10 +08:00
var combineRootObj = BakeCombinedGameObject();
_PrepareForBake(combineRootObj.transform);
2025-06-16 17:25:12 +08:00
2025-05-08 11:59:40 +08:00
// 如果Art为预制体先进行解包
UnpackPostSceneArt();
2025-04-16 15:28:21 +08:00
2025-05-08 11:59:40 +08:00
if (!PostProcessInstructor.enableSplitGround)
{
// 关闭切割地面 给地面添加BoxCollider
GroundAddBoxCollider();
ChangeMapTextureAndMatPath();
}
else
{
SplitGroundTexture();
}
2025-04-16 15:28:21 +08:00
2025-05-08 11:59:40 +08:00
BakeLightmaps();
2025-04-18 16:33:53 +08:00
2024-01-15 20:25:49 +08:00
SetFogPosition();
2024-10-22 16:10:43 +08:00
if (!defaultCameraParam)
{
SetCameraParam();
}
2025-04-07 18:55:27 +08:00
2025-05-08 11:59:40 +08:00
UnpackPostSceneArt();
RemoveRedundant();
2025-05-20 13:02:09 +08:00
HideCamera();
2025-06-16 17:25:12 +08:00
2024-01-16 14:23:05 +08:00
DestroyUselessObject();
2024-01-15 20:25:49 +08:00
AfterAll(destroyAfterPostProcess);
2025-06-16 17:25:12 +08:00
PostProcessData.EditorInstance.AddPostProcessData(AssetToPostProcess, OutputAssetPath);
2024-01-16 18:37:02 +08:00
Debug.Log($"执行后处理成功,后处理资源源路径:{OriginAssetPath} 后处理后路径:{OutputAssetPath}");
2024-01-26 16:02:49 +08:00
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
2024-01-15 20:25:49 +08:00
}
2025-06-16 17:25:12 +08:00
#endregion
2025-05-15 19:27:10 +08:00
private void _PrepareForBake(Transform combineRootParent)
{
2025-05-20 13:02:09 +08:00
if (PostProcessInstructor == null || !PostProcessInstructor.enableLightmapBaking)
return;
2025-05-15 19:27:10 +08:00
for (var i = 0; i < combineRootParent.childCount; ++i)
{
var child = combineRootParent.GetChild(i);
if (child == null)
continue;
var meshRenderer = child.GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
continue;
}
2025-06-16 17:25:12 +08:00
2025-05-15 19:27:10 +08:00
if (meshRenderer.shadowCastingMode == ShadowCastingMode.On)
{
meshRenderer.shadowCastingMode = ShadowCastingMode.On;
meshRenderer.staticShadowCaster = true;
meshRenderer.material.doubleSidedGI = true;
}
}
}
2025-06-16 17:25:12 +08:00
2025-05-08 11:59:40 +08:00
private bool CheckPostProcessInstructor(PostProcessInstructor postProcessInstructor)
2024-01-15 20:25:49 +08:00
{
2025-05-08 11:59:40 +08:00
if (postProcessInstructor == null)
{
Debug.LogError("postProcessInstructor is null");
return false;
}
2024-01-15 20:25:49 +08:00
2025-05-08 11:59:40 +08:00
if (postProcessInstructor.processPrefab &&
(!PrefabUtility.IsPartOfAnyPrefab(postProcessInstructor) ||
EditorUtility.IsPersistent(postProcessInstructor)))
{
Debug.LogError("postProcessInstructor不在任何预制体内或者其不是预制体实例");
return false;
}
var currentScene = postProcessInstructor.gameObject.scene;
var objs = currentScene.GetRootGameObjects();
foreach (var obj in objs)
{
if (!sceneRoots.Contains(obj.name))
{
2025-04-25 15:07:22 +08:00
Debug.LogWarning($"{currentScene.name} 场景有其他节点:{obj.name},请检查节点规范");
2025-05-08 11:59:40 +08:00
}
}
return true;
}
2024-01-15 20:25:49 +08:00
private void PrepareFolders()
{
AssetDatabase.DeleteAsset(ProcessedResourceDir);
2024-01-16 14:23:05 +08:00
AssetDatabase.CreateFolder(ResourcesBaseDir, PostProcessFolderName);
2024-01-15 20:25:49 +08:00
AssetDatabase.CreateFolder(ProcessedResourceDir, SCENE_COMBINED_NAME);
2025-05-08 11:59:40 +08:00
AssetDatabase.CreateFolder(ProcessedResourceDir, GROUND_TEXTURE_MAT_PATH);
2024-01-15 20:25:49 +08:00
}
2025-05-08 11:59:40 +08:00
/// <summary>
/// 合并网格、贴图
/// </summary>
2025-06-16 17:25:12 +08:00
private GameObject BakeCombinedGameObject(string combinedName = "")
2024-01-15 20:25:49 +08:00
{
2024-01-17 13:44:26 +08:00
var art = CombinedObjectsRoot;
2025-06-16 17:25:12 +08:00
var combinedRootName = string.IsNullOrEmpty(combinedName) ? SCENE_COMBINED_NAME : combinedName;
var outputPath = $"{ProcessedResourceDir}/{combinedRootName}";
2025-04-15 16:33:01 +08:00
2025-04-07 14:18:07 +08:00
// 收集渲染器
2025-04-25 15:07:22 +08:00
var renderers = MeshCombineUtils.CollectRenderers(PostProcessInstructor.rootsToCombine);
2025-04-07 14:18:07 +08:00
Debug.Log($"合批前收集到 {renderers.Count} 个渲染器");
2025-04-15 16:33:01 +08:00
2025-04-07 14:18:07 +08:00
var prefix = GetScenePrefix();
2024-01-15 20:25:49 +08:00
var combinedRoot = new GameObject("CombinedRoot");
combinedRoot.transform.parent = art.transform;
2025-06-16 17:25:12 +08:00
DebugUtil.Log($"合并节点是:{GameObjectUtils.GetFullPath(combinedRoot)},输出路径:{outputPath}" +
$"单位贴图尺寸:{(int)PostProcessInstructor.postProcessTextureUnitSize}");
2025-04-07 14:18:07 +08:00
try
2025-04-01 16:59:45 +08:00
{
2025-04-07 14:18:07 +08:00
if (PostProcessInstructor.enableBatchGrouping)
{
// 按照距离对渲染器进行分组
2025-04-07 18:55:27 +08:00
Dictionary<string, List<Renderer>> rendererGroups =
2025-05-14 16:34:24 +08:00
MeshCombineUtils.GroupRenderersByProximity(renderers, PostProcessInstructor.batchGroupDistance);
2025-04-07 14:18:07 +08:00
SceneCombineUtil.Instance.CombineGameObjectsByGroups(rendererGroups, combinedRoot.transform,
2025-06-16 17:25:12 +08:00
outputPath,
2025-04-07 14:18:07 +08:00
(int)PostProcessInstructor.postProcessTextureUnitSize,
PostProcessInstructor.sampleMaterials, prefix);
}
else
{
// 使用原有的合批方式
2025-06-16 17:25:12 +08:00
SceneCombineUtil.Instance.CombineGameObjects(renderers, combinedRoot.transform, outputPath,
2025-04-07 14:18:07 +08:00
(int)PostProcessInstructor.postProcessTextureUnitSize,
PostProcessInstructor.sampleMaterials, prefix);
}
2025-04-15 16:33:01 +08:00
2025-04-07 14:18:07 +08:00
// 如果是剧情场景,重命名生成的所有物体添加前缀
if (!string.IsNullOrEmpty(prefix))
{
var combined = combinedRoot.GetComponentsInChildren<Transform>();
foreach (var trans in combined)
{
if (trans != combinedRoot.transform && !trans.name.StartsWith(prefix))
{
trans.name = prefix + trans.name;
}
}
}
2025-04-18 14:04:30 +08:00
foreach (var root in PostProcessInstructor.rootsToCombine)
2025-04-07 14:18:07 +08:00
{
2025-04-18 14:04:30 +08:00
if (!root)
2025-04-07 14:18:07 +08:00
{
2025-04-18 14:04:30 +08:00
continue;
2025-04-07 14:18:07 +08:00
}
2025-04-18 14:04:30 +08:00
Object.DestroyImmediate(root.gameObject);
2025-04-07 14:18:07 +08:00
}
2025-04-01 16:59:45 +08:00
}
2025-04-07 14:18:07 +08:00
catch (System.Exception ex)
2025-04-01 16:59:45 +08:00
{
2025-04-07 14:18:07 +08:00
Debug.LogError($"合批过程中发生错误: {ex.Message}\n{ex.StackTrace}");
// 如果合批失败,保留原始物体
if (combinedRoot != null)
{
Object.DestroyImmediate(combinedRoot);
}
}
2025-06-16 17:25:12 +08:00
2025-05-15 19:27:10 +08:00
return combinedRoot;
2025-04-07 14:18:07 +08:00
}
2025-04-25 15:07:22 +08:00
#region 地面处理
2025-04-15 16:33:01 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 修改地面贴图及材质的路径 用于打包
/// </summary>
private void ChangeMapTextureAndMatPath()
{
var ground = PostProcessInstructor.ground;
2025-04-25 15:07:22 +08:00
if (_unpackedCombinedObjectsRoot != null && HasClone)
2025-05-08 11:59:40 +08:00
{
2025-04-25 15:07:22 +08:00
ground = _unpackedCombinedObjectsRoot.Find("Ground")?.gameObject;
2025-05-08 11:59:40 +08:00
}
2025-06-16 17:25:12 +08:00
GroundUtils.ChangeMapTextureAndMatPath(ground, GroundSplitDir, GetScenePrefix(),
2025-04-25 15:07:22 +08:00
groundRoot, CombinedObjectsRoot, _unpackedCombinedObjectsRoot);
2025-05-08 11:59:40 +08:00
}
/// <summary>
/// 给地面添加BoxCollider
/// </summary>
2025-04-18 16:33:53 +08:00
private void GroundAddBoxCollider()
{
var ground = PostProcessInstructor.ground;
if (_unpackedCombinedObjectsRoot != null && HasClone)
{
2025-04-25 15:07:22 +08:00
ground = _unpackedCombinedObjectsRoot.Find("Ground")?.gameObject;
2025-04-18 16:33:53 +08:00
}
if (ground != null)
{
2025-06-16 17:25:12 +08:00
// DebugUtil.LogError("获取的地面节点全路径:" + GameObjectUtils.GetFullPath(ground));
2025-04-25 15:07:22 +08:00
SceneUtils.AddBoxColliderToGround(ground);
2025-04-18 16:33:53 +08:00
}
else
{
2025-06-16 17:25:12 +08:00
Debug.LogError("场景地面节点不存在无法添加BoxCollider");
2025-04-18 16:33:53 +08:00
}
// 移除下层地面的碰撞体
var ground_2 = GameObject.Find("Ground_2");
if (ground_2 != null)
{
var collider = ground_2.GetComponent<Collider>();
if (collider != null)
{
Object.DestroyImmediate(collider);
}
}
2025-04-18 16:33:53 +08:00
}
2025-05-08 11:59:40 +08:00
/// <summary>
/// 切割地面
/// </summary>
2024-01-15 20:25:49 +08:00
private void SplitGroundTexture()
{
var ground = PostProcessInstructor.ground;
if (ground == null)
return;
2025-04-15 16:33:01 +08:00
2025-06-16 17:25:12 +08:00
GroundUtils.SplitGroundTexture(ground, GroundSplitDir, GetScenePrefix(), GROUND_SPLIT_WIDTH,
GROUND_SPLIT_HEIGHT);
2024-01-15 20:25:49 +08:00
}
2025-04-08 14:17:55 +08:00
#endregion
2025-04-15 16:33:01 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 设置雾的位置
/// </summary>
2024-01-15 20:25:49 +08:00
private void SetFogPosition()
{
2025-04-25 15:07:22 +08:00
SceneUtils.SetFogPosition(PostProcessInstructor.fog);
2024-01-15 20:25:49 +08:00
}
2024-01-16 14:23:05 +08:00
2025-05-08 11:59:40 +08:00
/// <summary>
/// 销毁多余eventSystems
/// </summary>
private void RemoveRedundant()
{
2025-04-25 15:07:22 +08:00
SceneUtils.RemoveRedundantEventSystems(PostProcessInstructor.gameObject.scene);
}
2025-06-16 17:25:12 +08:00
2024-01-16 14:23:05 +08:00
private void DestroyUselessObject()
{
2024-01-17 13:44:26 +08:00
foreach (var root in PostProcessInstructor.rootsToCombine)
2024-01-16 14:23:05 +08:00
{
if (!root)
{
continue;
}
2024-10-22 16:10:43 +08:00
2024-01-16 14:23:05 +08:00
Object.DestroyImmediate(root.gameObject, true);
}
Object.DestroyImmediate(PostProcessInstructor.gameObject, true);
var designerObj = GameObject.Find("Designer");
if (designerObj != null)
{
Object.DestroyImmediate(designerObj, true);
}
2024-01-16 14:23:05 +08:00
}
2025-05-08 11:59:40 +08:00
/// <summary>
/// 检测是否为剧情场景
/// </summary>
/// <returns></returns>
private bool IsStoryScene()
{
2025-05-08 11:59:40 +08:00
var sceneName = PostProcessInstructor.gameObject.scene.name;
return sceneName.Contains(STORY_SCENE_PREFIX);
}
private string GetScenePrefix()
{
return IsStoryScene() ? STORY_SCENE_PREFIX : "";
}
2025-04-07 18:55:27 +08:00
2025-04-08 14:17:55 +08:00
#region 保存相机参数
private void SetCameraParam()
{
var postScene = PostProcessInstructor.gameObject.scene;
var scene = _processInstructor.gameObject.scene;
foreach (var rootObj in scene.GetRootGameObjects())
{
if (rootObj.CompareTag("MainCamera"))
{
CloneCameraToScene(rootObj, postScene);
break;
}
}
}
private void CloneCameraToScene(GameObject obj, Scene scene)
{
// 只更改transform
var oldPosition = obj.transform.position;
var oldRotation = obj.transform.rotation;
GameObject oldCamera = null;
foreach (var rootObj in scene.GetRootGameObjects())
{
if (rootObj.CompareTag("MainCamera"))
{
oldCamera = rootObj;
break;
}
}
if (oldCamera == null) return;
oldCamera.transform.position = oldPosition;
oldCamera.transform.rotation = oldRotation;
}
2025-05-20 13:02:09 +08:00
private void HideCamera()
{
var scene = PostProcessInstructor.gameObject.scene;
var cameras = Object.FindObjectsOfType<Camera>();
2025-06-16 17:25:12 +08:00
2025-05-20 13:02:09 +08:00
foreach (var camera in cameras)
{
if (camera.gameObject.scene == scene)
{
camera.gameObject.SetActive(false);
// Debug.Log($"已隐藏相机: {camera.gameObject.name}");
}
}
2025-06-16 17:25:12 +08:00
2025-05-20 18:34:26 +08:00
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
EditorSceneManager.SaveOpenScenes();
2025-05-20 13:02:09 +08:00
}
2025-04-08 14:17:55 +08:00
#endregion
#region 烘焙
/// <summary>
/// 烘焙灯光贴图的方法
/// </summary>
2025-04-07 18:55:27 +08:00
private void BakeLightmaps()
{
// 检查是否开启了烘焙选项
2025-04-16 15:28:21 +08:00
if (PostProcessInstructor == null || !PostProcessInstructor.enableLightmapBaking)
2025-04-07 18:55:27 +08:00
return;
2025-04-08 14:17:55 +08:00
2025-04-07 18:55:27 +08:00
Debug.Log("开始灯光烘焙过程...");
2025-04-18 16:33:53 +08:00
2025-04-17 19:25:12 +08:00
// 1. 从CombinedObjectsRoot下查找灯光 改为烘焙灯光
2025-04-25 15:07:22 +08:00
LightmapUtils.PrepareLight(CombinedObjectsRoot, realTimeLights, bakedLights);
2025-04-15 16:33:01 +08:00
2025-04-17 19:25:12 +08:00
// 2. 处理参与烘焙的节点
2025-06-16 17:25:12 +08:00
LightmapUtils.PreProcessBake(bakeReplaceShaderRoot, CombinedObjectsRoot, true, true, allBakeRenderers,
needReplaceRenderers);
LightmapUtils.PreProcessBake(groundRoot, CombinedObjectsRoot, false, false, allBakeRenderers,
needReplaceRenderers);
2025-04-17 19:25:12 +08:00
ProcessGround(3000);
2025-04-08 14:17:55 +08:00
2025-04-17 19:25:12 +08:00
Debug.Log($"总共收集到 {needReplaceRenderers.Count} 个渲染器需要替换shader");
Debug.Log($"总共收集到 {allBakeRenderers.Count} 个渲染器参与烘焙");
2025-04-08 14:17:55 +08:00
2025-04-18 14:04:30 +08:00
// 3.替换Shader为支持光照贴图的Shader
2025-04-25 15:07:22 +08:00
MaterialUtils.ReplaceShaderWithLightmapShader(needReplaceRenderers);
2025-04-08 14:17:55 +08:00
2025-04-18 14:04:30 +08:00
// 4. 开始烘焙
2025-04-25 15:07:22 +08:00
LightmapUtils.Bake(SceneManager.GetActiveScene());
2025-04-08 14:17:55 +08:00
2025-04-18 14:04:30 +08:00
// 5. 关闭所有烘焙物体的阴影投射
2025-04-17 19:25:12 +08:00
foreach (var renderer in allBakeRenderers)
2025-04-07 18:55:27 +08:00
{
2025-04-15 16:33:01 +08:00
if (renderer != null)
2025-04-16 15:28:21 +08:00
renderer.shadowCastingMode = ShadowCastingMode.Off;
2025-04-15 16:33:01 +08:00
}
2025-04-08 14:17:55 +08:00
2025-04-18 14:04:30 +08:00
// 6. 打开实时灯光
2025-04-25 15:07:22 +08:00
LightmapUtils.RevertLight(realTimeLights, bakedLights);
2025-04-16 15:28:21 +08:00
2025-04-18 14:04:30 +08:00
// 7.还原地面RenderQueue
2025-04-17 19:25:12 +08:00
ProcessGround(2000);
2025-04-08 14:17:55 +08:00
2025-04-18 14:04:30 +08:00
// 8. 复制光照烘焙文件到目标路径
2025-04-25 15:07:22 +08:00
LightmapUtils.CopyLightmapFiles(SceneManager.GetActiveScene(), LightBakeDir);
2025-04-08 14:17:55 +08:00
2025-04-18 14:04:30 +08:00
// 9. 保存场景
2025-04-25 15:07:22 +08:00
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
2025-04-07 18:55:27 +08:00
EditorSceneManager.SaveOpenScenes();
2025-04-08 14:17:55 +08:00
2025-04-07 18:55:27 +08:00
Debug.Log("灯光烘焙处理完成");
}
2025-04-17 19:25:12 +08:00
private void ProcessGround(int renderQueue)
{
if (PostProcessInstructor.ground != null)
{
2025-04-25 15:07:22 +08:00
SceneUtils.SetGroundRenderQueue(PostProcessInstructor.ground, renderQueue);
2025-04-17 19:25:12 +08:00
}
2025-04-16 15:28:21 +08:00
}
2025-04-18 14:04:30 +08:00
private void UnpackPostSceneArt()
{
2025-04-25 15:07:22 +08:00
if (CombinedObjectsRoot != null && PrefabUtility.IsPartOfPrefabInstance(CombinedObjectsRoot.gameObject))
2025-04-18 14:04:30 +08:00
{
// 保存对象的引用
_unpackedCombinedObjectsRoot = CombinedObjectsRoot;
2025-04-25 15:07:22 +08:00
SceneUtils.UnpackPrefab(CombinedObjectsRoot.gameObject);
2025-04-18 14:04:30 +08:00
}
}
2025-04-08 14:17:55 +08:00
#endregion
2024-01-15 20:25:49 +08:00
}