如何避免特效渲染出错?

如何避免特效渲染出错?

特效渲染出错、Mono堆内存泄露、网络游戏通讯加密方案设计、如何实现游戏中绘制的地图网格线等...工作1小时,如何刷出10小时的经验值?UWA一下,你就知道!


这是第137篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)


渲染

Q:想问下大家,我们的项目中,黑色的特效用渲染到纹理的方式会被滤掉,这个是什么原因呢?或者有什么材质可以解决这样的问题呢?

A1:渲染摄像机有背景色的问题,要用RenderTexture正确地以UI为背景绘制Additive类的材质,需要很特殊的方法。
大致思路是RenderTexture使用者,用一个Blend为 One OneMinusSrcAlpha的材质。
摄像机背景色用RGB黑色,Alpha为0。
Additive和不透明的直接画就可以(Additive Alpha为0直接叠加,不透明为1直接覆盖)。原先AlphaBlend的材质,混色也改为One OneMinusSrcAlpha,然后RGB自己乘以Alpha(Alpha为自身Alpha,所以RenderTexture那边正确衰减Dst的颜色)。
感谢欧月松@UWA问答社区提供了回答

A2:查看下是不是粒子特效使用的Shader里使用了ColorMask RGB,导致没有写入Alpha通道的信息。

补充:
之前的项目遇到过同样的问题,题主没有继续回复,我猜应该是Additive材质的问题,我记录下我们项目遇到的问题和解决方案,给遇到类似问题的人参考。

1)用了Additive材质,效果跟题主相同,被过滤了。
2)我们的部分特效制作采用了粒子贴图采用不透明的贴图,要显示的透明部分采用黑色,跟背景叠加呈现出半透的效果,这个渲染到RenderTexture显示的结果是呈现方块,贴图黑色的部分呈现背景的颜色。
其实这两种情况,都是RenderTexture的透明通道信息出了问题,第一种情况是内置的Additive里面采用ColorMask RGB,对Alpha通道信息进行了过滤,一般背景是RGB黑色,Alpha为0,所以RenderTexture的Alpha通道信息为0,再和背景混合时就被过滤了,第二种情况没有透明度信息。
碰到渲染到RenderTexture效果不对的信息,可以先在Editor下通过Alpha通道模式查看RenderTexture的Alpha通道信息,确认是否是因为Alpha信息写入错误。
知道是Alpha信息写入错误,那么如何修改呢?
1)特效用自己的定制的Shader,将Alpha通道信息写进去,如果只有一层特别并且背景是RGB黑色Alpha0的话没问题,但是如果有多层特效,那么RenderTexture最后记录是最后一个渲染的特别混合出来的Alpha值,再拿这个值跟UI混合结果是错误的。小米超神优化里关于特效渲染到纹理对这个问题进行了比较详细的描述。请戳传送门。

2)就是楼上月松同学讲的方法,RenderTexture跟UI混合的时候,Blend One OneMinusSrcAlpha, 这样RenderTexture渲染出来的东西其实是叠加到UI背景上,而背景也可以进行一定程度的混合,这个方法也存计算上的差别,跟我们正常渲染特效的混合方式不同,所以要调整贴图颜色正确的显示。

3)在要渲染的特效后面加个面片,把UI背景贴上去,这样,特效可以和背景正确的混合显示,渲染出来的RenderTexture覆盖UI背景。 这也是我前一个项目最后采用的方案。
感谢赵林@UWA问答社区提供了回答

该回答由UWA提供,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bec285228a16f55acc394b0


逻辑代码

Q:框架C# + Lua。我们的Unity游戏在安卓手机上会出现越来越卡的情况,想问几个问题:
1)我们创建了Texture对象,只要不引用,但是没调用Destroy函数。GC能回收调用吗?
2)AssetBundle里生成的纹理对象,可以使用Resources.unLoad清理成功吗?
3)编辑器模式。为什么我在代码里循环生成1000个new Texture对象。并且存在list,却没看到Profiler有任何变化(编辑器的Mono是会一直在增加的,但是我生成的时候依旧没有加的很快,还是在慢慢增加)
4)卡顿感觉并不是内存太高的原因,好像是有很多东西没有被销毁,还存在Unity里面,一直在运行导致的?

A1:回答如下:

  1. Texture不走GC,必须手动销毁
  2. 请用AssetBundle.Unload
    https://docs.unity3d.com/Manual/AssetBundles-Native.html
  3. 凭感觉可还行,很多东西没销毁占用的也是内存。
    感谢凯奥斯@UWA问答社区提供了回答

A2:回答如下:

  1. 资源类的东西都不走GC
  2. AssetBundle.Unload
  3. Mono是会一直在增加,是因为Profile记录的数据是在Mono里面的
  4. 卡顿可以在Profiler中看一下是哪个函数执行时间过长来修复
    感谢萧小俊@UWA问答社区提供了回答

该回答来自UWA问答社区,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bee4d69a1dae055a7c051cd


渲染

Q:根据T4M的Shader写了一个项目的版本出来,但是原Shader没问题,我自己写的Shader出现了Lightmap不正确的问题。
在XCode上真机Profile发现我新写的Shader的texcoord0和texcoord1在bind VBO的offset相同,也就是传进来的UV和LightmapUV数据源是一样的。感觉影响这个的只有appdata,但是我自己写的appdata也很简单:

struct appdata_t4m
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
};

而且发现stride也不对,按我这个appdata传的数据stride应该是40(pos+normal+uv0+uv1=4x3+4x3+4x2+4x2=40),但是看到stride只有32。
只要换回原本的Surface版本的T4M就没问题,所以感觉不是动态加载或者Mesh上面的问题,实在找不到什么原因了。

A1:看了下T4M的Shader应该是Surface Shader,如果你是自己写Surface Shader,Lightmap是Unity自动处理的。如果你是要写VF Shader,建议你把T4M的Shader生成VF Shader,看一下生成出来的代码,应该就能找到原因了。Unity 默认静态Lightmap是存在TEXCOORD1,动态Lightmap是存在TEXCOORD2。
一天到头困来的@UWA问答社区分享了该回答

A2:直接抄Unity原生Shader的话,

#ifndef LIGHTMAP_OFF
o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#ifndef DYNAMICLIGHTMAP_OFF
o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
#endif
#endif

可能是unity_LightmapST 和 unity_DynamicLightmapST之类的参数没有用上导致的。
感谢欧月松@UWA问答社区分享了该回答

该回答来自UWA问答社区,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5be3e75df13b5823887f4ee7


渲染

Q:我想实现逆水寒庄园的网格线,如下图。用LineRenderer绘制一条线一个GameObject,感觉开销很大,改用自创建Mesh并用Shader来绘制网格线,但这两种方案都有一个很严重的效果问题,就是视野稍远处的线都会变花,摄像机视角转动的时候更是明显。请问Unity中要实现如下的网格效果,用什么方式效果好开销小呢?
http://uwa-ducument-img.oss-cn-beijing.aliyuncs.com/Blog/TechSharing_137/2.png

A:可以尝试在MeshRenderer添加第二个材质。材质使用一个Repeat采样的方块沟边贴图,然后调整UV缩放率来解决。

欧月松@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bed107ca1dae055a7c051ba


逻辑代码

Q:我们以前的项目是简单异或加密,后续新项目打算统一下这块,网上搜到的多数做法是通用的网络通讯加密方案设计,没有针对于网络游戏的特定定制的,所以看看大家是怎么实现的。这里的加密只涉及网络消息传递这层,不涉及客户端和服务器本身的安全(也就是假设它们是安全的),我的问题如下:

1)大家有没有做加密?为什么?
我们做了加密,抱的心态是“多少加点密,明文还是不太妥 - 即使是probuffer等2进制序列化方案也是可以解析出value的”。加密之外更多遵循“客户端不可信”的原则,在具体的业务通讯协议设计上保证无论客户端发来怎样的消息,服务器都不受骗(我们无损失,对方无受益)。
2)在机密性这层,用的是“自研加密算法”,还是公开的标准算法?为什么?
我们是简单异或
3)在完整性这层,是否有做保证?用的什么方案? - 我们没做
4)在防重放这层,是否有做保证?用的什么方案?- 我们没做
现代加密体系常用套路如下图,大家是按这个套路来的吗?选了其中哪些组件?做了哪些定制?为什么?

http://uwa-ducument-img.oss-cn-beijing.aliyuncs.com/Blog/TechSharing_137/3.jpg

参考:
TLS 1.2/1.3
很棒的文章:

https://blog.helong.info/blog/2015/09/07/tls-protocol-analysis-and-crypto-protocol-design
https://zhuanlan.zhihu.com/p/28850798

微信mmtls:
https://github.com/WeMobileDev/article/blob/master/基于TLS1.3的微信安全通信协议mmtls介绍.md

A1:我觉得题主你的功课已经做得挺足了~稍微聊聊我们项目,但因为我主要还是做客户端,协议加密这块不是特别熟悉,所以只提供一些信息供参考。
1)当然要做加密……“客户端不可信”原则是业务层遵守的东西,而这层东西首先因为人的原因会导致一些极限情况考虑不周,另外就是有些情况下从设计上就不太能做到万无一失。而且我个人认为协议加密是为了提高做外挂的难度——不加密裸奔,协议被人看个精光,岂不是很容易看出来漏洞,另外即使没有逻辑漏洞,也方便做一些并不是直接获得收益的辅助外挂。所以做协议加密我觉得是基本的职业素养,否则会被同行嘲笑,很没有面子(玩笑)。
2)推荐公开标准算法。自研的哪有论文+行业验证过的标准算法好。
3)至于完整性和防重这块做不做,做多深,我觉得是看项目时间和精力,有时间和精力肯定做一下更好。
协议加密和客户端防破解的功能类似,都是在给破解者提高门槛。因为可以抓包,所以协议数据对于破解者来说跟客户端资源一样,都是可以轻松拿到的内容,所以做一定程度的加密我觉得是完全有必要的。而做到什么程度,其实是一个性价比的事情。比如做基本的AES加密,其实就可以过滤掉70-80%的小白破解者,而当破解你的游戏的商业利益够大的时候,自然就有更多的高级破解者入局,这时候可能基本的加密就不够用了(参考吃鸡)。
我们都不愿面对破解者,但是有人在破解你的游戏的时候,也可能意味着你的游戏在挣钱。
感谢贾伟昊UWA问答社区提供了该回答

A2:逻辑跑在游戏服务器,无BUG,是不需要做加密的。而且让别人开发辅助工具去为游戏服务,是被推荐或允许的,又或者自带辅助工具。
比如:我们公司的MMO,战斗部分是跑在服务器,其它的功能更不用说,所以基本没什么问题,也已经上线运行中。重要的是服务器要验证!
感谢Robot.Huang@UWA问答社区分享了该经验

该回答来自UWA问答社区,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5bebe503a1dae055a7c051af


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(原群已满员)