Unity 小知识

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的长度即为\sqrt{(7-1)^{2} + (8-1)^{2} } \approx 9.22,(B-A).magnitude的值即为此。

由于上面的操作需要开根号操作,计算的消耗会很大。因此我们可以使用sqrMagnitude来代替,以节省性能。

sqrMagnitude:向量大小的平方,即为 magnitude^{2} 。

 

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,可以在里面设置每次移动的距离等。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值