Unity2D游戏优化总结

1.不要用foreach遍历对象,会产生额外内存,可参照网站

2.帧速尽量调为30fps或以下,尤其是没有动画效果的时候。

3.仅仅把input control的函数放入到 Update()函数中,尤其是getComponent函数和for循环,其它的完全可以用coroutines和delegate代替, 删除不用的Update()。

4.List和Dictionary的正确选择。objects一样不需要search不要用Lists;不要search且objects是动态的删除添加的用Lists;快速查询获得的需用Dictionary

5.2d游戏没有3d方面的特有渲染,设置中的Graphics质量可以调为最低。

6.xcode的instruments tool工具可以很方便的测出Gpu使用率、pixels、vertices等占用信息。参照网站

7.Image图片一般情况下是不需要Material的,指定了Sprite即可,增加一个Add的Material会增加4个顶点渲染。

8.一个显示的ui的图片尽量打到一个图集里,且图集大小尽量不超过1024,否则一些android机型加载很卡。

Unity的Image添加时raycastTarget默认为false

Unity的Image添加时raycastTarget很多时候是不需要监听其行为,默认为false

1
2
3
4
5
6
7
8
9
10
11
12
13
[MenuItem("GameObject/UI/Image")]
static void CreatImage()
{
if(Selection.activeTransform)
{
if(Selection.activeTransform.GetComponentInParent<Canvas>())
{
GameObject go = new GameObject("image",typeof(Image));
go.GetComponent<Image>().raycastTarget = false;
go.transform.SetParent(Selection.activeTransform);
}
}
}

Unity小结(持续更新)

1.
Resources資料夾裡的資源越多,程式的啟動畫面時間就越長。 链接

2.
Draw Call

Batching is only possible for objects that share the same material pointer.
Batching doesn't work on objects that have multiple materials.
Implicit state changes (e.g. lightmap index) can cause batching to end early.

3.
adb调试android

adb forward tcp:54999 localabstract:Unity-{insert bundle identifier here}
  1. Script Performance链接

Unity’s C# implementation is fast, and slowdown from script is usually the result of a mistake and/or an inadvertent block on slow external operations such as memory allocation. The Unity Profiler can help you find and fix these scripts.

Try to avoid foreach, lamda, and LINQ structures as these allocate memory needlessly at runtime. Use a for loop instead. Also, be wary of loops that concatenate strings.

GameObject creation and destruction takes time. If you have a lot of objects to create and destroy (say, several hundred in a frame), we recommend pooling them.

Don’t move colliders unless they have a rigidbody on them. Creating a rigidbody and setting isKinematic will stop physics from doing anything but will make that collider cheap to move. This is because Unity maintains two collider structures, a static tree and a dynamic tree, and the static tree has to be completely rebuilt every time any static object moves.

Note that coroutines execute in the main thread, and you can have multiple instances of the same coroutine running on the same script.

We recommend targeting around 1-2 ms maximum for all Mono execution time.

4.优化scrollRect

Unity中查找未打成图集的图片

写了个Unity小插件,能够遍历目录将没有打成图集的图片搜索出来
WithOutFolders为不搜索的目录
ConatainLastExtensions为搜索图片格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Linq;
public class FindUnDoTag {
[MenuItem("Libs/查找未打成图集的图片")]
private static void FindUnTagResource()
{
List<string> WithOutFolders = new List<string>(){"Assets/Libs","Assets/Platforms","Assets/Plugins","Assets/Resources"};
List<string> ConatainLastExtensions = new List<string>(){".png"};
string[] files = Directory.GetFiles (Application.dataPath, "*.*", SearchOption.AllDirectories)
.Where (s =>{
for(int k=0;k<WithOutFolders.Count;k++){
if(s.Contains(WithOutFolders[k])){
return false;
}
}
return ConatainLastExtensions.Contains (Path.GetExtension (s).ToLower ());
}).ToArray ();
string splitString = "Assets/";
for (int i = 0; i < files.Length; i++) {
string fullName = files [i].Substring (files [i].IndexOf(splitString));
TextureImporter importer = AssetImporter.GetAtPath(fullName) as TextureImporter;
// TextureImporter textureImporter = (TextureImporter)TextureImporter.GetAtPath (fullName);
if (importer.spritePackingTag == "") {
Log.Error (fullName);
}
}
Log.Trace ("查找结束");
}
}

Unity中Material修改shader后避免修改Mat文件

在Unity中经常会出现动态修改Material的shader属性后Mat文件随之改变,每次提交svn或git后总要先重置一下,方法可为在Start方法中新增一个Material,然后修改这个Material。

1
2
3
4
5
6
7
8
#if UNITY_EDITOR
Material cachedMat;
if(!_cache.TryGetValue(image.material,out cachedMat))
{
cachedMat = new Material(image.material);
_cache.Add(image.material,cachedMat);
}
material =cachedMat;

具体详情可以参照网站一

以及网站二

Unity查找某个资源的引用位置

unity中实现查找某个资源被prefab等引用的位置。首先需要在Project Setting的Editor中把Asset Serialization的Mode改成Force Text形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
EditorSettings.serializationMode = SerializationMode.ForceText;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
if (!string.IsNullOrEmpty(path))
{
string guid = AssetDatabase.AssetPathToGUID(path);
List<string> withoutExtensions = new List<string>(){".prefab",".unity",".mat",".asset"};
string[] files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories)
.Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();
int startIndex = 0;
for (; startIndex < files.Length; startIndex++) { string file = files [startIndex];
EditorUtility.DisplayCancelableProgressBar ("匹配资源中", file, (float)startIndex / (float)files.Length);
if (Regex.IsMatch (File.ReadAllText (file), guid)) {
Debug.Log (file, AssetDatabase.LoadAssetAtPath<Object> (GetRelativeAssetsPath (file)));
}
}
EditorUtility.ClearProgressBar ();
Debug.Log ("查找结束");
}

Unity中将目录中资源打包Assetbundle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
string scenePath = Application.dataPath + "/Scenes";
DirectoryInfo dir = new DirectoryInfo (scenePath);
List<FileInfo> fileInfos = DirSearch (dir,"*.unity");
string splitString = "Assets/";
foreach (FileInfo fileInfo in fileInfos) {
string fullName = fileInfo.FullName;
fullName = fullName.Substring (fullName.LastIndexOf (splitString) );
string fileName = Path.GetFileNameWithoutExtension (fileInfo.FullName);
AssetImporter importer = AssetImporter.GetAtPath(fullName);
if (Libs.Config.AssetBundleExcludeScenes.Contains (fileName)) {
importer.assetBundleName = "";
} else {
importer.assetBundleName = fileName;
}
importer.SaveAndReimport ();
}
1
2
3
4
5
6
7
8
9
private static List<FileInfo> DirSearch(DirectoryInfo d, string searchFor)
{
List<FileInfo> founditems = d.GetFiles(searchFor).ToList();
// Add (by recursing) subdirectory items.
DirectoryInfo[] dis = d.GetDirectories();
foreach (DirectoryInfo di in dis)
founditems.AddRange(DirSearch(di, searchFor));
return (founditems);
}