[Unity]利用Mesh绘制简单的可被遮挡,可以探测的攻击指示器
最近做一个小游戏的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不熟悉的可以看看资料,高性能的等以后有机会了专门研究下,完结撒花
[Unity]利用Mesh绘制简单的可被遮挡,可以探测的攻击指示器的更多相关文章
- 学习笔记:HTML5 Canvas绘制简单图形
HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...
- 学习笔记:利用GDI+生成简单的验证码图片
学习笔记:利用GDI+生成简单的验证码图片 /// <summary> /// 单击图片时切换图片 /// </summary> /// <param name=&quo ...
- Unity中Mesh分解与边缘高亮加上深度检测
一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...
- 利用PowerDesigner绘制PDM生成SQL Server数据库
PowerDesigner是个很强大的建模工具,可以利用它绘制各种图形,本文利用该工具绘制PDM,进而生成SQL Server数据库. 比如绘制一个简单的学生选课.教师授课管理系统的PDM: pk表示 ...
- Unity中动态绘制圆柱体
问题背景 上次写了动态绘制立方体,这最近又来了新功能,绘制圆柱(风筒),要求是给了很多节点,根据节点去动态绘制风筒,风筒就是圆柱连接而成的,可以理解为管道,还有就是拐角处注意倒角,圆润过度过来. 实现 ...
- JavaScript动画基础:canvas绘制简单动画
动画是将静止的画面变为动态的艺术.实现由静止到动态,主要是靠人眼的视觉残留效应.视觉残留也叫视觉暂留现象,物体在快速运动时, 当人眼所看到的影像消失后,人眼仍能继续保留其影像0.1~0.4秒左右的图像 ...
- C#利用GDI+绘制旋转文字等效果
C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经 ...
- 在OpenCV中利用鼠标绘制矩形和截取图像的矩形区域
这是两个相关的程序,前者是后者的基础.实际上前一个程序也是在前面博文的基础上做的修改,请参考<在OpenCV中利用鼠标绘制直线> .下面贴出代码. 程序之一,在OpenCV中利用鼠标绘制矩 ...
- 利用JFreeChart绘制股票K线图完整解决方案
http://blog.sina.com.cn/s/blog_4ad042e50100q7d9.html 利用JFreeChart绘制股票K线图完整解决方案 (2011-04-30 13:27:17) ...
- OpenGL学习-------绘制简单的几何图形
本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念. 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中会有所不同.数学上的 ...
随机推荐
- java线程基础知识整理
目录 线程基本概念 1.java实现线程 2.线程的生命周期 3.线程常用的方法 3.1.sleep() 3.2.interrupt方法 3.3.stop方法 4.线程调度 4.1.常见的线程调度模型 ...
- [图像处理] YUV图像处理入门5
12 yuv420转换为rgb(opencv mat) yuv格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式,而且自己造轮子工作量太大.因此通常都会将yuv转换为rgb, ...
- [深度学习] tf.keras入门1-基本函数介绍
目录 构建一个简单的模型 序贯(Sequential)模型 网络层的构造 模型训练和参数评价 模型训练 模型的训练 tf.data的数据集 模型评估和预测 基本模型的建立 网络层模型 模型子类函数构建 ...
- [OpenCV实战]29 使用OpenCV实现红眼自动去除
目录 1 红眼消除 1.1 眼部检测 1.2 红眼遮掩 1.3 清除瞳孔掩模空洞 1.4 红眼修复 2 结果与完整代码 2.1 结果 2.2 代码 3 参考 在本教程中,我们将学习如何完全自动地从照片 ...
- 07.synchronized都问啥?
大家好,我是王有志.关注王有志,一起聊技术,聊游戏,从北漂生活谈到国际风云.最近搞了个抽奖送书的活动,欢迎点击链接参与. 如果Java面试有什么是必问的,synchronized必定占据一席之地.初出 ...
- vue-element-admin 安装(node方式)
vue-element-admin node方式安装 需要的环境: git .node.js 1.git clone 项目(2选 1) // github https://github.com/Pan ...
- python之路28 网络编程基础之OSI七层协议模型
OSI七层协议 """ 七层模型,亦称OSI(Open System Interconnection).参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间 ...
- [cocos2d-x]用getContentSize()返回的值用CCLOG打印必须用%f
今天写代码,又遇到了一个bug,开始还以为是我自己哪写错了,没想到竟然在这里出错? 而width和height的类型是float类型,为什么必须用%d打印?接着我查看了一下源码: 如果没理解错的话,C ...
- ArcGIS实现打点、线路图、色块、自定义弹窗
闲聊: 马上就要过年了,不知道大家过年都放几天假,小颖公司就只放8天假,就这还有一天是集体调休扣年假,就很··············还不如不放,不过庆幸最近这两周项目也做完了也没啥事,不然就静不下心 ...
- react,vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中的key的作用: key是虚拟dom对象的标识,当状态中的数据发生变化时,vue会根据新数据生成新的虚拟dom,随后vue进行新的虚拟dom与旧的虚拟dom的差异比较. 2.比较规则 ...