unity实现3D物体的残影效果

很久之前我写过一篇用对象池等知识实现的2D的残影效果
好像有挺多小伙伴看的添加链接描述
然后这几天我有入门了一下shader 接触了透明的效果
之后我就飘了 想实现一下3D残影的效果
但是这个仅限于unity自带的规则物体 我这用的是球(sphere)
而且我写的代码没有做优化 可能有点混乱

老规矩我还是给出demo吧
在这里插入图片描述

我这里的想法是 我弄几个小球 让后边的小球跟着前边的走
前边的后边 后边的就怎么走
这个我们利用unity的特性很容易可以实现

private void FixedUpdate()
    {
        transform.position = LastObject.position;
    }

这样就很容易的实现了小球的跟随效果

这时候我们就想到了透明的效果了
我们要用shader自己去写一个材质

Shader "Custom/Chapter"
{
     Properties{
        _MainTex("Main Texture",2D) = "white"{}
        _BaseColor("Base Color",Color) = (1.0,1.0,1.0,1.0)
        _AlphaScale("Alpha Threshold",Range(0,1)) = 1
    }

    SubShader{
        Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        //记住Transparent就完事了
        
        pass{
            ZWrite On
            ColorMask 0    // 控制该Pass不输出任何颜色
        }
        pass{
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            //关闭深度写入,同时开启混合。这里我们的混合因子选择了SrcAlpha 和OneMinueSrcAlpha
            //这两个计算因子最终可以得到半透明混合的效果。

            Tags{"LightMode"="ForwardBase"}
            //不变

            CGPROGRAM
            #pragma vertex Vertex
            #pragma fragment Pixel
            #include "Lighting.cginc"

            struct vertexInput{
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct vertexOutput{
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float2 uv : TEXCOORD2;
            };

            sampler2D _MainTex;
            fixed4 _BaseColor;
            fixed _AlphaScale;

            vertexOutput Vertex(vertexInput v){
                
                vertexOutput o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                o.uv = v.texcoord;

                return o;
            }
            fixed4 Pixel(vertexOutput i):SV_TARGET{

                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed3 albedo = tex2D(_MainTex,i.uv).xyz * _BaseColor.xyz;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                fixed3 diffuse = _LightColor0.xyz * albedo * saturate(dot(worldNormal,lightDir));

                return fixed4(diffuse + ambient,_AlphaScale);
            }

            ENDCG
            }
      }
}

然后我们可以通过c#中的方法来修改透明度 从而实现残影的效果

  private void Start()
    {
        lattmat = GetComponent<Renderer>().material;
    }
    private void Update()
    {
        lattmat.SetFloat("_AlphaScale", alpyh);
    }

之后我们就要思考 怎么能把后边的球联系起来

  public followobject lastscript;//上一个物体的脚本
    public Transform  LastObject;//上一个物体
    private  Material lattmat;//本物体的材质
    public float alpyh;//设置的透明度

之后我们在unity中赋值
在这里插入图片描述

这里的赋值都上上一个物体

然后我给出完整的源码 给大家参考

后边子物体的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class followobject : MonoBehaviour
{
    public followobject lastscript;//上一个物体的脚本
    public Transform  LastObject;//上一个物体
    private  Material lattmat;//本物体的材质
    public float alpyh;//设置的透明度


    private void Start()
    {
        lattmat = GetComponent<Renderer>().material;
    }
    private void Update()
    {
        lattmat.SetFloat("_AlphaScale", alpyh);
    }
    private void FixedUpdate()
    {
        transform.position = LastObject.position;
        if (lastscript == null)
        {
            alpyh = ConShader.Instance.a;
        }
        else
        {
            alpyh = lastscript.alpyh;
        }
       
    }
    
}

可键盘控制的物体

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConShader : MonoBehaviour
{

    public float a = 1;
    public bool isstart = false;

    public static ConShader Instance;

    private void Awake()
    {
        Instance = this;
    }

    private void Update()
    {
        transform.Translate(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Time.deltaTime * 20);
        if (isstart)
        {
            a -= Time.deltaTime;
        }
        if (a < 0)
        {
            isstart = false;
            a = 0;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            a = 1;
            isstart = true;
        }

    }
}

shader源码

Shader "Custom/Chapter"
{
     Properties{
        _MainTex("Main Texture",2D) = "white"{}
        _BaseColor("Base Color",Color) = (1.0,1.0,1.0,1.0)
        _AlphaScale("Alpha Threshold",Range(0,1)) = 1
    }

    SubShader{
        Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        //记住Transparent就完事了
        
        pass{
            ZWrite On
            ColorMask 0    // 控制该Pass不输出任何颜色
        }
        pass{
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            //关闭深度写入,同时开启混合。这里我们的混合因子选择了SrcAlpha 和OneMinueSrcAlpha
            //这两个计算因子最终可以得到半透明混合的效果。

            Tags{"LightMode"="ForwardBase"}
            //不变

            CGPROGRAM
            #pragma vertex Vertex
            #pragma fragment Pixel
            #include "Lighting.cginc"

            struct vertexInput{
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct vertexOutput{
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float2 uv : TEXCOORD2;
            };

            sampler2D _MainTex;
            fixed4 _BaseColor;
            fixed _AlphaScale;

            vertexOutput Vertex(vertexInput v){
                
                vertexOutput o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                o.uv = v.texcoord;

                return o;
            }
            fixed4 Pixel(vertexOutput i):SV_TARGET{

                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed3 albedo = tex2D(_MainTex,i.uv).xyz * _BaseColor.xyz;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                fixed3 diffuse = _LightColor0.xyz * albedo * saturate(dot(worldNormal,lightDir));

                return fixed4(diffuse + ambient,_AlphaScale);
            }

            ENDCG
            }
      }
}

希望我所写的对大家有所帮助
如果有问题可以联系我 主页有我的联系方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity是一款强大的游戏开发引擎,可以用于实现各种各样的游戏功能和效果,包括在3D物体表面上挖孔。 在Unity实现3D物体表面挖孔,一种常见的方法是使用基于几何的技术。具体步骤如下: 1. 首先,需要一个3D模型,可以使用3D建模软件或者下载现有的模型资源。 2. 在Unity中创建一个3D对象,将该模型导入到场景中。 3. 选中该模型,添加一个Collider组件,确保物体具有碰撞器。 4. 创建一个脚本文件,并将其附加到该模型上。在脚本中,我们将使用鼠标点击事件来实现挖孔的功能。 5. 在脚本中,使用鼠标点击事件获取鼠标点击位置的3D坐标。 6. 使用射线投射技术,从鼠标点击位置向物体内部发出射线。 7. 通过检测射线与物体碰撞点,获取碰撞点的位置和法线。 8. 根据碰撞点的位置和法线,使用几何运算将此处的物体顶点进行改变,模拟挖孔效果。 9. 更新物体的网格信息,使其重新生成表面。 10. 最后,根据需求,可以给挖孔区域增加一些特效,比如添加纹理、粒子效果等,以增强视觉效果。 通过以上步骤,我们在Unity中可以实现3D物体表面挖孔的效果。这种方法能够实现比较简单的挖孔操作,但如果需要更复杂的挖孔效果,可能需要使用更高级的技术,比如基于物理引擎的仿真等。 要注意的是,实现3D物体表面挖孔需要一定的计算资源和编程技巧,因此在实现过程中需要注意性能优化和代码可维护性,以确保游戏的流畅性和可扩展性。 ### 回答2: 在Unity实现3D物体表面的挖孔需要采取一定的步骤。首先,我们需要一个3D模型作为基础。可以使用Unity自带的模型创建工具(如ProBuilder)或者外部建模软件(如Blender)来创建一个具有表面挖孔功能的模型。 接下来,我们需要为模型创建一个材质,并在该材质中设置透明效果。通过修改材质的属性,可以让物体的部分区域透明显示,从而实现挖孔的效果。我们可以将这一属性称之为"透明深度",其数值可根据需要进行调整。 然后,我们需要在模型的表面确定挖孔的位置。这可以通过添加一个附加的几何网格(如一个平面或小立方体)来实现。我们可以通过将这个附加的几何网格与模型进行布尔运算,从而真正地将模型的表面切割出一个洞来。 最后,在游戏运行时,我们需要实时更新模型的材质。通过使用Raycast或者其他方法,可以检测到位置在洞上方的碰撞点,并根据该碰撞点动态地更新模型的材质透明深度,以便在运行时实时显示挖孔效果。 需要注意的是,这只是一种简单的实现方式。在实际项目中,还需要考虑更复杂的情况,如洞的形状、洞的大小和位置等。此外,在实现过程中还需要处理碰撞检测、光照和阴影等问题,以获得更真实、更优质的显示效果。但总体而言,使用Unity进行3D物体表面挖孔是可行的,只需要按照上述步骤逐步进行操作即可。 ### 回答3: Unity是一款强大的游戏引擎,可用于创建各种类型的游戏和应用程序。要实现3D物体的表面挖孔,可以通过以下步骤在Unity中完成。 首先,在Unity中创建一个3D物体,比如一个立方体或球体。可以使用内置的3D对象创建功能或导入自定义模型。 然后,为了在物体表面上创建挖孔,需要在该物体上添加网格和碰撞器组件。网格组件定义了物体的形状,并允许我们对其进行操作。碰撞器组件用于处理与其他物体的交互。 接下来,可以使用Unity的建模工具或独立的3D建模软件来创建挖孔的形状。比如,可以使用圆柱体或球体创建一个挖孔模型,然后将其放置在要挖孔的物体上。 在挖孔模型完成后,将其设置为相同网格组件上的一个子网格。这可以通过Unity中的层级面板和编辑器功能来完成。确保子网格正确放置在主物体上。 然后,在脚本中使用布尔运算来实现物体的表面进行挖孔操作。Unity中有许多脚本插件和工具可用于这个任务,比如ProBuilder和Mesh Baker。使用这些工具,可以对子网格进行布尔差异运算,以在主物体上创建挖孔效果。 最后,可以在场景中调整和优化挖孔后的物体。可以根据需要对物体进行纹理映射、光照和特殊效果的添加,以使其更加真实和逼真。 通过以上步骤,就可以在Unity实现3D物体表面的挖孔效果。这种方法可以应用于各种类型的3D模型和场景中,以创建更加复杂和精细的效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值