更优雅地编写Unity Shader

前言

最近在自学Unity Shader,总免不了要不断地动手做实验嘛,那么问题来了,用什么编辑器来舒服地写这些shader代码呢~

据说真正的大神都是直接用notepad写的,当然不适合我这种弱鸡233

按理说,应该选择宇宙第一IDE Visual Studio是吧,嗯,应该是这样,然而。。

img01
怎么这么丑啦!!

VS插件

嗯,不要慌,百度一下找个插件好了,果不其然很多人吐槽VS写Unity的ShaderLab如何如何不便,然后顺利找到了一个插件

img02

作者博客

重启VS,看到效果了,好像还不错,带语法高亮和代码补全

img03

赶紧写一段代码压压惊~

不对。。为毛没有缩进啊(摔),每次敲回车,新的一行没有自动缩进,每行都要手动按一排的tab,不行不行,这个肯定受不了的。。

转战Sublime

看来得找另外的解决方案了,继续百度。。找到一个sublime的插件
不过我们写C#还是得用VS呀,还好C#提供了足够丰富的扩展接口,我们可以自定义指定类型的资产打开方式,在这里就是将.shader类型的资产打开过程截断,不让Unity启动默认编辑器,而是我们自己执行一段代码(启动sublime)

参考了这篇教程配置了下,基本上已经没啥问题了

img04

不过还是不太完美,比如当shader报错时,从unity的console里双击进去时不能定位到出错行的。
当然这个好办,把C#端的代码稍微改了一下,是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Filename: ShaderEditor.cs
// 把这个文件放到项目的Editor文件夹里就行了
using UnityEngine;
using UnityEditor;
using System;
using System.Diagnostics;

public static class ShaderEditor
{
/// <summary>
/// 编辑器中双击某Asset时调用
/// 会截断对.shader类型的处理
/// </summary>
/// <param name="instanceID">该Asset的instanceID</param>
/// <param name="line">行号,未指定时为-1</param>
/// <returns></returns>
[UnityEditor.Callbacks.OnOpenAsset(1)]
public static bool OnOpenAsset(int instanceID, int line)
{
string strFilePath = AssetDatabase.GetAssetPath(EditorUtility.InstanceIDToObject(instanceID));
string strFileName = System.IO.Directory.GetParent(Application.dataPath) + "/" + strFilePath;
if (strFileName.EndsWith(".shader"))
{
// 双击shader文件时
string strSublimeTextPath = Environment.GetEnvironmentVariable("SublimeText_Path");
if (strSublimeTextPath != null && strSublimeTextPath.Length > 0)
{
Process.Start(strSublimeTextPath, $"\"{strFileName}:{line}\"");
return true;
}
else
{
UnityEngine.Debug.Log("Not Found Enviroment Variable 'SublimeText_Path'.");

return false;
}
}
return false;
}
}

这样一来就可以直接定位到指定的行数啦~

仍然不够完美。。

不过这个sublime插件也有点小问题,比如CGPROGRAMENDCG不能很好地匹配,不过暂时我的shader都是只有一个SubShader一个Pass的,最后几行不舒服就先算了,看看之后能不能解决