文章目录
- 吐槽
- 开启 Log Shader Compilation
- 实践
- 资源准备
- Build AB
- Testing Script
- Shader Compiled Log
- Project
吐槽
先说一下,最近几天前,纷纷看到 unity install fee 的天才收费方案
真的忍不住吐槽,我只想说: “no zuo no die”
(吃相太难看了)
开启 Log Shader Compilation
如果要做变体优化,或是 Shader.CreateGPUProgram 的 CPU 卡顿优化
都可以使用 Shader Compiled Log,只要在开启:Project Settings/Graphics/Shader Loading/Log Shader Compilation 即可
这样的话,就可以真机上查看编译情况,每个以 Compiled Log 都是对应 Shader.CreateGPUProgram,因此如果要做: 变体优化,变体预热,都是一个比较好的调试Log
实践
资源准备
顺便编写简单的 shader,创建 material,创建 prefab
设置 AB 信息,build AB
如下
Build AB
// jave.lin : 测试 打 AB
using System.IO;
using UnityEditor;
using UnityEngine;
public class TestingBuildAB : MonoBehaviour
{
[MenuItem("实用工具/BuildAB")]
public static void Build()
{
var curBuildTarget = EditorUserBuildSettings.activeBuildTarget;
var outputPath = $"{curBuildTarget}/ABs";
try
{
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
BuildPipeline.BuildAssetBundles(
outputPath,
BuildAssetBundleOptions.ChunkBasedCompression
| BuildAssetBundleOptions.DeterministicAssetBundle,
curBuildTarget);
EditorUtility.DisplayDialog("Build ABs Result", $"Build {outputPath} Successfully!", "OK");
}
catch (System.Exception er)
{
Debug.LogError(er);
EditorUtility.DisplayDialog("Build ABs Result", $"Build {outputPath} Failure! See Console Plz.", "OK");
}
}
}
Testing Script
// jave.lin : 测试 ab loading & unloading
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestingScript : MonoBehaviour
{
private Dictionary<string, AssetBundle> loaded_AB_Dict = new Dictionary<string, AssetBundle>();
private Dictionary<string, bool> isLoadByMajor_Dict = new Dictionary<string, bool>();
private AssetBundleManifest manifest;
private bool isLoadedManifest;
private AssetBundleManifest GetManifest(string platform = "Android")
{
if (manifest == null)
{
var buildTarget = platform;
var projectPath = Application.dataPath.Replace("/Assets", "");
var platformABPath = $"{projectPath}/{buildTarget}/ABs";
var manifest_bundle = AssetBundle.LoadFromFile($"{platformABPath}/ABs");
manifest = manifest_bundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
//Debug.Log($"loaded manifest : {platformABPath}, manifest : {manifest}");
}
return manifest;
}
private AssetBundle LoadAB(string abName, bool isMajorAB)
{
///*
//shader.ab // all shader
//* common.svc
//* height_fog.svc
//* gi.svc
//* xxx.svc
// *
// */
//AssetBundle ab = AssetBundle.LoadFromFile("shaders.ab");
1. 游戏通用 shader warmup (可能会卡顿,因为编译时间长),注意: 一般不用 warmup
//ab.LoadAsset<ShaderVariantCollection>("common.svc").WarmUp(); // 一般不用 warmup
2. 进入一些需要 height fog 的场景
//ab.LoadAsset<ShaderVariantCollection>("height_fog.svc").WarmUp();
3. 进入一些【不】需要 height fog,但需要 gi 的场景,但是这块管理很有风险,我记得 unity 的 shader一旦 Shader.Find 不到会导致闪退
//GameObject.Destroy(ab.LoadAsset<Shader>("height_fog1.shader"));
//GameObject.Destroy(ab.LoadAsset<Shader>("height_fog2.shader"));
//ab.LoadAsset<ShaderVariantCollection>("gi.svc").WarmUp();
4. 再次进入需要 height fog ,不需要 gi的场景
//GameObject.Destroy(ab.LoadAsset<Shader>("gi.shader"));
//ab.LoadAsset<Shader>("height_fog1.shader"); // 之前 destroy ,现在重现 load 回来
//ab.LoadAsset<Shader>("height_fog2.shader"); // 之前 destroy ,现在重现 load 回来
//ab.LoadAsset<ShaderVariantCollection>("height_fog.svc").WarmUp();
var buildTarget = "Android";
//Debug.Log($"Application.dataPath : {Application.dataPath}"); // Application.dataPath : E:/WorkFiles/UnityStudies/Testing_AB_Load_Unload/Assets
var projectPath = Application.dataPath.Replace("/Assets", "");
//Debug.Log($"projectPath : {projectPath}"); // projectPath : E:/WorkFiles/UnityStudies/Testing_AB_Load_Unload
var platformABPath = $"{projectPath}/{buildTarget}/ABs";
//Debug.Log($"platformABPath : {platformABPath}"); // projectPath : E:/WorkFiles/UnityStudies/Testing_AB_Load_Unload
var ps_ab_path = $"{platformABPath}/{abName.ToLower()}";
//Debug.Log($"ps_ab_path : {ps_ab_path}"); // ps_ab_path : e:/workfiles/unitystudies/testing_ab_load_unload/testingeffect_1
if (!loaded_AB_Dict.TryGetValue(abName, out var ab))
{
ab = AssetBundle.LoadFromFile(ps_ab_path);
loaded_AB_Dict.Add(abName, ab);
if (isMajorAB)
{
isLoadByMajor_Dict[abName] = isMajorAB;
}
Debug.Log($"loaded ab : {abName}");
}
return ab;
}
private bool UnLoadAB(string abName)
{
if (loaded_AB_Dict.TryGetValue(abName, out var ab))
{
ab.Unload(true);
loaded_AB_Dict.Remove(abName);
Debug.Log($"unload ab : {abName}");
return true;
}
return false;
}
private int instCount;
public void OnLoadPS_Btn()
{
//var manifest = GetManifest();
// load deps
var abNames = new string[]
{
"Assets/Textures/tex_1.png",
"Assets/Textures/tex_2.png",
"Assets/Materials/ps_mat_1.mat",
"Assets/Materials/ps_mat_2.mat",
};
var isAnyChildABUnload = false;
foreach (var abName1 in abNames)
{
if (!loaded_AB_Dict.ContainsKey(abName1))
isAnyChildABUnload = true;
LoadAB(abName1, false);
}
// load main ab
var abName = "Assets/Effects/TestingEffect_1.prefab";
if (isAnyChildABUnload)
{
UnLoadAB(abName);
}
var ab = LoadAB(abName, true);
var prefab = ab.LoadAsset<GameObject>(abName.ToLower());
var inst = GameObject.Instantiate<GameObject>(prefab);
inst.transform.position = Vector3.zero + Vector3.up * (instCount++);
}
public void OnUnloadPS_Btn()
{
var abName = "Assets/Effects/TestingEffect_1.prefab";
UnLoadAB(abName);
}
public void OnUnloadMat_Btn()
{
var abName = "Assets/Materials/ps_mat_2.mat";
UnLoadAB(abName);
}
public void OnUnloadTex_Btn()
{
var abName = "Assets/Textures/tex_2.png";
UnLoadAB(abName);
}
public void OnLoadMat_Btn()
{
var abName = "Assets/Materials/ps_mat_2.mat";
LoadAB(abName, false);
}
}
Shader Compiled Log
Project
TestingShaderCompiledLog.rar
提取码:yv4d