Unity开发实用技巧汇总
Unity开发实用技巧汇总
Unity是一款广泛使用的3D游戏开发引擎,掌握其使用技巧可以显著提高开发效率。本文总结了多个实用的Unity编辑器功能和代码优化技巧,包括编辑器颜色更改、物体捕捉、Inspector锁定、变量显示、摄像头视角控制等,适合Unity开发者参考学习。
一、改变运行时编辑器颜色
效果:
二、捕捉到网格
拖动物体时按住Ctrl键,在Scene视图中可以设置捕捉的距离大小。
三、Inspector锁定
点击锁定物体A后,再选择物体B,Inspector界面仍然显示A的参数。这个功能在给一个数组拖动物体时特别有用,可以避免Inspector界面频繁跳转。
四、在Inspector中显示私有变量(灰色)
常规模式下,私有变量不显示。将Inspector设置为Debug模式即可显示私有变量,私有变量将以灰色显示。
五、移动摄像头视角
选中相机后,按Ctrl+Shift+F键。
六、给变量一个范围
使用Range属性,可以在Inspector中显示滑条。
[Range(1f,2f)]
七、保存游戏模式下的更改
在游戏模式下,选中组件,选择复制,结束游戏模式后,右键组件,粘贴即可。
八、多个公共变量之间插入空格和分类标题
使用Header和Space属性,可以在Inspector中插入空格和分类标题。
[Header("这是测试")]
[Space]
九、在编辑器中隐藏
使用HideInInspector属性,可以在编辑器中隐藏变量。
[HideInInspector]
十、序列化:私有变量显示在Inspector中
当Unity对脚本进行序列化时,仅对公共字段进行序列化。如果还需要Unity对私有字段进行序列化,可以将SerializeField属性添加到这些字段。序列化后的私有变量仍然为私有变量。
序列化系统可执行以下操作:
- 可序列化(可序列化类型的)公共非静态字段
- 可序列化标记有SerializeField属性的非公共非静态字段
- 不能序列化静态字段
- 不能序列化属性
参考:SerializeField - Unity 脚本 API
[SerializeField]
十一、最大/最小化窗口
鼠标悬停在窗口上+Shift+Space
十二、锁定图层
参考Unity 基础 之 Layer(层layer)、LayerMask (遮罩层) 的 总结 和 使用(CullingMask、Ray 射线的使用等)_unity layermask-CSDN博客
十三、快速聚焦
单击F键
双击F键
十四、tooltip
在变量上使用Tooltip,可以添加变量描述,在Inspector上鼠标悬停在变量上时可以看到变量描述。
十五、自动语句
在VS中,有些语句可以自动填充,如for循环,写下for然后按下两次Tab键就会自动填充,同样适用于if、foreach、while等。
十六、区域
使用#region和#endregion,来折叠代码
十七、快速折叠/展开
Alt+→展开
Alt+←折叠
十八、模型预览
右键单击,点这里窗口独立出来
点这里,窗口变回去
十九、在Inspector中显示自己写的函数调用按钮(开发时使用)
首先放入两个脚本文件,之后在自己写的代码上添加InspectorButton即可
[InspectorButton("按钮名字")]
例如
[InspectorButton("显示房子")]
void OnEnable()
{
for (int i = 0; i < hidenMesh.Length; i++)
{
hidenMesh[i].GetComponent<MeshRenderer>().enabled = true;
}
}
显示为
InspectorButton.cs
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MonoBehaviour), true)]
[CanEditMultipleObjects]
public class InspectorButton : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var mono = target as MonoBehaviour;
if (mono == null)
return;
var methods = mono.GetType()
.GetMethods(
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static
).Where(method =>
Attribute.IsDefined(method, typeof(InspectorButtonAttribute))
).ToArray();
foreach (var method in methods)
{
var attr = method.GetCustomAttribute<InspectorButtonAttribute>();
DrawButton(method, attr.Name);
}
}
private void DrawButton(MethodInfo methodInfo, string methodName)
{
if (string.IsNullOrEmpty(methodName))
methodName = methodInfo.Name;
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(
methodName,
GUILayout.ExpandWidth(true)
))
{
foreach (var targetObj in targets)
{
var mono = targetObj as MonoBehaviour;
if (mono == null)
continue;
var val = methodInfo.Invoke(mono, new object[] { });
if (val is IEnumerator coroutine)
mono.StartCoroutine(coroutine);
else if (val != null)
Debug.Log($"{methodName}调用结果: {val}");
}
}
EditorGUILayout.EndHorizontal();
}
}
InspectorButtonAttribute.cs
using UnityEngine;
[System.AttributeUsage(System.AttributeTargets.Method)]
public class InspectorButtonAttribute : PropertyAttribute
{
public readonly string Name;
public InspectorButtonAttribute()
{
}
public InspectorButtonAttribute(string name)
{
Name = name;
}
}