using System.Collections.Generic;
using System.IO;
using PhxhSDK;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEngine.Rendering;
using UnityEditorGameObjectUtility = UnityEditor.GameObjectUtility;
///
/// 灯光烘焙工具类
///
public static class LightmapUtils
{
///
/// 处理参与烘焙的节点
///
public static void PreProcessBake(List rootNames, Transform rootTransform, bool castShadow, bool needReplaceShader,
List allBakeRenderers, List needReplaceRenderers)
{
foreach (var rootName in rootNames)
{
var rootObj = rootTransform.FindChildRecursive(rootName);
if (rootObj != null)
{
SceneUtils.SetStaticFlagsRecursive(rootObj.gameObject, StaticEditorFlags.ContributeGI);
var renderers = rootObj.GetComponentsInChildren(true);
if (renderers != null && renderers.Length > 0)
{
Debug.Log($"从{rootName}收集到 {renderers.Length} 个渲染器用于烘焙");
foreach (var renderer in renderers)
{
Debug.Log($"处理从{rootName}收集到物体{renderer.gameObject.name}的渲染器");
if (renderer.receiveShadows)
{
renderer.shadowCastingMode = castShadow ? ShadowCastingMode.On : ShadowCastingMode.Off;
allBakeRenderers.Add(renderer);
if (needReplaceShader)
needReplaceRenderers.Add(renderer);
}
}
}
else
{
Debug.Log($"从{rootName}收集不到渲染器");
}
}
}
}
///
/// 准备灯光:将实时灯光改为烘焙灯光
///
public static void PrepareLight(Transform root, List realTimeLights, List bakedLights)
{
var lights = root.GetComponentsInChildren();
foreach (var light in lights)
{
light.transform.position = new Vector3(0, 0, 0);
// 复制灯光对象
var bakeLightObj = Object.Instantiate(light.gameObject, light.transform.parent);
var bakeLight = bakeLightObj.GetComponent();
// 设置为烘焙模式
bakeLightObj.name = light.name + "_Bake";
bakeLight.lightmapBakeType = LightmapBakeType.Baked;
// 取消实时灯光的static
UnityEditorGameObjectUtility.SetStaticEditorFlags(light.gameObject, 0);
// 设置烘焙灯光的static
UnityEditorGameObjectUtility.SetStaticEditorFlags(bakeLightObj, StaticEditorFlags.ContributeGI);
// 添加到列表
bakedLights.Add(bakeLight);
realTimeLights.Add(light);
}
// 关闭实时灯光
foreach (var realTimeLight in realTimeLights)
{
if (realTimeLight != null)
realTimeLight.gameObject.SetActive(false);
}
// 开启烘焙灯光
foreach (var bakeLight in bakedLights)
{
if (bakeLight != null)
bakeLight.gameObject.SetActive(true);
}
}
///
/// 恢复实时灯光
///
public static void RevertLight(List realTimeLights, List bakedLights)
{
// 开启实时灯光
foreach (var realTimeLight in realTimeLights)
{
if (realTimeLight != null)
realTimeLight.gameObject.SetActive(true);
}
Debug.Log($"销毁{bakedLights.Count}个烘焙灯光");
// 销毁烘焙灯光
foreach (var bakeLight in bakedLights)
{
if (bakeLight != null)
Object.DestroyImmediate(bakeLight.gameObject);
}
}
///
/// 执行烘焙
///
public static void Bake(Scene activeScene)
{
// 设置烘焙参数并开始烘焙
var lightingSettings = new LightingSettings();
Debug.Log($"烘焙时 场景是{activeScene.name}");
if (Lightmapping.TryGetLightingSettings(out var existingSettings))
{
lightingSettings = existingSettings;
}
else
{
lightingSettings.name = $"{activeScene.name}_LightingSettings";
AssetDatabase.CreateAsset(lightingSettings, $"Assets/{lightingSettings.name}.asset");
Lightmapping.lightingSettings = lightingSettings;
}
// 设置烘焙参数
lightingSettings.mixedBakeMode = MixedLightingMode.Subtractive;
lightingSettings.lightmapper = LightingSettings.Lightmapper.ProgressiveGPU;
lightingSettings.directSampleCount = 1;
lightingSettings.indirectSampleCount = 1;
lightingSettings.environmentSampleCount = 1;
lightingSettings.lightProbeSampleCountMultiplier = 8;
lightingSettings.maxBounces = 1;
lightingSettings.filteringMode = LightingSettings.FilterMode.Auto;
lightingSettings.lightmapResolution = 40;
lightingSettings.lightmapPadding = 2;
lightingSettings.lightmapMaxSize = 1024;
lightingSettings.lightmapCompression = LightmapCompression.HighQuality;
lightingSettings.indirectScale = 1;
lightingSettings.directionalityMode = LightmapsMode.NonDirectional;
Lightmapping.lightingSettings = lightingSettings;
// 强制场景保存以确保设置生效
EditorSceneManager.MarkSceneDirty(activeScene);
EditorSceneManager.SaveOpenScenes();
Debug.Log("开始烘焙灯光...");
Lightmapping.Bake();
Debug.Log("灯光烘焙完成");
}
///
/// 移动光照烘焙相关文件到指定目录
///
public static void CopyLightmapFiles(Scene scene, string lightmapDirPath)
{
string sceneName = scene.name;
Debug.Log("开始移动光照烘焙文件...");
try
{
// 确保目标目录存在
string lightmapDirAssetPath = SceneUtils.GetAssetPath(lightmapDirPath);
if (!AssetDatabase.IsValidFolder(lightmapDirAssetPath))
{
// 创建父目录结构
string[] folders = lightmapDirAssetPath.Split('/');
string currentPath = folders[0]; // Assets
for (int i = 1; i < folders.Length; i++)
{
string folderName = folders[i];
string parentPath = currentPath;
currentPath = $"{currentPath}/{folderName}";
if (!AssetDatabase.IsValidFolder(currentPath))
{
AssetDatabase.CreateFolder(parentPath, folderName);
}
}
AssetDatabase.Refresh();
}
// 1. 移动LightingSettings.asset文件
string lightingSettingsPath = $"Assets/{sceneName}_LightingSettings.asset";
if (AssetDatabase.LoadAssetAtPath