【Unity3D】地面网格特效

这篇具有很好参考价值的文章主要介绍了【Unity3D】地面网格特效。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 前言

        本文实现了地面网格特效,包含以下两种模式:

  • 实时模式:网格线宽度和间距随相机的高度实时变化;
  • 分段模式:将相机高度分段,网格线宽度和间距在每段中对应一个值。

【Unity3D】地面网格特效,Unity3D,# Shader,网格特效,Unity3D

        本文完整资源见→Unity3D地面网格特效。 

2 地面网格实现

        SceneController.cs

using System;
using UnityEngine;

public class SceneController : MonoBehaviour {
    private static SceneController instance; // 单例
    private Action cameraChangedHandler; // 相机状态改变处理器
    private Transform cam; // 相机

    public static SceneController Instance() { // 获取实例
        return instance;
    }

    public void AddHandler(Action handler) { // 添加处理器
        cameraChangedHandler += handler;
    }

    private void Awake() {
        instance = this;
        cam = Camera.main.transform;
    }

    private void Update() { // 更新场景(Scroll: 缩放场景, Ctrl+Drag: 平移场景, Alt+Drag: 旋转场景)
        float scroll = Input.GetAxis("Mouse ScrollWheel");
        ScaleScene(scroll);
        if ((Input.GetMouseButton(0))) {
            if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) {
                float hor = Input.GetAxis("Mouse X");
                float ver = Input.GetAxis("Mouse Y");
                MoveScene(hor, ver);
            }
            if (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) {
                float hor = Input.GetAxis("Mouse X");
                float ver = Input.GetAxis("Mouse Y");
                RotateScene(hor, ver);
            }
        }
    }

    private void ScaleScene(float scroll) { // 缩放场景
        if (Mathf.Abs(scroll) > Mathf.Epsilon) {
            cam.position += cam.forward * scroll * 50;
            cameraChangedHandler?.Invoke();
        }
    }

    private void MoveScene(float hor, float ver) { // 平移场景
        if (Mathf.Abs(hor) > Mathf.Epsilon || Mathf.Abs(ver) > Mathf.Epsilon) {
            cam.position -= (cam.right * hor * 3 + cam.up * ver * 3);
            cameraChangedHandler?.Invoke();
        }
    }

    private void RotateScene(float hor, float ver) { // 旋转场景
        if (Mathf.Abs(hor) > Mathf.Epsilon || Mathf.Abs(ver) > Mathf.Epsilon) {
            cam.RotateAround(Vector3.zero, Vector3.up, hor * 3);
            cam.RotateAround(Vector3.zero, -cam.right, ver * 3);
            cameraChangedHandler?.Invoke();
        }
    }
}

        说明:SceneController 脚本组件挂在相机对象上,这里旋转中心是固定的,如果想设置为随相机焦点自动变化,可以参考 缩放、平移、旋转场景。

        GridPlane.cs

using UnityEngine;

public class GridPlane : MonoBehaviour {
    public GridType gridType = GridType.REALTIME; // 网格类型
    private const float lineGapFactor = 0.2f; // 线段间距因子(相机距离单位长度变化时线段间距的变化量)
    private const float lineWidthFactor = 0.01f; // 线段宽度因子(相机距离单位长度变化时线段宽度的变化量)
    private const int segmentFactor = 100; // 分段因子(每隔多远分一段)
    private Transform cam; // 相机
    private float camDist; // 相机距离
    private float lineGap = 1; // 线段间距
    private float lineWidth = 0.05f; // 线段宽度
    private Vector4 planeCenter = Vector4.zero; // 地面中心
    private Material material; // 网格材质

    private void Start() {
        SceneController.Instance().AddHandler(UpdateGrid);
        cam = Camera.main.transform;
        material = Resources.Load<Material>("GridPlaneMat");
        material.SetVector("_PlaneCenter", planeCenter);
        UpdateGrid();
    }

    private void UpdateGrid() { // 更新网格
        camDist = Mathf.Abs(cam.position.y - planeCenter.y);
        if (gridType == GridType.REALTIME) {
            RealtimeUpdateGrid();
        } else if (gridType == GridType.SEGMENTED) {
            SegmentedUpdateGrid();
        }
    }

    private void RealtimeUpdateGrid() { // 实时更新网格
        lineGap = camDist * lineGapFactor;
        lineWidth = camDist * lineWidthFactor;
        UpdateMatProperties();
    }

    private void SegmentedUpdateGrid() { // 分段更新网格
        int dist = (((int) camDist) / segmentFactor + 1) * segmentFactor;
        lineGap = dist * lineGapFactor;
        lineWidth = dist * lineWidthFactor;
        UpdateMatProperties();
    }

    private void UpdateMatProperties() { // 更新材质属性
        lineGap = Mathf.Max(lineGap, lineGapFactor);
        lineWidth = Mathf.Max(lineWidth, lineWidthFactor);
        material.SetFloat("_LineGap", lineGap);
        material.SetFloat("_LineWidth", lineWidth);
    }
}

public enum GridType { // 网格类型
    REALTIME, // 实时模式(网格随相机高度实时变化)
    SEGMENTED // 分段模式(网格随相机高度分段变化)
}

        说明:GridPlane 脚本组件挂在地面对象上。

        GridPlane.shader

Shader "MyShader/GridPlane"  { // 路径上的节点移动特效
    Properties {
        _PlaneColor("Plane Color", Color) = (1, 1, 1, 1) // 地面颜色
        _LineColor("Line Color", Color) = (1, 1, 1, 1) // 线条颜色
        _LineGap("Line Gap", Int) = 1 // 线段间距
        _LineWidth("Line Width", Range(0, 1)) = 0.1 // 线段宽度
        _PlaneCenter("Plane Center", Vector) = (0, 0, 0, 0) // 地面中心
    }

    SubShader {
        Pass {
            cull off
            CGPROGRAM
 
            #include "UnityCG.cginc"
            #pragma vertex vert
            #pragma fragment frag

            float4 _PlaneColor; // 地面颜色
            float4 _LineColor; // 线条颜色
            int _LineGap; // 线段间距
            float _LineWidth; // 线段宽度
            float4 _PlaneCenter; // 地面中心

            struct v2f {
                float4 pos : SV_POSITION; // 裁剪空间顶点坐标
                float2 worldPos : TEXCOORD0; // 世界空间顶点坐标(只包含xz)
            };
 
            v2f vert(float4 vertex: POSITION) {
                v2f o;
                o.pos = UnityObjectToClipPos(vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, vertex)
                o.worldPos = mul(unity_ObjectToWorld, vertex).xz; // 将模型空间顶点坐标变换到世界空间
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                float2 vec = abs(i.worldPos - _PlaneCenter.xz);
                float2 mod = fmod(vec, _LineGap);
                float2 xz = min(mod, _LineGap - mod);
                float dist = min(xz.x, xz.y);
                float factor = 1 - smoothstep(0, _LineWidth, dist);
                fixed4 color = lerp(_PlaneColor, _LineColor, factor);
                return fixed4(color.xyz, 1);
            }

            ENDCG
        }
    }
}

        说明:在 Assets 窗口新建 Resources 目录,接着在 Resources 目录下面创建材质,重命名为 GridPlaneMat,将 GridPlane.shader 与 GridPlaneMat 材质绑定。

3 运行效果

        1)实时模式

【Unity3D】地面网格特效,Unity3D,# Shader,网格特效,Unity3D

        2)分段模式

【Unity3D】地面网格特效,Unity3D,# Shader,网格特效,Unity3D文章来源地址https://www.toymoban.com/news/detail-600388.html

到了这里,关于【Unity3D】地面网格特效的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Unity3D教程:2D游戏技能特效

    Unity3D教程:2D游戏技能特效

    在我们的2D图形游戏中不可缺少大量的光影、技能特效,像Diablo II中的魔法效果的实现,幸好我们拥有强大的CPU来为我们实现Alpha混合与色彩饱和混合,接下来让我们来讨论一下如何用这些方法来实现我们游戏中所需要的技能特效。     一、Alpha混合特效     Alpha混合可以让我

    2024年02月01日
    浏览(53)
  • Unity3D粒子系统之制作烟雾特效

    Unity3D粒子系统之制作烟雾特效

    本文将会介绍如何使用Unity内的粒子系统制作烟雾效果。 如果想了解Unity粒子系统中的基础属性,可以看这篇博客:Unity3D 粒子系统之基础属性介绍 先附上预览图: 材质贴图 首先我们需要一张烟雾材质用的材质贴图,我是自己画的,可以参考下图自己画一张或者去网上找素材

    2024年02月02日
    浏览(17)
  • Unity3D粒子系统之制作火焰特效

    Unity3D粒子系统之制作火焰特效

    本文将会介绍如何使用Unity内的粒子系统制作烟雾效果。 如果想了解Unity粒子系统中的基础属性,可以看这篇博客:Unity3D粒子系统之基础属性介绍 先上预览图吧 用自己熟悉的绘画工具画一张类似这样的图片(相似即可,白灰色部分边缘不规则),注意一定要黑底。 将画好的

    2024年02月02日
    浏览(11)
  • Unity3d 图片Image置灰shader

    置灰公式:    value=color.r x 0.299 +color.g x 0.587 + color.b * 0.114 color.rgb = lerp(color.rgb, Luminance(color.rgb), _Factor); 或 color.rgb = dot(color.rgb, fixed3(0.299, 0.587, 0.114));

    2024年02月11日
    浏览(17)
  • Unity3D Shader系列之描边

    Unity3D Shader系列之描边

    总结下描边效果的实现方式,主要有以下几种: ①法线外拓+ZTest Always ②法线外拓+Cull Front ③法线外拓+ZWrite Off ④法线外拓+模板测试 ⑤基于屏幕后处理 法线外拓的原理如下: 基本原理还是很简单的:模型渲染两次,第一次渲染时将模型的顶点沿法线方向外拓,然后绘制描边

    2023年04月08日
    浏览(45)
  • Unity3D Shader系列之深度纹理

    Unity3D Shader系列之深度纹理

    这篇总结下场景扫描的效果。场景扫描背后的原理其实挺简单,先获取相机的深度图,再获取相机绘制的画面,然后从深度图中取出当前像素的深度值,如果深度值在我们扫描线的深度值的范围内,那么当前像素的颜色就为扫描线的颜色与原画面颜色的叠加。所以实现这个效

    2023年04月11日
    浏览(11)
  • Unity3D打包Assetbundle丢失Shader问题

    Unity3D打包Assetbundle丢失Shader问题

    详情见:https://www.pianshen.com/article/5391338163/ 1、Unity3D在打包Assetbundle时,可能会遇到Shader丢失的问题,解决方法:打开 Edit-Project Settings-Graphics,在Always Included Shaders列表添加上所需的shader ,再打包即可。 2、参考 3、原文复制 Scriptable RenderLoop settings This is an experimental setting wh

    2023年04月22日
    浏览(42)
  • Unity3D Shader 引导遮罩,支持圆形、矩形、圆角矩形框

    Unity3D Shader 引导遮罩,支持圆形、矩形、圆角矩形框

    unity3D新手引导遮罩,支持圆形,矩形框,圆角矩形框。图形位置和大小可以根据控件的位置和大小调节,通用所有分辨率设备。黄色区域遮挡,只有白色区域可以点穿。 原文链接:https://www.kadastudio.cn/archives/89 ​ 将MyGuideMask挂载到脚本上,然后通过GuideMask创建材质并赋值,根据

    2024年02月11日
    浏览(16)
  • 【Unity3D赛车游戏优化篇】【十】汽车粒子特效和引擎咆哮打造极速漂移

    【Unity3D赛车游戏优化篇】【十】汽车粒子特效和引擎咆哮打造极速漂移

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 :Unity游戏demo – 😶‍🌫️版本: Unity2021 😶‍🌫️适合人群:Unity初学者进阶 😶‍🌫️学习目标:3D赛车游戏的基础制作 😶‍🌫️技能

    2024年02月09日
    浏览(24)
  • 让AI臣服,而不是被它替代!让ChatGPT为我们编写Unity3d Shaderlab的着色器(shader)

    让AI臣服,而不是被它替代!让ChatGPT为我们编写Unity3d Shaderlab的着色器(shader)

    ChatGPT的火热大家应该都有目共睹,文案工作者、翻译工作者和画师等各种行业都在被嘲即将失业。不光是这些岗位的员工,作为资深社畜程序猿也能感受到会受到冲击。网上很多人都在发ChatGPT写的代码,并开始大肆宣扬AI要取代程序员了,今天测一测使用ChatGPT来生成一些代码,

    2023年04月23日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包