不好方式:yield return 0;
正确方式:yield return null;
不好方式:
while(!IsComplete) {
yield return new WaitForSeconds(1f);
}
正确方式:
WaitForSeconds delay = new WaitForSeconds(1f);
while(!IsComplete) {
yield return delay;
}
不好方式:
gameObject.tag == "TagString";
正确方式:
gameObject.CompareTag("TagString");
不好方式:
ArrayList list = new ArrayList();
正确方式:
List<T> list = new List<T>();
不好方式:
public struct Item
{
public string Name;
public int Age;
public Vector3 Postion;
}
public Item[] ItemArray;
正确方式:
public string[] Names;
public int[] Ages;
public Vector3[] Postions;
不好方式:
private void Update()
{
Collider c = GetComponent<Collider>();
}
正确方式:
private Collider m_c;
private void Start()
{
m_c = gameObject.GetComponent<Collider>();
}
##
网络模块
网络层消息分组处理,比如聊天组和逻辑组 网络层消息组分帧处理,减少网络消息单帧吞吐量 控制网络层消息优先级队列处理
界面模块
界面管理分组管理 界面开发必须通过事件机制解耦 界面导航采用堆栈方式 界面关闭应分为:返回和关闭(返回代表返回栈顶元素,关闭直接返回主界面) 界面关闭指定到跳转界面同样入栈
梳理界面界面开发流程,界面开发不高效,且缺少通用型组件。
资源管理
资源Bundle管理 资源Asset的管理
资源池策略(引用计数或反向依赖) 资源加载和卸载 资源卸载下载一定通过Unload(true)方式卸载
资源打包策略(主包和依赖包方式) 资源打包只关心依赖图集、贴图
主资源通过资源清单方式维护
配置数据模块
数据生成数据高效数据文件(文件格式和二进制格式) 数据对象生成一定不能暴露出可修改静态配置数据可能
版本自动化
高效使用的版本资源化规划 版本打包脚本实现,建议使用Python 版本部署参数配置(版本号,CDN服务器,是否打开日志,平台等) 版本部署参数应分为不同平台 自动化工具可统一继承Jenkins平台
客户端Tick管理
不同系统底层心跳管理必须有先后顺序 系统心跳管理必须可以通过参数控制,便于性能调优
项目适配方案
适配方案应项目初期确定 项目适配配置文件应分为不同平台不同配置 所有适配参数应该统一由设置模块调用
对象池方案
普通对象缓存池管理方案 带类型的对象池管理方案
项目SDK和Device
SDK需要在客户端封装成统一的接口,不同平台不同实现 设备信息也需要封装成统一接口,不同平台分别实现
音效方案
音效需要分组播放
动画优化
控制动画的更新类型,一般是主角是一直更新,其他的动画是在视野范围内更新 动画状态机的动画剪辑动态替换
特效打包
所有的特效作为主包,贴图按照依赖关系打包
单元测试
根据游戏类型定义资源游戏单元检测框架,主要是为了美术检测资源 定期进行性能检测 兼容性检测 压力检测
场景优化
Instance 技术 显示对象的权限管理,隐藏应该是所有的逻辑也隐藏 显示对象更新权限管理,统一由显示对象管理器控制
框架模块测试Unity工程
Editor Default Resources -默认标记器资源目录
Launcher 游戏初始化场景,启动游戏
Standard Assets-标准资源目录
拆箱和装箱是C#很基础问题,这里简单说明一些装箱 和拆箱基本概念和应用,装箱和拆箱是值类型和引用 类型之间相关转换要执行的操作。
code
using System;
namespace ConsoleApplication1
{
struct Vector : IDisposable
{
public void Dispose()
{ }
}
class Matrix : IDisposable
{
public void Dispose()
{ }
}
class Program
{
static void Main(string[] args)
{
object obj_v = new Vector();// 发生装箱
object obj_i = 10;// 发生装箱
object obj_m = new Matrix();// 未发生装箱
int val_i = 10;// 未发生装箱
Vector val_v = new Vector();// 未发生装箱
}
}
}
code to il
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 43 (0x2b)
.maxstack 1
.locals init ([0] object obj_v,
[1] object obj_i,
[2] object obj_m,
[3] int32 val_i,
[4] valuetype ConsoleApplication1.Vector val_v,
[5] valuetype ConsoleApplication1.Vector V_5)
IL_0000: nop
IL_0001: ldloca.s V_5
IL_0003: initobj ConsoleApplication1.Vector
IL_0009: ldloc.s V_5
IL_000b: box ConsoleApplication1.Vector//执行ILbox指令,在内存堆中申请Vector类型需要的堆空间
IL_0010: stloc.0
IL_0011: ldc.i4.s 10
IL_0013: box [mscorlib]System.Int32//执行ILbox指令,在内存堆中申请System.Int32类型需要的堆空间
IL_0018: stloc.1
IL_0019: newobj instance void ConsoleApplication1.Matrix::.ctor()
IL_001e: stloc.2
IL_001f: ldc.i4.s 10
IL_0021: stloc.3
IL_0022: ldloca.s val_v
IL_0024: initobj ConsoleApplication1.Vector
IL_002a: ret
} // end of method Program::Main
说明
obj_v 是引用类型,new Vector()是值类型struts,将 值类型转为引用类型是发生装箱操作,变量obj_i也发生了装 箱操作。
obj_m 是引用类型,new Matrix()是引用类型class,将 引用类型转为引用类型,并不会发生装箱操作。val_i和val_v 都是值类型赋给值类型,也不会发生装箱操作。
总结
以上就是装箱所要执行的操作了,执行装箱操作时不可避免的要 在堆上申请内存空间,并将堆栈上的值类型数据复制到申请的堆 内存空间上,这肯定是要消耗内存和cpu资源的。
shaderlib是Unity引擎用来组织渲染脚本。
一个shader是由多个subshader组成,一个subshader可理解为一个shader的渲染方案。即subshader是针对不同的显卡而编写的,每一个shader至少有1个subshader、理论可以无线多个,但是一般两到三个足够。
Shader "Custom/TestName" {
SubShader {
}
SubShader {
}
}