unity 高效率阴影手机游戏里怎么实现阴影效率比较高

努力加载中,稍等...
暂无新消息
努力加载中,稍等...
已无更多消息...
这些人最近关注了你
努力加载中,稍等...
已无更多消息
努力加载中,稍等...
已无更多消息
使用Unity进行增强现实中的光照和阴影的渲染
版权所有,禁止匿名转载;禁止商业使用;禁止个人使用。
该文章来自用户转载
我们曾经为大家介绍过Unity中光照和阴影有关的内容,比如。近几年,增强现实应用开发者越来越多,相应的开发技巧被众多开发者所关注。本文将指导您对Unity和Vuforia SDK增强现实的应用进行光照和阴影渲染。这背后的理论同样适用于其它的SDK和游戏引擎。光照与阴影的重要性想要使用Unity创建优质的游戏场景,光照和阴影的设置是非常重要的,因为它们被用来制造场景的景深,从而让画面更加自然与真实。缺少阴影会使得画面缺乏真实感,如果没有阴影,您无法区分出人物是站在平面上还是漂浮在空中,如下图所示。从上图中可以看出有无阴影的明显区别,在AR增强现实应用开发中也是如此。渲染光照和阴影存在的问题如果想在Unity中渲染光照或者阴影,就必须有网格。但是,添加网格会遮挡相机视图。如下图所示,灰色的平板挡住了桌面。如果把灰色平板换成透明材质不就可以解决这个问题么?其实不然,如果使用透明材质替代上图的灰色平面,使用Unity的标准着色器就无法在上面投射阴影(虽然可能有些自定义着色器可以投射)。如下图所示,使用透明材质可以看到桌面,但没有阴影。解决思路:分别渲染光照和阴影最初的想法是利用叠加(Addition)或者复合(Multiplication)效果,可以分别渲染光照和阴影,然后使用后处理效果将阴影和相机视图结合起来。我们可以将场景内容分为三层:背景、光照和阴影、3D对象,然后将它们合并到一起。背景层:只包含相机渲染的图像光照和阴影层3D对象层三层叠加的最终效果上图由于桌面太黑了,因此可能看不清阴影。您可以查看下面的视频了解更多详情。详细步骤如果您还不清楚Unity结合Vuforia开发AR应用的基本步骤,可以先看看之前的文章。总得来讲,我们需要添加三个相机分别用来渲染背景、光照和阴影以及增强现实对象,这三个相机的视角与Vuforia的Augmented Reality Camera相机完全一样,本例中使用CopyCameraData.cs来实现上述功能。另外,由于无法将对象的阴影渲染到另外一层,因此需要将其进行拷贝,我们需要编辑副本的“Mesh Renderer”,将“Cast Shadows”属性设置为“Shadow Only”。最后,本例中使用了Color FX插件实现后处理效果。您可以在文末查看教程的视频演示,并点击【阅读原文】下载教程相关素材。使用Unity实现本例中AR环境下的阴影与光照渲染效果的详细步骤如下:1)新建场景,删除新场景默认的主相机和平行光。2)将Vuforia中的预制件ARCamera拖拽至场景中,在检视面板中加入App License Key(Vuforia 的激活码), 并勾选配置文件的Datasets(数据集)中的Load MyTargets Database和Active。3)将Vuforia 中的预制件ImageTarget拖拽至场景中,设置好Database中的目标识别图。4)新建一个Plane,将其Position的Y值设为-0.01(略低于识别目标图)。5)新建一个立方体和球体,作为光照遮挡物。6)新建一个点光源,设置好光照范围和阴影类型。7)将ARCamera的中的World Center Mode由FIRST_TARGET改为SPECIFIC_TARGET。并将目标图像(ImageTarget)指定给World Center。8)在ARCamera下再创建两个Camera分别命名为Light Camera和ARObject Camera。9)打开Tags & Layers检视面板,分别添加Background Layer、Light Layer 和 ARObject Layer三个层。10)设置ARCamera下方的三个相机。将Light Camera的Culling Mask设置为Light Layer和Default;ARObject Camera的Culling Mask设置为ARObject Layer和Default;Camera 的Clear Flags设置为Solid Color, Culling Mask设置为Background Layer, 并且其子节点BackgroundPlane的Layer设置为Background Layer。11)分别为Light Camera和ARObject Camera 添加 CopyCameraData脚本并将TargetCamera指定为Camera。12)调整一下相机的视角,创建一个空对象命名为_ARObjects并将Plane、Cube和Sphere拖拽至其下方。然后复制_ARObjects对象并命名为_Light Layer Objects,并将Cube和Sphere的Cast Shadows 设置为Shadows Only。将_Light Layer Objects的层级设置为Light Layer。13)删除_ARObjects中的 Plane,并将其层级设置为ARObject Layer。这样三个相机对应三层就设置好了。最后在Camera上添加后处理脚本对图像进行混合。本例中使用Colorful FX插件进行混合以实现后处理效果,您也可以使用其它的后处理脚本。在Light Camera上添加RendderTextureToBlend脚本并将Camera赋给脚本的Blend属性。最后将ARObject Camera的Clear Flags设置为Depth only并调整深度值即可。调整混合模式选取最理想的效果。您可以跟着下面的视频一起练习一下:
分类:(转载)Unity3D圈
登录后参与讨论。点击
请勿发表无意义的内容请勿发表重复内容请勿发表交易类内容禁止发表广告宣传贴请使用文明用语其它
淫秽色情政治倾向人身攻击抄袭剽窃广告刷屏恶意挖坟冒充他人其它3642人阅读
&&&&&&& 无意间看到一篇文章,说是Unity5 demo中为了实现角色的良好阴影,单独给角色设计了一个角色阴影系统。而且使用的是比较老的技术,但效果很好。其实在很多时候,我们需要的并不是万能的阴影光照系统,而是局部能做到效果就行。
&&&&&&& 万能的好处在于任何情况都能看上去合理,但是相对的,性能开销也大,同时为了兼顾各种情况,只能做各种效果的折中,所以我们看到了现在移动平台上,要么就是没有实时阴影,要么就是充满锯齿的实时阴影,要么就是使用2D贴图来模拟实时阴影。
&&&&&&& 用2D贴图来模拟的效果毫无疑问是最好的,但问题在于成本太高,很多小团队资金有限,很难专门为每一个角色都让美术画一大堆阴影贴图。而这也毫无疑问会增加游戏的大小。
&&&&&&& 我主要思考的是,在某种条件下,是否可以实现局部的良好的阴影。比如角色展台,毫无疑问只会出现一个角色,那么这个情况下,毫无疑问我们需要的是一个完美的阴影。或者说某一些游戏,视角固定,而且能看到的范围很小,那么是否只针对这个部分去实现好的阴影系统。或者一个很小的室内,我们也需要一个好的角色阴影。
&&&&&&& ok,那么开始思考方案,首先我们应该只需要一个平行光的阴影。一般来说需要获得这个位置看过去的深度图。我首先在这个位置上放了一个正交摄像机,注意如果你想让角色有阴影,那么必须让角色处在这个正交摄像机的范围内,那么现在第一个问题来了,如何保证角色在正交摄像机的范围内?
&&&&&&& 方法如下:首先你要获得你主摄像机内的所有的需要阴影的物体,然后将这些物体转化到正交摄像机的坐标中,计算出这些物体的最大范围,并得出正交矩阵赋值给正交摄像机。(代码借鉴了/forum/read.php?tid=22738&fid=2,对这个楼主深表感谢)
&&&&&&& 这里要注意,Unity计算出来的Z是负值,但OpenGL是正的,官方说明如下:
Matrix that transforms from world to camera space.
Use this to calculate the camera space position of objects or to provide customcamera's location that is not based on the transform.
Note that camera space matches OpenGL convention: camera's forward is the negativeZ axis. This is different from Unity's convention, where forward is the positive Zaxis.
If you change this matrix, the camera no longer updates its rendering based on its
.This lasts until you call .
#pragma strict
// Offsets camera's rendering from the transform's position.
public var offset:
= new (0, 1, 0);
var camera: ;
function Start() {
camera = GetComponent.&Camera&();
function LateUpdate() {
var camoffset:
= new (-offset.x, -offset.y, offset.z);
= (camoffset, , new (1, 1, -1));
camera.worldToCameraMatrix = m * transform.worldToLocalM
不过实际使用过程中,我们也许并不需要正确的矩阵赋值,因为你需要的是保证所有的物体在摄像机范围内,只需要知道AABB盒,然后把相机设置在AABB盒的中心,同时增加Size即可。
public List&Transform& CharactorL
&& &void CreateCameraProjecterMatrix()
&& &&& &Vector3 v3MaxPosition = -Vector3.one * f;
&& &&& &Vector3 v3MinPosition = Vector3.one * f;&& &
&& &&& &for (int vertId = 0; vertId & CharactorList.C ++vertId)
&& &&& &&& &// Light view space
&& &&& &&& &Vector3 v3Position = camera1.worldToCameraMatrix.MultiplyPoint3x4(CharactorList[vertId].position);
&& &&& &&& &if (v3Position.x & v3MaxPosition.x)
&& &&& &&& &{
&& &&& &&& &&& &v3MaxPosition.x = v3Position.x;
&& &&& &&& &}
&& &&& &&& &if (v3Position.y & v3MaxPosition.y)
&& &&& &&& &{
&& &&& &&& &&& &v3MaxPosition.y = v3Position.y;
&& &&& &&& &}
&& &&& &&& &if (v3Position.z & v3MaxPosition.z)
&& &&& &&& &{
&& &&& &&& &&& &v3MaxPosition.z = v3Position.z;
&& &&& &&& &}
&& &&& &&& &if (v3Position.x & v3MinPosition.x)
&& &&& &&& &{
&& &&& &&& &&& &v3MinPosition.x = v3Position.x;
&& &&& &&& &}
&& &&& &&& &if (v3Position.y & v3MinPosition.y)
&& &&& &&& &{
&& &&& &&& &&& &v3MinPosition.y = v3Position.y;
&& &&& &&& &}
&& &&& &&& &if (v3Position.z & v3MinPosition.z)
&& &&& &&& &{
&& &&& &&& &&& &v3MinPosition.z = v3Position.z;
&& &&& &&& &}
&& &&& &Vector3 off = v3MaxPosition - v3MinP
&& &&& &Vector3 sizeOff =
&& &&& &sizeOff.z = 0;
&& &&& &float dis = sizeOff.
&& &&& &//CreateOrthogonalProjectMatrix (ref m_projMatrix, v3MaxPosition, v3MinPosition);
&& &&& &//Debug.Log (v3MaxPosition.ToString() + v3MinPosition.ToString());
&& &&& &//Matrix4x4 m = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
&& &&& &//camera1.projectionMatrix = m * m_projM
&& &&& &camera1.orthographicSize = dis / 1.8f;
&& &&& &camera1.farClipPlane = off.z + 50;
&& &void CreateViewMatrix(ref Matrix4x4 viewMatrix,Vector3 look,Vector3 up,Vector3 right,Vector3 pos)
&& &&& &look.Normalize ();
&& &&& &up.Normalize ();
&& &&& &right.Normalize ();
&& &&& &float x = -Vector3.Dot (right,pos);
&& &&& &float y = -Vector3.Dot (up,pos);
&& &&& &float z = -Vector3.Dot (look,pos);
&& &&& &viewMatrix.m00 = right.x; viewMatrix.m10 = up.x; viewMatrix.m20 = look.x; viewMatrix.m30 = 0.0f;
&& &&& &viewMatrix.m01 = right.y; viewMatrix.m11 = up.y; viewMatrix.m21 = look.y; viewMatrix.m31 = 0.0f;
&& &&& &viewMatrix.m02 = right.z; viewMatrix.m12 = up.z; viewMatrix.m22 = look.z; viewMatrix.m32 = 0.0f;
&& &&& &viewMatrix.m03 =&&&&&& viewMatrix.m13 =&&& viewMatrix.m23 =&&&&& viewMatrix.m33 = 1.0f;
&& &void CreateOrthogonalProjectMatrix(ref Matrix4x4 projectMatrix,Vector3 v3MaxInViewSpace, Vector3 v3MinInViewSpace)
&& &&& &float scaleX, scaleY, scaleZ;
&& &&& &float offsetX, offsetY, offsetZ;
&& &&& &scaleX = 2.0f / (v3MaxInViewSpace.x - v3MinInViewSpace.x);
&& &&& &scaleY = 2.0f / (v3MaxInViewSpace.y - v3MinInViewSpace.y);
&& &&& &offsetX = -0.5f * (v3MaxInViewSpace.x + v3MinInViewSpace.x) * scaleX;
&& &&& &offsetY = -0.5f * (v3MaxInViewSpace.y + v3MinInViewSpace.y) * scaleY;
&& &&& &scaleZ = 1.0f / (v3MaxInViewSpace.z - v3MinInViewSpace.z);
&& &&& &offsetZ = -v3MinInViewSpace.z * scaleZ;
&& &&& &//列矩阵
&& &&& &projectMatrix.m00 = scaleX; projectMatrix.m01 = 0.0f; projectMatrix.m02 = 0.0f; projectMatrix.m03 = offsetX;
&& &&& &projectMatrix.m10 = 0.0f; projectMatrix.m11 = scaleY; projectMatrix.m12 = 0.0f; projectMatrix.m13 = offsetY;
&& &&& &projectMatrix.m20 = 0.0f; projectMatrix.m21 = 0.0f; projectMatrix.m22 = scaleZ; projectMatrix.m23 = offsetZ;
&& &&& &projectMatrix.m30 = 0.0f; projectMatrix.m31 = 0.0f; projectMatrix.m32 = 0.0f; projectMatrix.m33 = 1.0f;
你看 所有角色都被包括在内了。当然具体适合的值你可以自己调整,这样我们就解决了第一个问题。 如果你的应用场景在室内,你可以无视第一个问题,直接手动设置一个
最合适的值就行了。
第二部,就是我们需要获得物体的剪影。就是说将物体的外轮廓给检录下来。当然复杂点就是获得物体的深度图。剪影获得很简单,我们看下深度图如何获得。因为在移动平台上不支持自动生成深度图,所以我打算自己使用片段着色器获得。
Shader &depthShader& {
&&& Properties {
&&& SubShader {
&&&& //Tags {&Queue&=&Transparent& &IgnoreProjector&=&True& &RenderType&=&Transparent&}
&&&&&&& Pass {
&&&&&&&&&&& CGPROGRAM
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members pos1)
#pragma exclude_renderers d3d11 xbox360
&&&&&&&&&&&&&&& #pragma vertex vert
&&&&&&&&&&&&&&& #pragma fragment frag
&&&&&&&&&&&&&&& #include &UnityCG.cginc&
&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&& sampler2D_float _CameraDepthT
&&&&&&&&&&&&&&& struct appdata {
&&&&&&&&&&&&&&&&&&& float4 vertex : POSITION;
&&&&&&&&&&&&&&&&&& &
&&&&&&&&&&&&&&& };
&&&&&&&&&&&&&&& struct v2f {
&&&&&&&&&&&&&&&&&&& half4 pos : SV_POSITION;
&&&&&&&&&&&&&&&&&&& float2
&&&&&&&&&&&&&&& };
&&&&&&&&&&&&&&& v2f vert (appdata_base v) {
&&&&&&&&&&&&&&&&&&& v2
&&&&&&&&&&&&&&&&&&& o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
&&&&&&&&&&&&&&&&&&& o.depth = o.pos.
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& }
&& &&& &&& &&& &
&&&&&&&&&&&&&&& fixed4 frag(v2f i) : COLOR
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&& &&& &float d = i.depth.x/i.depth.y;
&&&&&&&&&&&&&& &&& &float flag = 0;
&&&&&&&&&&&&&& &&& &if(d & 0)
&&&&&&&&&&&&&& &&& &{
&&&&&&&&&&&&&& &&& &&& &d = abs(d);
&&&&&&&&&&&&&& &&& &&& &flag = 1;
&&&&&&&&&&&&&& &&& &}
&&&&&&&&&&&&&& &&& &float3 kEncodeMul = float3(1.0, 255.0, 65025.0);
&& &&& &&& &&& &&& &float kEncodeBit = 1.0/255.0;
&& &&& &&& &&& &&& &float3 enc = kEncodeMul *
&& &&& &&& &&& &&& &enc = frac (enc);
&& &&& &&& &&& &&& &enc -= enc.yzz * kEncodeB
&& &&& &&& &&& &&& &
&&&&&&&&&&&&&& &&& &return fixed4(flag, enc);
&&&&&&&&&&&&&&& }
&&&&&&&&&&& ENDCG
本来只要存储z就好了,不过很遗憾的是,有些平台的z竟然是负值,负值存储成像素是无意义的。所以我用r存储正负值,gba保存数值,但这样子性能确实会下降,毕竟在片段着色器里,考虑到后面需要照顾阴影质量,我觉得不使用深度图,而使用剪影。
剪影就简单了,连着色器都不用自己写,直接用摄像机渲染的黑图即可。这里我将摄像机设置成普通渲染模式,手动调用render,将贴图放到rendertexture中。
&& &&&& camera1 = GameObject.Find (&Camera&).
&& &&& &//camera1.hideFlags = HideFlags.HideAndDontS
&& &&& &camera1.enabled =
&& &&& &//camera1.projectionMatrix = camera.projectionM
&& &&& &int textureSize = 1024;
&& &&& &shadowTexture = new RenderTexture(textureSize , textureSize, 16, RenderTextureFormat.ARGB32);
&& &&& &shadowTexture.name = &shadowTexture& + GetInstanceID();
&& &&& &shadowTexture.isPowerOfTwo =
&& &&& &shadowTexture.hideFlags = HideFlags.DontS
&& &&& &camera1.targetTexture = shadowT
这样就可以看到如下贴图:
1024大小,内存6M 还算可以接受。当然,因为深度没有用,可以取消,这样会变成4M,其他格式可能会更小,但手机上不一定支持,所以暂时先这样吧。
第三个问题,就是怎么把这些东西投射到地上变成影子。
首先投射到地上已经有现成的Projector组件了,所以问题变成了坐标计算。
我们先把Projector的位置确定一下,Projector应该和主摄像机放在同一个地方,同时有同样的参数设置:
&& &&&& proj = GameObject.Find (&GameObject&).GetComponent&Projector& ();
&& &&& &proj.nearClipPlane = camera.nearClipP
&& &&& &proj.farClipPlane = camera.farClipP
&& &&& &proj.fieldOfView = camera.fieldOfV
这样就保证了视角内的物体都会出现阴影。然后就是坐标计算了,我们想一下,假设世界坐标中的点a,那么我们计算出它在正交摄像机中的坐标,然后根据坐标取出投影贴图中的点,那么假如这个点是全黑的(看你设置的是啥值了),那么就是不在阴影区的,假如不是,那么说明是阴影。
有了这个方案,我们就开始计算吧。首先我们可以轻易获得物体的坐标,问题在于怎么获得它在正交摄像机中的坐标,这个就需要使用正交摄像机的矩阵获得:
matVP = GL.GetGPUProjectionMatrix (camera1.projectionMatrix, true) * camera1.worldToCameraM
proj.material.SetMatrix(&ShadowMatrix&, matVP);
注意,我将这个计算出来的矩阵赋值给了一个材质,这个材质就是Projector使用的,因为是它需要根据坐标判断是否有阴影。
这样似乎接下来就可以直接写出着色器了:
&& &&& &&&& v2f vert (appdata_base v)
&& &&& &&& &{
&& &&& &&& &&& &v2
&& &&& &&& &&& &o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
&& &&& &&& &&& &float4x4 matWVP = mul (ShadowMatrix, _Object2World);
&& &&& &&& &&& &o.uvShadow = mul(matWVP, v.vertex);&&&&&& &
&& &&& &&& &&& &
&& &&& &&& &}
注意,顶点着色器不仅要计算出pos,同时还要获得正交相机中的坐标,也就是uvShadow.
然后就可以在片段着色器中处理了:
half2 uv = i.uvShadow.xy / i.uvShadow.w * 0.5 + 0.5;
&& &&& &&& &&& &#if UNITY_UV_STARTS_AT_TOP
&&&&&&&&&&&&&& &&& &uv.y = 1 - uv.y;
&&&&&&&&&&&&&&& #endif
&&& &&& &&& &&& &fixed4 res = fixed4(0, 0, 0, 0);
&&& &&& &&& &&& &fixed4 texS = tex2D(_ShadowTex, uv);
&&& &&& &&& &&& &if(texS.a & 0)
&&& &&& &&& &&& &{
&&& &&& &&& &&& &&& &res.a = 0.5;
&&& &&& &&& &&& &}
就这么几行,阴影就出现了:
但效果似乎不那么尽如人意,让我们看下u3d自带的高品质的阴影效果:
其实已经很接近了呢,不过鉴于我开头宣称要高质量阴影,所以我打算继续优化边缘,因为你可以看到边缘部分的锯齿,当然我们可以单纯增加贴图大小,但是假如到2048,那么就要占据16M的内存了,所以我暂时打算用另外一种做法,pcf。就是通过采样,将边缘像素模糊化。
&& &&& &&& &&&& texS = tex2D(_ShadowTex, uv + half2(-0./pad, -0./pad));
&&& &&& &&& &&& &if(texS.a & 0)
&&& &&& &&& &&& &{
&&& &&& &&& &&& &&& &res.a += _S
&&& &&& &&& &&& &}
&&& &&& &&& &&& &
&&& &&& &&& &&& &texS = tex2D(_ShadowTex, uv + half2(0./pad, -0./pad));
&&& &&& &&& &&& &if(texS.a & 0)
&&& &&& &&& &&& &{
&&& &&& &&& &&& &&& &res.a += _S
&&& &&& &&& &&& &}
&&& &&& &&& &&& &
&&& &&& &&& &&& &texS = tex2D(_ShadowTex, uv + half2(-0./pad, -0./pad));
&&& &&& &&& &&& &if(texS.a & 0)
&&& &&& &&& &&& &{
&&& &&& &&& &&& &&& &res.a += _S
&&& &&& &&& &&& &}
&&& &&& &&& &&& &texS = tex2D(_ShadowTex, uv + half2(0./pad, 0./pad));
&&& &&& &&& &&& &if(texS.a & 0)
&&& &&& &&& &&& &{
&&& &&& &&& &&& &&& &res.a += _S
&&& &&& &&& &&& &}
经过采样后效果如下:
最后 是时候做一次全面比较了,在电脑上我自己写的完爆自带的,因为我的电脑的显卡很渣,但手机显卡好一些,所以手机上的结果可能不太一样,放到手机上,开启最强模式,看看到底性能和效果对比吧。找了一台两年前的1000块钱的华为:
u3d 高质量阴影:
近距离效果:
再看我自己实现的效果:
2048最强模式下:
不过帧数下降了不少,再看看1024的吧。
效果也是要好上不少吧。
ok,暂时先这样吧
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:199428次
积分:3005
积分:3005
排名:第10514名
原创:87篇
转载:19篇
评论:91条
文章:54篇
阅读:77907
(1)(1)(3)(2)(2)(4)(2)(2)(4)(5)(1)(2)(4)(2)(3)(10)(5)(7)(10)(4)(2)(3)(3)(5)(10)(3)(2)(2)(1)(1)http://blog.csdn.net/dj0379/article/details/
http://blog.csdn.net/dj0379/article/details/
unity 3d中每倒入一次模型就多一个材质球,可我的这些模型都是共用一张贴图的就想共用一个材质球,所以每次都要删除再附上,很麻烦。怎么才能合并这些材质球?
采用TexturePacking吧
1、遍历gameobject,取出material,并根据shader来将material分类
2、调用Unity自带的PackTextures函数来合并每个shader分类中的material所对应的textures(PackTextures函数有缺陷,不过可以将就用)
3、根据合并的大的texture来更新原有模型的texture、material已经uv坐标值。
需要注意的是:需要合并的纹理应该是物体在场景中距离相近的,如果物体在场景中的距离较远,则不建议合并纹理,因为这样做很有可能非但起不到优化的作用,反而降低了运行效率。
一、程序方面
  01、务必删除脚本中为空或不需要的默认方法;
  02、只在一个脚本中使用OnGUI方法;
  03、避免在OnGUI中对变量、方法进行更新、赋值,输出变量建议在Update内;
  04、同一脚本中频繁使用的变量建议声明其为全局变量,脚本之间频繁调用的变量或方法建议声明为全局静态变量或方法;
  05、不要去频繁获取组件,将其声明为全局变量;
  06、数组、集合类元素优先使用Array,其次是List;
  07、脚本在不使用时脚本禁用之,需要时再启用;
  08、可以使用Ray来代替OnMouseXXX类方法;
  09、需要隐藏/显示或实例化来回切换的对象,尽量不要使用SetActiveRecursively或active,而使用将对象远远移出相机范围和移回原位的做法;
  10、尽量少用模运算和除法运算,比如a/5f,一定要写成a*0.2f。
  11、对于不经常调用或更改的变量或方法建议使用Coroutines & Yield;
  12、尽量直接声明脚本变量,而不使用GetComponent来获取脚本;
  13、尽量使用整数数字,因为iPhone的浮点数计算能力很差;
  14、不要使用原生的GUI方法;
  15、不要实例化(Instantiate)对象,事先建好对象池,并使用Translate“生成”对象;
二、模型方面
  01、合并使用同贴图的材质球,合并使用相同材质球的Mesh;
  02、角色的贴图和材质球只要一个,若必须多个则将模型离分离为多个部分;
  02、骨骼系统不要使用太多;
  03、当使用多角色时,将动画单独分离出来;
  04、使用层距离来控制模型的显示距离;
  05、阴影其实包含两方面阴暗和影子,建议使用实时影子时把阴暗效果烘焙出来,不要使用灯光来调节光线阴暗。
  06、少用像素灯和使用像素灯的Shader;
  08、如果硬阴影可以解决问题就不要用软阴影,并且使用不影响效果的低分辨率阴影;
  08、实时阴影很耗性能,尽量减小产生阴影的距离;
  09、允许的话在大场景中使用线性雾,这样可以使远距离对象或阴影不易察觉,因此可以通过减小相机和阴影距离来提高性能;
  10、使用圆滑组来尽量减少模型的面数;
  11、项目中如果没有灯光或对象在移动那么就不要使用实时灯光;
  12、水面、镜子等实时反射/折射的效果单独放在Water图层中,并且根据其实时反射/折射的范围来调整;
  13、碰撞对效率的影响很小,但碰撞还是建议使用Box、Sphere碰撞体;
  14、建材质球时尽量考虑使用Substance;
  15、尽量将所有的实时反射/折射(如水面、镜子、地板等等)都集合成一个面;
  16、假反射/折射没有必要使用过大分辨率,一般64*64就可以,不建议超过256*256;
  17、需要更改的材质球,建议实例化一个,而不是使用公共的材质球;
  18、将不须射线或碰撞事件的对象置于IgnoreRaycast图层;
  19、将水面或类似效果置于Water图层
  20、将透明通道的对象置于TransparentFX图层;
  21、养成良好的标签(Tags)、层次(Hieratchy)和图层(Layer)的条理化习惯,将不同的对象置于不同的标签或图层,三者有效的结合将很方便的按名称、类别和属性来查找;
  22、通过Stats和Profile查看对效率影响最大的方面或对象,或者使用禁用部分模型的方式查看问题到底在哪儿;
  23、使用遮挡剔除(Occlusion Culling)处理大场景,一种较原生的类LOD技术,并且能够“分割”作为整体的一个模型。
  场景中如果没有使用灯光和像素灯,就不要使用法线贴图,因为法线效果只有在有光源(Direct Light/Point Light/Angle Light/Pixel Light)的情况下才有效果。
阅读(...) 评论()

我要回帖

更多关于 unity3d 实现联网游戏 的文章

 

随机推荐