当前位置: 代码迷 >> 综合 >> 闲云野鹤:吃鸡(三)之场景制作:制作毒圈
  详细解决方案

闲云野鹤:吃鸡(三)之场景制作:制作毒圈

热度:61   发布时间:2023-10-09 09:44:26.0

先上最终效果图:

电弧为shader动态效果

 

闲云野鹤:吃鸡(三)之场景制作:制作毒圈

交界处电弧高亮(也是动态)

闲云野鹤:吃鸡(三)之场景制作:制作毒圈

 

上部全透明

闲云野鹤:吃鸡(三)之场景制作:制作毒圈

 

        思路:毒圈为吃鸡比较有特色的元素,在3dmax里面做一个72段边的圆柱,半径5米,高度500米。去掉上下底面,用“展开UV”功能调整好UV,全部塌陷后导出预制体到unity,注意物体的中心要落在底面上,再写两个脚本,一个为viewAngle.cs,一个为IntersectHightLight.shader。将viewAngle.cs挂在毒圈物体上即可。

viewAngle.cs主要实现以下几个功能:

1、设置相机.depthTextureMode模式,为shader获取深度图做准备。

2、打开摄像机HDR模式增强电弧亮度的强度。

3、由于吃鸡游戏需要狙击开镜,那么毒圈的电弧的显示强度需要与相机的fieldOfView关联:随着fieldOfView的减小而越清晰(相当于走近)。

4、实现毒圈大小的接口(通过Mul变量值控制)

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class viewAngle : MonoBehaviour
{Camera _camera;Renderer _renderer;float TAnangle;float lastfieldOfView = 1;public float Mul = 1f;float lastMul = 0;void Start(){_camera = Camera.main.GetComponent<Camera>();_camera.depthTextureMode = DepthTextureMode.Depth;//设置相机.depthTextureMode模式,为shader获取深度图做准备_camera.allowHDR = true;//允许摄像机HDR模式增强电弧强度lastfieldOfView = _camera.fieldOfView;_renderer = GetComponent<Renderer>();transform.localScale = new Vector3(1, 1, 1) * Mul;}void Update(){if (lastfieldOfView != _camera.fieldOfView)//减少运行次数{TAnangle = Mathf.Tan(22.5f * 3.14159f / 180f) / Mathf.Tan(_camera.fieldOfView * 3.14159f / 360f);//以40度为基准,得到随视角变化的放大倍数_renderer.material.SetFloat("_viewAngle", TAnangle);//代入毒圈的shader,lastfieldOfView = _camera.fieldOfView;}if (lastMul != Mul){transform.localScale = new Vector3(1, 1, 1/Mul) * Mul;//保持毒圈高度不变,只改变水平方向大小。_renderer.material.SetFloat("_Mul", Mul);//代入毒圈的shaderlastMul = Mul;}}}

 

IntersectHightLight.shader 主要实现毒圈的特效。下图是我的经验值:

闲云野鹤:吃鸡(三)之场景制作:制作毒圈

代码如下:

Shader "Unlit/IntersectHightLight"
{Properties{_MainTex ("Base (RGB)", 2D) = "white" {}//电弧_MaskTex("MaskTexture", 2D) = "white" {}//电弧遮罩_TurnTex("MaskTexture", 2D) = "white" {}//切换电弧_Color ("Color",Color) = (0,0,0,0)//毒圈颜色_IntersectWidth("Intersect Width",Range(0,5)) = 0.05 //相交宽度 Zintersect_IntersectColor("Intersect Color",Color) = (0,0,0,0) //交界颜色_Constrast("Constrast",Range(1,5))=3_lightNess("lightNess",Range(1,100))=50_viewAngle("ViewAngle",Range(1,500))=1_Mul("_Mul",Range(0,500))=1}SubShader{Tags { "RenderType"="Transparent" "Queue" = "Transparent"}LOD 100Pass{//为了方便观察相交情况,设置半透,双面渲染ZWrite OffCull offBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;sampler2D _MaskTex;sampler2D _TurnTex;fixed4 _MainTex_ST ;fixed4 _MaskTex_ST ;fixed4 _TurnTex_ST ;fixed _Constrast;fixed _lightNess;fixed _viewAngle;//来自unity脚本的视野放大倍数,倍数越大越近,越能看见电弧fixed _Mul;struct appdata{fixed4 vertex : POSITION;fixed4 texcoordMain : TEXCOORD0;fixed4 texcoordMask : TEXCOORD1;fixed4 texcoordTurn : TEXCOORD2;};struct v2f{fixed2 Z0 : TEXCOORD0;fixed4 scrPos : TEXCOORD1;fixed4 vertex : SV_POSITION;fixed4 uvMain : TEXCOORD3;fixed4 uvMask : TEXCOORD4;fixed2 uvTurn : TEXCOORD5;fixed2 uvTurnFast : TEXCOORD6;fixed4 vert2world : TEXCOORD7;//fixed uvMain_y:TEXCOORD8;};fixed4 _Color;//获得深度图,注意摄像机需要设置 Camera.main.depthTextureMode = DepthTextureMode.Depth;sampler2D _CameraDepthTexture;fixed _IntersectWidth;fixed4 _IntersectColor;v2f vert (appdata v){v2f o;//以下是边缘交界高亮o.vertex = UnityObjectToClipPos(v.vertex);COMPUTE_EYEDEPTH(o.Z0.x);// 在相机空间把顶点的深度存入ZOo.scrPos = ComputeScreenPos(o.vertex);//先把顶点在屏幕空间的位置存起来,用于片元着色器中获取深度图的深度o.vert2world=mul(unity_ObjectToWorld ,v.vertex);o.Z0.y=v.texcoordMain.y;//以下是电弧和频率_MainTex_ST.x=_Mul;//由于毒圈高度固定,所以x方向UV要随毒圈大小改变,以免电弧走形o.uvMain.xy = v.texcoordMain.xy * _MainTex_ST.xy + _MainTex_ST.zw;//电弧UV(空间)_MainTex_ST.w=-_Time.x*2;o.uvMain.zw = v.texcoordMain.xy * _MainTex_ST.xy*16 + _MainTex_ST.zw;//电弧UV(交界处)_MaskTex_ST.x=_Mul;o.uvMask.xy = v.texcoordMask.xy * _MaskTex_ST.xy + _MaskTex_ST.zw ;//遮罩1 UV_MaskTex_ST.zw=fixed2(666,666);o.uvMask.zw = v.texcoordMask.xy * _MaskTex_ST.xy + _MaskTex_ST.zw ;//遮罩2 UV_TurnTex_ST.zw += _Time.x*3;o.uvTurn = fixed2(0.1,0.1) * _TurnTex_ST.xy + _TurnTex_ST.zw;//用固定点按直线扫描(慢)_TurnTex_ST.z += _Time.w;o.uvTurnFast= fixed2(0.4,0.4) * _TurnTex_ST.xy + _TurnTex_ST.zw;//用固定点按直线扫描(快)return o;}fixed4 frag (v2f i) : SV_Target{//以下是电弧频率fixed4 albedo1 = fixed4(tex2D(_MainTex, i.uvMain.xy).rgb,0);//电弧采样fixed4 albedo5 =fixed4(tex2D(_MainTex, i.uvMain.zw).rgb,0);//交界处电弧采样fixed4 albedo2 = fixed4(tex2D(_MaskTex, i.uvMask.xy).rgb,0);//加上遮罩1fixed4 albedo4= fixed4(tex2D(_MaskTex, i.uvMask.zw).rgb,0);//加上遮罩2fixed4 albedo3 = tex2D(_MaskTex, i.uvTurnFast);//获得快闪动fixed3 turnRGB=step(fixed3(0.3,0.3,0.3), tex2D(_TurnTex, i.uvTurn).rgb);//根据采集rgb控制3种闪电交替闪烁fixed4 albedoA=pow( albedo1*albedo2*(albedo3.r+2),_Constrast)*_lightNess*15;//电弧1亮度对比度fixed4 albedoB=pow( albedo1*albedo4*(albedo3.g+2),_Constrast)*_lightNess*15;//电弧2亮度对比度fixed3 DistDir=i.vert2world-_WorldSpaceCameraPos;//受倍镜影响fixed sqDist= dot(DistDir,DistDir);//以下是边缘交界高亮fixed ZdepthTexture = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture,UNITY_PROJ_COORD(i.scrPos)));fixed Zdiff = saturate(_IntersectWidth - abs(ZdepthTexture - i.Z0.x));//用模型的改片元的深度值 和 深度图的深度值 取差fixed4 junction=(albedo3+0.7).b*albedo5*Zdiff*5; //交界高亮float4 OutColor= _Color+junction+(albedoA*turnRGB.r+albedoB*turnRGB.g)*_viewAngle*_viewAngle*_IntersectColor/sqDist; //// OutColor.a=(1-i.Z0.y)*(1-i.Z0.y)*(1-i.Z0.y)*(1-i.Z0.y)*0.4;OutColor.a=pow(1-i.Z0.y,6)*0.4;return OutColor;}ENDCG}}
}

说明:1、以上实现了基本的毒圈显示效果,也预留了毒圈在游戏中控制大小的接口:Mul变量值。但最终还要实现在游戏中按照一定规则变化,比如毒圈开始出现的位置、暂停、缩小、加速缩小等,以后再做。2、最后做了下效率测试,没多大影响,偷个懒不贴了。

所有资源(贴图、材质、代码等)已上传,可以下载:

https://download.csdn.net/download/qq_34593121/11982510