虽然说美术资源优化会提高性能,不过好的代码可以提高很多性能
这些大部分都出现在我的项目,一些不好的代码,功能是可以就是用了比较耗性能的实现方式
1.在Update里面一直new
例子:最近看到同事写的定时器,他是用字典存储,然后每次update都new list(keys)来遍历定时器和移除定时器
因为foreach下不能移除字典数据,所以用这种new keys
//错误写法
public class ErrorInvoke
{
Dictionary<string, InvokeData> dic = new Dictionary<string, InvokeData>();
void Update()
{
List<string> list = new List<string>(dic.Keys);
for(int i=0;i<list.Count;i++)
{
//满足情况就移除字典
}
}
}
解决方案:用列表来存储相关定时器,update只遍历列表,字典存储列表的引用就好
//修改之后写法
public class FixInvoke
{
Dictionary<string, object> dic = new Dictionary<string, object>();
List<InvokeData> list = new List<InvokeData>();
void Update()
{
for(int i=list.Count;i-->0;)
{
//满足条件移除列表移除字典
}
}
}
2.太多装箱和拆箱
这个东西不用说太多就是目标类型->object装箱,object->目标类型拆箱
这个用的最多可能就是事件系统,我发送事件里面可以有多个参数,这些参数类型不定,然后到最后消息回调里面进行类型转换,频繁的装箱拆箱会引起内存问题,可以使用避免装箱拆箱的事件系统
我同事写的事件事件系统全部用parma object[],因为战斗和ui之间的通信通过事件来,如果一直update来发送事件,装箱拆箱很频繁,我是不建议这么写事件系统
可以参考这个事件系统https://blog.csdn.net/SnoopyNa2Co3/article/details/84971510
3.遍历列表移除
很多情况我们遍历列表来更新数据,如果数据已经没用的情况要从list移除
很多情况的写法是这样的,把移除的存起来,遍历完再移除
如果数据没有先后顺序问题的情况可以下面优化
存起来移除的代码
public class Temp1
{
List<datat> list = new List<datat>();
List<datat> removeList = new List<datat>();
void Update()
{
datat temp;
for (int i=0;i<list.Count;i++)
{
temp = list[i];
if(temp.Remove)
{
removeList.Add(temp);
}
}
if(removeList.Count > 0)
{
for(int i=0;i<removeList.Count;i++)
{
list.Remove(removeList[i]);
}
removeList.Clear();
}
}
}
下面是优化过的代码
public class Temp2
{
List<datat> list = new List<datat>();
void Update()
{
datat temp;
for (int i = list.Count; i-->0 ;)
{
temp = list[i];
if (temp.Remove)
{
list.RemoveAt(i);
}
}
}
}
4.关于反射的使用
反射有什么好处,其实就是少写一些代码,方便一点
就例如:后端返回的协议号和对应的proto,来进行序列化数据
最稳的方法就是手写协议号对应的proto类,不过太繁琐(其实可以用工具生成,其实最好)
这方法消耗不大,不过我同事采用等协议返回来再进行反射获取类,再实例化类。如果协议通信多了性能消耗也大
这种是不可以接受的
1.游戏初始化的时候进行绑定
2.就是用工具进行绑定代码的生成
反射着东西能不用尽量不用
5.频繁GetComponent
一般来说初始化的时候才会GetComponent,如果在update里面出现GetComponent或者频繁,这代码肯定有问题
尤其UI上面出现这种基本都是要改。拒绝没必要的性能消耗
6.功能没分模块,代码乱导致查bug麻烦
某个功能模块尽量写到一起,方便扩展和查看
例如:一个角色可以分很多个模块(控制器)
数据控制器(生命值计算之类),buff控制器,技能控制器(分被动和主动),武器控制器(切换武器逻辑),动作控制器(封装各种动作接口),受击控制器(受击击退),操作控制器(控制移动攻击),死亡控制器(多种死亡类型)如果还有其他特殊的可以加,如果这一大堆写到一个脚本里面,那是一个噩梦,查太麻烦,脚本太庞大,改动麻烦