一、在地形周围创建圆环
效果:
地形创建圆环
用途:显示角色周围某个范围(攻击、移动、视野)
注意事项: 需要准备地形几何,涉及着色器与C#脚本配合、C#动态获得当前角色的世界坐标并传送给着色器,需要取得角色当前在地形上的世界坐标
步骤:
1.首先创建一个名为RadiusShader的着色器和一个名为Radius的材质。
2.准备一个角色,我们会在这个角色周围画出一个圆。
3.从菜单中选择 GameObject|3D Object|Terrain来创建一个新地形。
4.给地形创建一定的几何结构。可以导入一个已有的结构或者使用工具来创建一个新的(Raise/Lower Terrain,Paint Height,Smooth Height).
5.在Unity中,地形是一类特殊的对象,地形上的纹理映射也和传统的三维模型上的纹理映射有所不同。不能通过着色器提供一个_MainTex纹理,因为地形需要自己提供纹理。步骤是选择 Paint Texture,然后单击 Add Texture
6.现在纹理已经设置好了,你可以修改地形的材质,通过这个材质就可以应用我们的自定义着色器。从Terrain Settings 中修改 Material 属性为Custom,然后将 Radius 材质拖曳到Custom Material栏。
之后编辑RadiusShader文件
代码:
Shader "Custom/RadiusShader"
{
Properties
{
_Center("Center",Vector)=(0,0,0,0)
_Radius("Radius",Float)=0.5
_RadiusColor("Radius Color",Color)=(1,0,0,1)
_RadiusWidth("Radius Width",Float)=2
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
float3 worldPos;
};
float3 _Center;
float _Radius;
fixed4 _RadiusColor;
float _RadiusWidth;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
float d = distance(_Center, IN.worldPos);//距离中心
if (d > _Radius && d < _Radius + _RadiusWidth) //半径
{
o.Albedo = _RadiusColor;
}
else {
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;//颜色
}
}
ENDCG
}
FallBack "Diffuse"
}
7.创建一个移动圆环,使圆环跟着角色走:给角色添加一个名为Radius的C#脚本,加入角色移动和圆环绘制的代码。
代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Radius : MonoBehaviour
{
public Material radiusMaterial;
public float radius = 80;
public Color color = Color.red;
public float movespeed = 20;
//public float rotatespeed = 40;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
radiusMaterial.SetVector("_Center", transform.position);//变量类型对应角色
radiusMaterial.SetFloat("_Radius", radius);
radiusMaterial.SetVector("_RadiusColor", color);
//控制角色的移动
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
transform.Translate(new Vector3(horizontal, 0, vertical) * Time.deltaTime * movespeed);
}
}
二、实现砖缝积沙效果
效果:
沙子
原理:
代码:
Shader "mya/terrainTextrueBlend" {
Properties{
_Splat0("Layer 1(RGBA)", 2D) = "white" {}
_Splat1("Layer 2(RGBA)", 2D) = "white" {}
//_Splat2("Layer 3(RGBA)", 2D) = "white" {}
//_Splat3("Layer 4(RGBA)", 2D) = "white" {}
//_Control("Control (RGBA)", 2D) = "white" {}
_Weight("Blend Weight" , Range(0.001,1)) = 0.2
}
SubShader{
Tags
{
"RenderType" = "Opaque"
"Queue" = "Geometry"
}
CGPROGRAM
#pragma surface surf BlinnPhong
#pragma target 3.0
struct Input
{
//float2 uv_Control : TEXCOORD0;
float2 uv_Splat0 : TEXCOORD1;
float2 uv_Splat1 : TEXCOORD2;
};
sampler2D _Splat0,_Splat1;
float4 _Tiling3;
float _Weight;
inline half4 Blend(half high1 ,half high2,half high3,half high4 )
{
half4 blend;
blend.r = high1 ;
blend.g = high2 ;
blend.b = high3 ;
blend.a = high4 ;
half ma = max(blend.r, max(blend.g, max(blend.b, blend.a)));
blend = max(blend - ma + _Weight , 0) ;
return blend / (blend.r + blend.g + blend.b + blend.a);
}
void surf(Input IN, inout SurfaceOutput o) {
//half4 splat_control = tex2D(_Control, IN.uv_Control).rgba;
half4 lay1 = tex2D(_Splat0, IN.uv_Splat0);//实例化
half4 lay2 = tex2D(_Splat1, IN.uv_Splat1);
// half4 lay3 = tex2D(_Splat2, IN.uv_Splat2);
// half4 lay4 = tex2D(_Splat3, IN.uv_Splat3);
half4 blend = Blend(lay1.a,lay2.a,lay1.a,lay2.a);
o.Alpha = 0.0;
o.Albedo.rgb = blend.r * lay1 + blend.g * lay2 ;//混合
}
ENDCG
}
FallBack "Specular"
}