2022年8月

在要Unity Editor下查找一个资源,是否被其它预制(prefab)引用,AssetDatabase并没有给出现成的API,AssetDatabase只能查找一个游戏对象依赖了哪些资源,我们可以在启动的时候,使用AssetDatabase对每个资源建议反向索引,再进行查找,但是建议反向索引的过程还是比较耗时的,项目越大,资源越多,耗时越久。
这样的方式虽然能达到查找资源被依赖的目的,但是还不够高效,下面我们讲一下,在Mac系统下,使用系统索引的方式,快速进行资源被依赖的方法,可以在1秒内,找到资源的被依赖对象,因为Mac系统已经为文件建立好了索引,所以可以直接使用,以下是已经集成好的代码工具,可以拷贝到项目里直接使用,上代码:

using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class FindProject
{
#if UNITY_EDITOR_OSX
    private static string _curFileName;
    private static readonly List<string> References = new List<string>();

    private static bool _canOutResult;
    private static string _selectedAssetPath;
    
    [MenuItem("Assets/Find References In Project", false, 2000)]
    private static void FindProjectReferences()
    {
        var appDataPath = Application.dataPath;
        _selectedAssetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
        

        _curFileName = Path.GetFileName(_selectedAssetPath);

        var guid = AssetDatabase.AssetPathToGUID(_selectedAssetPath);

        var psi = new System.Diagnostics.ProcessStartInfo
        {
            WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized,
            FileName = "/usr/bin/mdfind",
            Arguments = "-onlyin " + Application.dataPath + " " + guid,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        };
        
        EditorApplication.update += OnUpdate;

        var process = new System.Diagnostics.Process();
        process.StartInfo = psi;

        process.OutputDataReceived += (sender, e) =>
        {

            if (string.IsNullOrEmpty(e.Data))
            {
                _canOutResult = true;
            }
            else
            {
                var fileName = Path.GetFileName(e.Data);

                if (fileName.Contains(_curFileName))
                {
                    return;
                }

                var relativePath = "Assets" + e.Data.Replace(appDataPath, "");
                References.Add(relativePath);
            }

        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (string.IsNullOrEmpty(e.Data))
                return;

            // output += "Error: " + e.Data + "\n";
        };
        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
    }
    
    private static void OnUpdate()
    {
        if (!_canOutResult) return;
        _canOutResult = false;
        
        var rawObj = AssetDatabase.LoadAssetAtPath<Object>(_selectedAssetPath);
        Debug.Log($"<color=aqua><b>{References.Count}</b></color> 个对象引用了 <color=fuchsia><b>{_curFileName}</b></color>", rawObj);
        
        foreach (var file in References)
        {
            var findObj = AssetDatabase.LoadAssetAtPath<Object>(file);
            Debug.Log( $"<color=lime>引用者:</color> <color=yellow>{file}</color>", findObj);
        }
    }

#endif
}

点击ESC进入“正常模式”,然后输入“:”,进入“命令模式”。此时屏幕的下方会出现一个冒号,你可以输入以下命令,并按“ENTER”执行:

:q ,退出(:quit的缩写)

:q!,退出且不保存(:quit!的缩写)

:wq,保存并退出

:wq!,保存并退出即使文件没有写入权限(强制保存退出)

:x,保存并退出(类似:wq,但是只有在有更改的情况下才保存)

:exit,保存并退出(和:x相同)

:qa,退出所有(:quitall的缩写)

:cq,退出且不保存(即便有错误)

你也可以直接在“正常模式”下输入“ZZ”来保存并退出Vim(和:x相同),或者“ZQ”不保存并退出(和:q!相同)注意此处ZZ大写和小写是完全不同的。

Vim还有一个帮助菜单,可以通过“:help”调出来,基本能够解决你的绝大多数问题。

Vim常用命令


1.移动光标

  • j:向下
  • 20j: 向下移动 20 行
  • k:向上
  • h:向左
  • l:向右
  • 0:到行首
  • ^:到行首第一个字符,如果前面有空格的话
  • $:到行尾
  • gg:快速到文件头
  • G:快速到文件尾
  • 50G:跳转到第 50 行

    请不要在插入模式进行光标移动,效率很低下。

2.复制

  • yy:复制一行
  • 8yy:向下复制8行
  • yw:复制光标开始的一个单词
  • y$:复制光标到行尾
  • yfA:复制光标到第一个大写A中间的内容
  • y2fA:复制光标到第二个大写A中间的内容

3.剪切

  • x:向后剪切一个一个字符,如果是在行尾,则为向前剪切
  • 4x:剪切4个
  • xp:非行尾交换两个字符,如从bs变成sb

4.删除

  • dd:删除一行
  • 100dd:删除100行
  • dw:删除一个单词
  • df":删除到出现的第一个双引号
  • d^:删除至行首
删除的内容会放到剪贴板,按p即可粘贴到其他地方。

5.粘贴

  • p:粘贴复制或剪切的内容
  • 5p:将复制或剪切的内容粘贴5次

6.替换和撤销

  • r+<待替换字母>:将游标所在字母替换为指定字母
  • R:连续替换,直到按下Esc
  • cc:替换整行,即删除游标所在行,并进入插入模式
  • cw:替换一个单词,即删除一个单词,并进入插入模式
  • u{n}:撤销一次或n次操作
  • U(大写):撤销当前行的所有修改
  • Ctrl+r:redo,即撤销undo的操作

7.退出编辑器

  • wq:保存当前文件并退出
  • wqa:保存所有文件并退出
  • q!: 不保存,强制退出
  • qa!: 有多个文件被打开,同时退出

以下命令请在命令模式下执行

在普通模式下,输入:即可进入。

调整文本

  • %s/$/sth/ :在行尾追加sth
  • %s/^M//g :替换掉dos换行符,^M使用ctrl+v + Enter即可输入
  • :g/^\s$/d* :删除空行以及只有空格的行
  • %s/#.*//g :删除#之后的字符
没错,这里使用的是正则。
  • ce:使本行文本内容居中
  • ri:使本行文本内容靠右
  • le:使本行文本内容靠左

查找字符串

在普通模式下,按下/直接进入查找,输入相应的字符串按确定即可

  • n:查找下一个匹配
  • N:查找上一个匹配
  • 2n:查找下面第二个匹配

在Unity里,矩阵的作用是对向量进行变换,主要的变换有三种形式,旋转、平移、缩放,以下为主要的几种矩阵的具体公式:

旋转矩阵

​ 2D坐标旋转矩阵

$$ M = \left[ \begin{matrix} \cos\theta & \sin\theta \\ -\sin\theta & \cos\theta \end{matrix} \right] $$

​ 具体计算

$$ \left[ \begin{matrix} x & y \end{matrix} \right] \times \left[ \begin{matrix} \cos\theta & \sin\theta \\ -\sin\theta & \cos\theta \end{matrix} \right] = \left[ \begin{matrix} x\times\cos\theta - y\times\sin\theta & x\sin\theta + y\times\cos\theta \end{matrix} \right] $$

​ 3D坐标旋转矩阵
​ 绕x轴旋转:

$$ \left[ \begin{matrix} 1 & 0 & 0\\ 0 & \cos\theta & \sin\theta\\ 0 & -\sin\theta & \cos\theta \end{matrix} \right] $$

   绕y轴旋转:

$$ \left[ \begin{matrix} \cos\theta & 0 & \sin\theta\\ 0 & 1 & 0\\ -\sin\theta & 0 & \cos\theta \end{matrix} \right] $$

   绕z轴旋转:

$$ \left[ \begin{matrix} \cos\theta & \sin\theta & 0 \\ -\sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{matrix} \right] $$

​ 具体计算与2D相同,具体思想:
​ 绕x旋转,x不变,用矩阵改变y,z的坐标;
​ 绕y旋转,y不变,用矩阵改变x,z的坐标;
​ 绕z旋转,z不变,用矩阵改变x,y的坐标;

平移矩阵

​ 2D平移矩阵

$$ \left[ \begin{matrix} 1 & 0 & 0\\ 0 & 1 & 0\\ d_x & d_y & 1 \end{matrix} \right] $$

​ (d_x 为 x方向增量,d_y 为 y方向增量)

​ 具体计算

$$ \left[ \begin{matrix} x & y & 1\\ \end{matrix} \right] \times \left[ \begin{matrix} 1 & 0 & 0\\ 0 & 1 & 0\\ d_x & d_y & 1 \end{matrix} \right] = \left[ \begin{matrix} x+d_x & y+d_y & 1\\ \end{matrix} \right] $$

​ 计算结果与分别在x、y坐标上增加增量一致

​ 3D平移矩阵

$$ \left[ \begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ d_x & d_y & d_z & 1\\ \end{matrix} \right] $$

​ (d_x 为 x方向增量,d_y 为 y方向增量,d_z 为 z方向增量)
​ 计算方式与2D相同,不再赘述

投影矩阵

$$ \left[ \begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & \frac{1}{d}\\ 0 & 0 & 0 & 0 \end{matrix} \right] $$

​ 计算

$$ \left[ \begin{matrix} x & y & z & 1 \end{matrix} \right] \times \left[ \begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & \frac{1}{d}\\ 0 & 0 & 0 & 0 \end{matrix} \right] = \left[ \begin{matrix} x & y & z & \frac{z}{d} \end{matrix} \right] $$

​ d是摄像机到视椎体前平面的距离,最终的x、y需要除以第4个分量,得到最终值

缩放矩阵

$$ \left[ \begin{matrix} s_x & 0 & 0 & 0\\ 0 & s_y & 0 & 0\\ 0 & 0 & s_z & 0\\ 0 & 0 & 0 & 1 \end{matrix} \right] $$

​ 缩放矩阵具体计算

$$ \left[ \begin{matrix} x & y & z & 1 \end{matrix} \right] \times \left[ \begin{matrix} s_x & 0 & 0 & 0\\ 0 & s_y & 0 & 0\\ 0 & 0 & s_z & 0\\ 0 & 0 & 0 & 1 \end{matrix} \right] = \left[ \begin{matrix} xs_x & ys_y & zs_z & 1 \end{matrix} \right] $$

​ 矩阵的效果可以通过相乘进行叠加,比如把平移和旋转的矩阵相乘,得到的新矩阵,就同时具有这两个功能,也可以多个矩阵相乘

$$ \left[ \begin{matrix} \cos\theta & 0 & \sin\theta & 0\\ 0 & 1 & 0 & 0\\ -\sin\theta & 0 & \cos\theta & 0\\ 0 & 0 & 0 & 1 \end{matrix} \right] \times \left[ \begin{matrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ d_x & d_y & d_z & 1\\ \end{matrix} \right] = \left[ \begin{matrix} \cos\theta & 0 & \sin\theta & 0\\ 0 & 1 & 0 & 0\\ -\sin\theta & 0 & \cos\theta & 0\\ d_x & d_y & d_z & 1 \end{matrix} \right] $$

  1. 余弦定理:
    对于任意三角形,任何一边的平方等于其他两边平方的和减去这两边与它们夹角的余弦的积的两倍。

ta.png

$$ c^2 = a^2 + b^2 - 2ab\cos\gamma $$

余弦定理,可以用来推导向量的点积

  1. 向量的点积(点乘)公式:

$$ a\cdot b = (a_x,a_y,a_z)\cdot(b_x,b_y,b_z) = a_xb_x + a_yb_y + a_zb_z $$

点积的几何意义为b向量在a向量方向上的投影

image-20220118144358911.png

点积的结果是一个标量,两个向量的夹角小于90度,结果为正,等于90度,结果为0,大于90度,结果为负;可以用计算结果来判断两个向量的方向的一致性;

image-20220118144852067.png

  1. 向量的叉乘公式

    $$ a \times\ b = (a_x, a_y, a_z) \times\ (b_x, b_y, b_z) = (a_yb_z - a_zb_y,a_zb_x - a_xb_z,a_xb_y - a_yb_x) $$

叉乘不满足交换律,即 a×b ≠ b×a,但满足反交换律 a×b = −(b×a),叉乘也不满足结合律,即 (a×b) ×c ≠ a×(b×c)

原公式比较复杂,不容易记,可以用行列式的方式速记,或掐头去尾的方式速记;

$$ a \times\ b = \begin{vmatrix}i & j & k\\ a_x & a_y & a_z\\ b_x & b_y & b_z \end{vmatrix} = \begin {vmatrix} a_y & a_z \\ b_y & b_z \end{vmatrix}i + \begin {vmatrix} a_x & a_z \\ b_x & b_z \end{vmatrix}j + \begin {vmatrix} a_x & a_y \\ b_x & b_y \end{vmatrix}k $$

计算顺序为 y -- z -- x;

《掐头去尾法》:把向量的行列式水平写两遍,再掐头去尾去掉首列和尾列,之后,从左到右交叉相乘即可,如下

$$ a \times\ b = \begin{vmatrix}a_x & a_y & a_z & a_x & a_y & a_z\\ b_x & b_y & b_z &b_x & b_y & b_z \end{vmatrix} = \begin{vmatrix}a_y & a_z & a_x & a_y\\ b_y & b_z &b_x & b_y \end{vmatrix} = \begin{vmatrix}a_y & a_z\\ b_y & b_z\end{vmatrix} + \begin{vmatrix}a_z & a_x\\ b_z &b_x \end{vmatrix} + \begin{vmatrix}a_x & a_y\\ b_x & b_y \end{vmatrix} $$

叉乘结果是一个向量,向量的方向与做叉乘的两个向量同时垂直,也就是a、b两个向量所在平面的法线