1.Component的复制黏贴
等同于Inspector窗口下的Copy Component,Paste Component Values,Paste Component As New
#if UNITY_EDITOR
//首先复制需要复制的组件
UnityEditorInternal.ComponentUtility.CopyComponent(needCopyComponent);
//粘贴组件的值到另一个组件上
UnityEditorInternal.ComponentUtility.PasteComponentValues(newComponent);
//为GameObject添加复制的组件
UnityEditorInternal.ComponentUtility.PasteComponentAsNew(gameObject);
#endif
2.组件删除
//Running模式下
Destroy(component);
//Editor模式下
DestroyImmediate(component);
3.Editor模式下执行脚本的Update或OnGUI 方法
有时为了帮助策划搞一下编辑工具,需要在Editor模式下,自动帮其做些操作,要在Update下进行检测。在类的定义前添加ExecuteInEditMode标签即可。
[ExecuteInEditMode]
public class TestComponent : MonoBehaviour
{
}
4.弧度与角度的转换
Mathf.Sin(float),Mathf.Cos(float)这些正弦余弦的方法中,参数的单位是弧度而不是角度。
弧度:弧长等于半径的弧,其所对的圆心角为1弧度,单位缩写是rad。(半径为r的圆,当某个角度α的弧长为r,那么角度α即为一弧长)
根据定义我们可以知道,圆的周长为2πr,对应360°,即360°=2πr,180°=πr。1rad对应弧长r,可以得出,1rad=180°÷π≈57.295°反过来,1°≈0.01745rad
在Mathf中有两个变量用于转换
Mathf.Deg2Rad = 0.0174532924F;//角度转弧度
Mathf.Rad2Deg = 57.29578F;//弧度转角度
所以如果我们要求sin30°,写法应该为
Mathf.Sin(30 * Mathf.Deg2Rad);
5.Vector3.ProjectOnPlane
Vector3.ProjectOnPlane(Vector3 vector, Vector3 planeNormal);将向量vector投影到法向量为planeNormal的平面上。
例如你有个向量Vector3 v = new Vector3(x, y, z); 你想求他在xy轴平面上的向量(法向量为z轴),就可以使用该方法
Vector3.ProjectOnPlane(v, Vector3.forward);
6.向量的点积,叉积
点积
Vector3.Dot(Vector3 lhs, Vector3 rhs);
计算方式为: a·b = |a|·|b|cos<a,b> 其中|a|和|b|表示向量的模,<a,b>表示两个向量的夹角。另外在 点积 中,<a,b>和<b,a> 夹角是不分顺序的。
在a,b非零的前提下,点积如果为负,则a,b形成的角大于90度;如果为零,那么a,b垂直;如果为正,那么a,b形成的角为锐角。由于单位向量的模为1,所以两个单位向量的点积得到两个向量的夹角的cos值,因此我们可以通过点积,计算两个向量的夹角。
Vector3 a = new Vector3(7, 0, 0);
Vector3 b = new Vector3(0, 8, 0);
//cos<a,b> = x
float x = Vector3.Dot(a.normalized, b.normalized);
//反余弦 Cos(r) = x, r = Acos(x);
float r = Mathf.Acos(x);
//前面得到的是弧度,转角度
float angle = r * Mathf.Rad2Deg;
叉积
Vector3.Cross(Vector3 lhs, Vector3 rhs);
计算方式为: |c| = |axb| = |a|·|b|sin<a,b>
Vector3.Cross(a, b)得到的值依旧为一个向量c,c垂直于a,b所形成的平面,并且方向遵守右手定则(即b到a的转向为右手四指弯曲的方向,大拇指的方向即为c的方向)因此axb ≠ bxa,而是axb = – bxa。因此我们可以利用这个性质来判断a,b的相对位置,同样也可以求得a,b的夹角,两个单位向量的叉积的模为两个向量的夹角的sin值
Vector3 a = new Vector3(1, 0, 1);
Vector3 b = new Vector3(0, 0, 1);
Vector3 c1 = Vector3.Cross(a, b);
Debug.Log("c1:" + c1);//c1:(0.0, -1.0, 0.0)
//xz平面上,b到a为顺时针
Vector3 c2 = Vector3.Cross(b, a);
Debug.Log("c2:" + c2);//c2:(0.0, 1.0, 0.0)
//xz平面上,a到b为顺时针
//|c| = sin<a, b>
Vector3 c = Vector3.Cross(a.normalized, b.normalized);
//x = |c|
float x = Vector3.Distance(Vector3.zero, c);
//反余弦 Sin(r) = x, r = Asin(x);
float r = Mathf.Asin(x);
//前面得到的是弧度,转角度
float angle = r * Mathf.Rad2Deg;
Debug.Log("angle:" + angle);//angle:45
7.物体匀速运动,匀加速运动
匀速运动,由公式:位移 = 速度 * 时间
float speed = 10;
void Update()
{
transform.position += transform.forward * speed * Time.deltaTime;
}
匀加速运动,由公式:
float speed = 0;
float endspeed;
int acceleration = 10;//加速度
void Update()
{
endspeed = speed + acceleration * Time.deltaTime;
//transform.position += transform.forward * (speed * Time.deltaTime + acceleration * Time.deltaTime* Time.deltaTime*0.5f);
transform.position += transform.forward * (speed + endspeed) * 0.5f * Time.deltaTime;
speed = endspeed;
}
8.Unity 项目多开
有些项目需要多人在线,测试的时候就需要多开来模拟。但是同一个unity工程只能打开一次,我们可以通过联接的方式来引用出一个新的相同的工程来实现多开。如图,需要多开的原工程为MainProject,而MainProject_copy就是我们的镜像工程
我们在需要多开的项目的根目录的同级目录下新建一个.bat文件,内容如下:
%cd%
rem 需要创建的目录
set dir = CopeProjectFolderName
rem 如果没有则创建
if not exist %dir% ( md %dir%)
rem 创建链接
mklink /J %dir%\Assets YourProjectFolderName\Assets
mklink /J %dir%\ProjectSettings YourProjectFolderName\ProjectSettings
pause
CopeProjectFolderName:镜像工程的文件名
YourProjectFolderName:原工程文件名
原理就是在镜像工程中创建原工程的Assets目录和ProjectSettings目录的联接,这样原目录修改的话,镜像目录也会一并的改变。
运行.bat文件后,建好新的工程,最后用unity打开这个新建的工程即可。
9.Unity调用外部可执行文件(例如 .exe .bat文件)
我们可以使用System.Diagnostics.Process来实现Unity调用外部可执行文件,官方文档:https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.process?view=netframework-4.8
public class EditorUtil
{
public static void ExecuteProcess(string filePath, string command, int seconds = 0)
{
if (string.IsNullOrEmpty(filePath))
{
UnityEngine.Debug.LogError(filePath + " 找不到");
return;
}
Process process = new Process();//创建进程对象
//process.StartInfo.WorkingDirectory = workPath;//文件目录,可以不设置,在FileName中带上路径
process.StartInfo.FileName = filePath;//文件名
process.StartInfo.Arguments = command;//参数(会传入到如exe的Main()函数或者bat的%1 %2)
process.StartInfo.CreateNoWindow = true;//启动该进程而不创建包含它的新窗口
process.StartInfo.RedirectStandardOutput = false;//不重定向输出
try
{
if (process.Start())
{
if (seconds == 0)
{
process.WaitForExit(); //无限等待进程结束
}
else
{
process.WaitForExit(seconds); //在指定的毫秒数内等待关联进程退出
}
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e.Message);
}
finally
{
process.Close();
}
}
}
举例:根据上面的方法我们可以在Unity中进行svn的相关操作,即写好svn的命令行脚本后存为.bat文件,然后在Unity中调用,其中的参数:目录路径,即在process.StartInfo.Arguments传入,每个参数之间用空格分隔
svn.bat:
set path=%1
svn revert -R %path%
svn update %path%
::svn commit -m "log" %path%
如果命令行svn无效可以看看是否环境变量没有配置,或者安装的时候没有勾选(默认不勾选)
使用svn还有一种比较蠢的方法是使用小乌龟svn安装目录下bin/TortoiseProc.exe文件,同样也是要使用上面的Process来调用并传递参数,具体的大家可以百度看看
10.向量的长度sqrMagnitude和magnitude
magnitude:用于获取向量的大小。适用于Vector2.magnitude或Vector3.magnitude
假设在一个平面上有两个点,A:Vector2(1,1),B:Vector2(7,8),根据勾股定理那么A到B的长度即为,(B-A).magnitude的值即为此。
由于上面的操作需要开根号操作,计算的消耗会很大。因此我们可以使用sqrMagnitude来代替,以节省性能。
sqrMagnitude:向量大小的平方,即为 。
11.获取Scene中GameObject的LocalId(Local Indentfier In File)
官方有个API是AssetDatabase.TryGetGUIDAndLocalFileIdentifier,但是这个方法只能用于查看Project视图中的资源文件,无法查看Hierarchy中已在场景中的GameObject的LocalId。
如果要获取场景中的GameObject的LocalId,我们需要通过反射去读取内部的值(原文链接:https://forum.unity.com/threads/how-to-get-the-local-identifier-in-file-for-scene-objects.265686/)
PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
SerializedObject serializedObject = new SerializedObject(unityObject);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile"); //note the misspelling!
int localId = localIdProp.intValue;
12.获取当前Scene中所有的GameObject
GameObject[] array = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
13.Unity2019判断当前Hierarchy是否在Prefab编辑页面
bool IsEditPrefab()
{
var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
return prefabStage != null;
}
14.用代码提交当前Prefab的修改
有时候我们修改了某个在Hierarchy面板的Prefab,此时想将改动通过代码Apply到Project中的.prefab文件时,可以使用下面方法
//获取到Prefab的根目录
GameObject parent = PrefabUtility.GetCorrespondingObjectFromSource(this.gameObject);
//提交修改
PrefabUtility.ApplyPrefabInstance(parent, InteractionMode.UserAction);
//刷新Project面板
AssetDatabase.Refresh();
15.No 'git' executable was found. Please install Git ...
在我们使用PackageManager时,Unity允许我们使用Git上的package(点击加号,选择add package from git URL...)
但是这操作需要我们的电脑里事先装好git,并且配置好相应的环境变量,否则会报错
Cannot perform upm operation: Unable to add package [git://github.com/.../XXX.git]:
No 'git' executable was found. Please install Git on your system then restart Unity and Unity Hub [NotFound]
我们只需要找到git.exe的目录,并且将其配置到系统环境变量的Path中即可。验证方式为,打开命令行窗口输入git,若有效即可。(若使用sourcetree的,可以参考https://blog.csdn.net/wangjiangrong/article/details/80287041 最后面的环境变量相关内容)
配置好环境变量后需要重启Unity以及Unity Hub,注意一定要都重启,否则还是会报错。
16.一些快捷键
windows:
mac:
常见的如QWERTY对应编辑器的拖动,移动,旋转等:
展开或收起所有的子层,按住 alt 再去点击Hierarchy面板的小箭头:
按住鼠标右键然后就可以通过WASD四个方向键来移动我们Scene窗口的视角了
2019新增 Shortcuts Manager(快捷键管理器)可以自定义快捷键:
17.Snap
在Scene目录下,我们可以通过按住Ctrl或者Cmd键,然后拖动或旋转物体时,会按照一定的数值进行变化
相关设置在 Editor-> Snap Settings,可以在里面设置每次移动的距离等。