[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学习-------绘制简单的几何图形
本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念. 一.点.直线和多边形我们知道数学(具体的说,是几何学)中有点.直线和多边形的概念,但这些概念在计算机中会有所不同.数学上的 ...
随机推荐
- 3_多维数组转一维数组 reduce()
一,二维数组转一维数组 1 //1. 二维数组转一维数组 2 let arr = [[0,1],[2,3],[4,5]] 3 let newArr = arr.reduce((pre,cur) =&g ...
- UnoCSS 简化 CSS 的书写,Nice!
CSS 样式太多,重复写 在学习 UnoCSS 之前,我提出几个问题: 你是否有过写完了 HTML 之后,跳转到 style 写 CSS 这样来回跳转的痛苦? 你是否有过不知道如何给节点取类名的痛苦( ...
- 史上最简单 OpenCV for C++ 在 Windows 和 Ubuntu 上编译安装使用教程
准备工作 原材料 Ubuntu 系统(非必须,Windows 也可以,主要是 Ubuntu 适合编译) OpenCV 3.4.1 压缩包 OpenCV contrib 3.4.1 压缩包 MinGW( ...
- 从零写一个兼容MySQL/Oracle的Proxy中件间(一)《初识Oracle的通信协议》
0.前言 MySQL由于开源的原因,有各式各样的中件间Proxy ,极大的丰富了做高可用或迁移的方案,习惯了MySQL生态圈的灵活和便利,Oracle官方不开源代码和协议,没有中间件proxy,显得很 ...
- Java 进阶P-3.5+P-3.6
对象数组的for-each循环 for-each是用于遍历数组的另一种形式的for循环.for-each循环显着减少了代码,并且循环中没有使用索引或计数器. 句法: For(<数组/列表的数据类 ...
- 2023牛客寒假算法基础集训营4 A-H+JLM
比赛链接 A 题解 知识点:数学. 算一下发现 \(3\) 最好,\(2,4\) 并列, \(4\) 以后递减.于是,特判 \(3\) ,其他取最小值. (众所周知, \(e\) 进制最好qwq. 时 ...
- 【学习笔记】开源库之 - sigslot (提供该库存在对象拷贝崩溃问题的解决方案)
介绍说明 学习 QT 的时候,觉得 QT 提供的信号槽机制非常有用,这种机制可以解决对象与对象之间通信中的耦合问题,原本想从网络上了解一下具体的实现思路用于项目中,意外的发现了用 C++ 实现的信号槽 ...
- Spring中常见的注解
1.组件注解 @Controller @Service @Repository @Component ---标注一个类为Spring容器的Bean @Configration ---声明当前类为配置类 ...
- docker命令之docker build
docker命令之docker build 明天要讲docker file的公开课,正好借此机会,整理下docker 命令的专题 语法 docker build [OPTIONS] PATH | UR ...
- sqlserver数据库批量新增修改类
MSSql Server 数据库批量操作 需要引用的命名空间 using System; using System.Collections.Generic; using System.Data; us ...