Unity小技巧
更新: 4/3/2026 字数: 0 字 时长: 0 分钟
快捷键
- 按下
F2快速重命名。 - 在 Inspector 中修改参数时,按
Tab快速切换到下一个参数,Shift + Tab为上一个参数。 Tab也可用于移动焦点。Ctrl + 5聚焦 Project 窗口- Edit -> Shortcut 可以自定义快捷键。
Ctrl + f在 project 窗口搜索。Ctrl + k打开全局搜索。
全局搜索
按下Ctrl + k打开全局搜索。其功能之强大如同 vscode 里的Ctrl + Shift + p。
- 搜索资源
- 执行菜单上的功能
- 场景物体筛选
- 计算
特殊前缀:
t:script-> 只搜脚本(t 代表 type 类型)t:texture player-> 只搜名字带 player 的贴图m:create-> 只搜菜单命令(menu)p:physics-> 只搜设置项(preferences)
优先选中父物体
更新: 4/3/2026 字数: 0 字 时长: 0 分钟
在 Scene View(场景视图) 中点击物体时,Unity 默认会选中你鼠标点到的最上层(或最前)的物体(尤其是嵌套了很多子物体、模型零件、LOD、碰撞体等情况时,很容易点到子物体)。 加上[SelectionBase]后:
- 当你点击这个脚本所在的 GameObject 或它的任意子物体时,
- Unity 会自动选中带有
[SelectionBase]的这个父级 GameObject,而不是选中你实际点击的子物体。
[SelectionBase]
public class MyObject : MonoBehaviour
{
}专用于调式方法的注解
[Conditional]可以让对某个方法的调用在编译时被自动移除,前提是指定的编译符号(Conditional Symbol)没有被定义。
它是一种比#if更优雅的条件编译方式,专门用来控制是否编译方法的调用。
Example:
using System.Diagnostics;
public class Logger
{
[Conditional("DEBUG")] // ← 关键在这里
public static void Log(string message)
{
UnityEngine.Debug.Log(message);
}
}仅当项目定义了DEBUG符号时(Editor 和 Development Build 也有,Release Build 中无):Logger.Log("xxx")这行调用会被正常编译并执行,否则会删除一切对该方法的调用(方法本身还是会被编译)。
GetEntityId()
GetEntityId()是 Unity 6+ 中推荐用于获取对象唯一标识符的方法,它取代了旧的GetInstanceID()(后者已被标记为 Obsolete 并将在后续版本移除)。
它返回EntityId类型(struct值类型),相当于 Unity 引擎为每个UnityEngine.Object(包括GameObject、MonoBehaviour、ScriptableObject等)在内存中分配的唯一句柄(handle)。
核心特点
- 在当前运行进程(Editor 或 Build)内绝对唯一,不同对象绝不会重复。
- 始终有效,不会返回无效的
EntityId.None。 - 每次运行都会变化(重启 Editor 或重新运行 Build 后 ID 会不同),因此不能用于存档或持久化场景。
EntityId在 Unity 6.5+ 中是 64-bit,更稳定。
与旧方法和 GetHashCode 的区别
GetInstanceID():旧版,返回int,已弃用,不推荐使用。GetEntityId():新版,返回EntityId,是官方推荐的替代方案。GetHashCode():C# 标准哈希方法,在 Editor 中数值常与旧InstanceID重合,但在 Build 中不保证一致,不适合作为唯一标识使用。
常见用途
- 作为
Dictionary<EntityId, T>或HashSet<EntityId>的 Key,实现高效的对象查找、缓存和管理。 - 快速判断两个对象是否为同一个实例(比直接用
==更直接,尤其在大量动态对象时)。 - 对象池、Manager 系统、调试工具中标识子弹、敌人、特效等运行时生成的对象。
- 减少持有大量对象引用,降低 GC 压力。
示例代码
using UnityEngine;
public class GetEntityIdExample : MonoBehaviour
{
private Dictionary<EntityId, string> dataDict = new();
void Start()
{
EntityId myId = this.GetEntityId(); // MonoBehaviour 上直接调用
EntityId goId = gameObject.GetEntityId();
dataDict[myId] = "我的数据";
// 如果需要 int 类型的哈希值(用于兼容旧代码)
int hash = myId.GetHashCode();
}
}大幅减少进入播放模式时的加载时间
勾选 Project Setting -> Editor ->Enter Play Mode Options 以跳过(或减少)进入播放模式时的重新加载过程,从而大幅缩短等待时间。
默认情况下,每次你按下 Play 键,Unity 为了保证一个“绝对干净”的运行环境,会执行两个非常耗时的操作:
Domain Reload (域重载):卸载并重新加载所有的 C# 程序集(DLLs)。这会重置所有的
static变量,确保你的单例(Singleton)或静态数据回到初始状态。Scene Reload (场景重载):重新加载当前的场景文件,重置所有 GameObject 的初始状态。
当你开启Enter Play Mode Options后,你可以选择勾选以下两个选项:
Reload Domain (不勾选 = 禁用重载): Unity 不再重启 C# 的虚拟机环境。点击 Play 时,脚本立刻开始运行。
- 速度提升:极其明显,几乎是秒开。
Reload Scene (不勾选 = 禁用重载): Unity 不再从硬盘重新加载场景。
- 速度提升:对于物体极其密集的场景,提升巨大。
但是如果你禁用了 Domain Reload,由于 C# 域没有重启,静态变量的值会保留上一次运行后的结果。 所以如果有时候你的游戏刚才还运行得好好的,再运行突然出了 Bug,考虑一下是不是因为开启了这个选项。
不受帧率影响的阻尼
TIP
感觉还是直接使用 DOTween 更好。
Func<float, float> func = (float time) => 1 - Mathf.Exp(-time * Time.deltaTime);
var t = func(10f)
postion = Vector3.Lerp(position, target, t)公式的原理可以类比物理中半衰期的概念。
Instantiate<Component>
实例化一个游戏对象并且避免之后GetComponet<T>的开销:
Component c = UnityEngine.Object.Instantiate<Component>(prefab);将无需移动旋转缩放的物体标记为Static
当你勾选 Inspector 面板右上角的Static复选框时,你是在告诉 Unity 这个物体在游戏运行时不会移动、旋转或缩放。”这样 Unity 就可以预先计算一些复杂的物理、光照和渲染数据,从而减轻 CPU 和 GPU 的负担。
性能优势
降低 CPU 开销:减少了每帧计算物体位置和剔除逻辑的压力
降低 GPU 开销:通过静态合批减少渲染次数
更真实的画面:可以使用烘焙光照实现高精度的软阴影和全局光照(GI)
注意事项
内存消耗:静态合批会创建新的合并网格,可能会增加内存占用
灵活性丧失:一旦标记为 Static,你在脚本中尝试通过
transform.position移动它通常是无效的(或者会导致巨大的重新计算开销)
标记为Static后,记得在 Rendering -> Lighting 窗口烘培光照。
警惕根运动动画间的过渡
根运动动画间的过渡非常容易产生问题,例如从竖直爬墙的根运动动画可能会和跑步动画混合,导致在动画过渡期间角色向前上方爬取,容易造成角色卡入墙内然后直接被物理系统弹飞。因此,警惕根动画过渡期间可能运行的逻辑。
// 让动画播放到10%之后再进行动画匹配,给根运动动画些时间过渡
_animator.MatchTarget(
matchPosition,
Quaternion.identity,
AvatarTarget.RightHand,
new MatchTargetWeightMask(new Vector3(0, 1, 0), 0),
0.10f,
0.25f
);Collider + Kinematic Rigidbody
在 Unity 的物理引擎眼中,一个只有 Collider 没有 Rigidbody 的物体被称为 静态碰撞体 (Static Collider)。 物理引擎会理所当然地认为这是一个建筑物、一面墙或者一块永远不会动的石头。为了优化性能,引擎会在游戏加载时,把这些静态物体的信息“烘焙”成一个极其复杂的空间树结构(BVH)。
如果你通过播放动画或者代码,强行改变了这个静态碰撞体的 Transform(比如挥舞巨剑),物理引擎就会因为发现“墙居然动了”而引发大地震——它被迫在这一帧重新计算并重建整个场景的静态空间树。如果你频繁挥剑,CPU 就会出现极大的开销,导致游戏严重卡顿。
当你给巨剑加上 Rigidbody 时,你就等于向物理引擎声明:这是一个动态物体 (Dynamic Object),它随时都会移动,把它放进动态物体的处理列表里。这样一来,物理引擎就不会因为它的移动而重新计算整个场景了,性能开销骤降。+
在Untiy3d中导入pmx类型的模型
众所周知,Unity3d 只支持 fbx 类型的文件,而大多数较为精美的人物模型都是 pmx 类型的, 而转换起来又十分麻烦,不过现在可以在Untiy中可以添加名为 MMD4 的插件对模型进行导入。
使用 MMD4Mecanim 插件直接将 pmx 文件导入 Unity,并进行游戏开发。以下是完整的操作步骤和注意事项:
插件下载地址:http://stereoarts.jp/
安装 MMD4Mecanim 插件
在 Unity 中,选择 Assets > Import Package > Custom Package,导入下载的 MMD4Mecanim.unitypackage。
确保导入后项目中出现 MMD4Mecanim 相关文件夹。
导入 PMX 模型
准备 PMX 文件:
- 确保 PMX 文件及其贴图(.png/.jpg)在同一个文件夹内,不要更改文件结构。
- 拖入 Unity:
- 将整个 PMX 文件夹拖入 Unity 的 Assets 目录。
- 插件会自动生成 .MMD4Mecanim 文件。
转换模型:
- 选中 .MMD4Mecanim 文件,在 Inspector 窗口勾选使用条款,点击 Process 进行转换。
- 转换完成后,会在原文件夹下生成 Materials 文件夹(包含所有材质)。
修复材质(避免粉色材质)
- 问题:MMD4Mecanim 默认使用 MMD 风格的 Shader,Unity 可能不兼容,导致材质变粉。
- 解决方法:
- 选中 Materials 文件夹内的所有材质球。
- 在 Inspector 窗口,将 Shader 改为:
- 内置渲染管线 → Standard
- URP(Universal RP) → Universal Render Pipeline/Lit
- HDRP → HDRP/Lit14。
- 手动检查贴图是否正确连接(如 Albedo、Normal Map 等)。
TIP
该情况暂未出现,如出现会进行详细解答
调整骨骼与动画
- 骨骼适配:
- 在 Inspector 窗口,选择 Rig 选项卡,将 Animation Type 改为 Humanoid(适用于角色动画)。
- 点击 Configure 检查骨骼绑定是否正确(绿色表示正常,红色需调整)。
- 动画导入:
- 如果有 .vmd 动作文件,可以一起导入,MMD4Mecanim 会自动转换为 Unity 的 .anim 格式。
物理效果(如头发、裙子摆动)
- 在 MMD4Mecanim 组件中:
- 将 Physics Engine 改为 Bullet Physics(优化物理计算)。
- 勾选 Generate Colliders,使布料、头发等具有物理效果。