最近做一个小游戏的Demo,最终的效果是这样的

主要是利用Mesh绘制三角形作为显示,然后使用后处理来制作探灯,注意,性能一般,仅仅适合小游戏

分为3步

1:利用mesh绘制三角形,原理很简单,利用三角函数Tan,给定一个角度计算三角形左或者右一个顶点,最后绘制即可

 1 void DrawIt()
2 {
3 if (distance > 0 && angle > 0)//angle角度的一半,distance指三角形起点到另外两点间的距离
4 {
5 Mesh mesh = new Mesh();
6 float pointY = Mathf.Tan(angle * Mathf.Deg2Rad) * distance;//
7 Vector3 p1 = new Vector3(distance, transform.localPosition.y, pointY);
8 Vector3 p2 = new Vector3(distance, transform.localPosition.y, -pointY);
9 mesh.vertices = new[] { transform.localPosition, p1, p2 };
10 mesh.triangles = new[] { 0, 1, 2 };
11 transform.GetComponent<MeshFilter>().mesh = mesh;
12 }
13 }

2:为了制作出被墙壁阻挡得效果,用了最笨得方法,即按照每一度都计算一个点,最后连成三角形,上面得三角形只有三个点,这步制作得可能有N个点,然后从每个起点向终点发射射线,如果有碰撞就将顶点修改为碰撞点,为了让三角形每个点足够平滑,还是用了一个缩放来增加顶点数

 1     void DrawItMore()
2 {
3 if (distance > 0 && angle > 0)//distance:三角形起点到某点的距离,用在Tan函数,angle,三角形角度的一半
4 {
5 Mesh mesh = new Mesh();
6 List<Vector3> point = new List<Vector3>();
7 point.Add(transform.localPosition);
8 List<Vector3> pointLeft = new List<Vector3>();
9 List<Vector3> pointRight = new List<Vector3>();
10 RaycastHit hit;
11 for (int i = angle * LineScale; i > 0; i--)//LineScale,没一度都发射射线还不够细,一般这个值为5比较合适(缩放1的时候),性能消耗主要在这
12 {
13 float index = i / (float)LineScale;
14 float pointY = Mathf.Tan(index * Mathf.Deg2Rad) * angle;
15 Vector3 p1 = new Vector3(distance, transform.localPosition.y, pointY);
16 Vector3 world = transform.TransformPoint(p1);
17 if (Physics.Linecast(transform.position, world, out hit, 1 << LayerMask.NameToLayer("Wall")))//只和Wall Layer进行检测
18 {
19 p1 = transform.InverseTransformPoint(hit.point);
20 }
21 Vector3 p2 = new Vector3(GameModel.Ins.MainRoleData.AtkRange, transform.localPosition.y, -pointY);
22 if (Physics.Linecast(transform.position, transform.TransformPoint(p2), out hit, 1 << LayerMask.NameToLayer("Wall")))
23 {
24 p2 = transform.InverseTransformPoint(hit.point);
25 }
26 pointLeft.Add(p1);
27 pointRight.Insert(0, p2);
28 }
29 point.AddRange(pointLeft);
30 point.AddRange(pointRight);
31 List<int> triangles = new List<int>();//简单设置顶点连接顺序,注意unity顺时针才是正面
32 for (int i = 1; i < point.Count - 1; i++)
33 {
34 triangles.Add(i);
35 triangles.Add(i + 1);
36 triangles.Add(0);
37 }
38 mesh.vertices = point.ToArray();
39 mesh.triangles = triangles.ToArray();
40 transform.GetComponent<MeshFilter>().mesh = mesh;
41 }
42 }

3:遮挡完成了,最后一步就是制作三角形探测,大概原理是新建一个相机仅仅渲染绘制的三角形,并且修改相机设置为Don't Clear,然后将此相机渲染到纹理,最后和主相机利用屏幕后处理进行混合

3.1:新建相机设置,主要是ClearFlags和CullingMask(裁剪设置,只渲染绘制的三角形),主相机叫相机A,新相机就是相机B

3.2:将此相机渲染到纹理,并为混合Shader赋值

1 void Start()
2 {
3 var t = new RenderTexture(Screen.width, Screen.height, 16);
4 GetComponent<Camera>().targetTexture = t;
5 Mat.SetTexture("_LOSMaskTexture", t);//Mat是后面用到的Shader,这里仅仅为Shader图片赋值,也可以不用代码创建RenderTexture,随意
6 }

3.3:编写混合Shader,就是单纯的根据某个通道值叠加

 1 Shader "Custom/LOSMaskShader"
2 {
3 Properties
4 {
5 _MainTex("MainTex",2D) = "white"{}
6 _LOSMaskTexture("LOSMaskTexture",2D) = "white"{}//相机B生成的图
7 _MaskScale("MaskScale", float) = 0.5//混合比例
8 }
9 SubShader
10 {
11 // No culling or depth
12 Cull Off ZWrite Off ZTest Always//屏幕后处理的标配
13
14 Pass
15 {
16 CGPROGRAM
17 #pragma vertex vert
18 #pragma fragment frag
19
20 #include "UnityCG.cginc"
21
22 struct appdata
23 {
24 float4 vertex : POSITION;
25 float2 uv : TEXCOORD0;
26 };
27
28 struct v2f
29 {
30 float2 uv : TEXCOORD0;
31 float4 vertex : SV_POSITION;
32 };
33
34 v2f vert (appdata v)
35 {
36 v2f o;
37 o.vertex = UnityObjectToClipPos(v.vertex);
38 o.uv = v.uv;
39 return o;
40 }
41
42 sampler2D _LOSMaskTexture;
43 sampler2D _MainTex;
44 float _MaskScale;
45
46 fixed4 frag (v2f i) : SV_Target
47 {
48 float4 mask = tex2D(_LOSMaskTexture,i.uv);
49 float4 main = tex2D(_MainTex,i.uv);
50
51 main = main * saturate(mask.r + _MaskScale); //这里提取相机B的R值作为混合,MsakScale越高自然整体越亮
52 return main;
53 }
54 ENDCG
55 }
56 }
57 }

3.4:最后一步,利用OnRenderImage应用屏幕后处理效果

1 private void OnRenderImage(RenderTexture source, RenderTexture destination)
2 {
3 Graphics.Blit(source, destination, LOSMaskMaterial);//Mat是上面Shader的Mat
4 }

Over,对Shader不熟悉的可以看看资料,高性能的等以后有机会了专门研究下,完结撒花

最新文章

  1. Delphi 取得 iOS 辅助使用里的字型大小
  2. CSS代码片段【图文】
  3. 大数的除法 不使用BigInteger Java实现
  4. C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步
  5. Install OE and BitBake
  6. oracle11g rac asm存储数据迁移
  7. 将ECSHOP会员注册页面的Email修改成非必填项
  8. 转:Java NIO系列教程(六) File Channel
  9. ajax 之js读取xml的多浏览器兼容
  10. ICTCLAS50中文分词软件“Init ICTCLAS failed!”问题
  11. linux命令:touch
  12. 关于Schema设计规范及SQL使用建议
  13. 快速使用Log4Cpp
  14. PHP HTTP
  15. 【经验】在CSS中定义a:link、a:visited、a:hover、a:active顺序
  16. 转载:ionic+nodejs开发遇到的跨域和post请求数据问题
  17. node.js爬虫爬取拉勾网职位信息
  18. ●BZOJ 3566 [SHOI2014]概率充电器
  19. Win32对话框程序(2)
  20. bond绑定两张物理网卡为一张逻辑网卡

热门文章

  1. 原生js实现rsa加密
  2. SPOJLCMSUM - LCM Sum
  3. 一种面向业务配置基于JSF广播定时生效的工具
  4. Keepalived高可用集群部署
  5. Array list练习
  6. 12月1日内容总结——表单标签知识补充、css介绍、css选择器和选择器的优先级、css样式调解
  7. 编程哲学之 C# 篇:005——&quot;Hello,World!&quot;
  8. LeetCode_单周赛_332
  9. Portainer功能使用之开启远程访问
  10. SpringBoot 整合Seccurity、权限管理