(转载)[海莉zhe] 【每日一记】Unity3D 实战练习-实现物体的镜像 (十四)

本文介绍了一种在Unity中实现物体镜像的方法,通过MeshFilter和MeshRenderer组件操作顶点和网格信息,按指定轴向和距离克隆新对象。文章详细展示了MeshMirrorManager.cs组件类的具体代码,包括镜像方向、距离、材质透明度和颜色的设定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.manew.com/thread-140831-1-1.html

 

 

最近在学习如何实现物体的镜像,练习了一个简单的例子,然后和大家一起探讨一下哈!物体镜像的操作实际上是通过一个模型的MeshFilter 和 MeshRenderer 来获取模型的顶点和网格的信息,按指定的轴向、指定的距离来克隆一个新对象,简单来讲,就是克隆了一个含有MeshRenderer的对象。                            
             好吧!废话不多讲,我们直接进入实战吧!
 

            1. 需要新建一个含有Mesh Filter组件和Mesh Renderer 组件的对象;

 

                


 

            2. 直接增加 MeshMirrorManager.cs 组件类,并且附加对象上;

               具体代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
 
/// <summary>
/// 镜像方向
/// </summary>
public enum MeshMirrorDir
{
    X,
    Y,
    Z
}
 
/// <summary>
/// 显示的模式
/// </summary>
public enum MeshRendererMode
{
    Opaque,//不透明
    Cutout,//镂空
    Fade,//淡入淡出
    Transparent,//透明
}
 
/// <summary>
/// 对象镜像管理类
/// </summary>
public class MeshMirrorManager : MonoBehaviour {
 
    /// <summary>
    /// 镜像方向
    /// </summary>
    public MeshMirrorDir m_mirrorDir;
 
    /// <summary>
    /// 镜像与对象距离
    /// </summary>
    public float m_mirrorDistance=2.0f;
 
    /// <summary>
    /// 镜像材质透明度
    /// </summary>
    [Range(0.1f, 1.0f)]
    public float m_mirrorMaterialAlpha = 0.5f;
 
    /// <summary>
    /// 镜像材质颜色
    /// </summary>
    public Color m_mirrorMaterialColor = Color.white;
 
    MeshFilter _meshFilter;
    MeshRenderer _meshRenderer;
 
    void Start () 
    {
        _meshFilter = GetComponent<MeshFilter> ();
        _meshRenderer = GetComponent<MeshRenderer> ();
 
        GenerateMirror();
    }
 
 
    private void GenerateMirror()
    {
        if ( _meshFilter== null &&  _meshRenderer== null)
        {
            Debug.Log("请确认对象已附加MeshFilter或MeshRenderer组件");
        }
 
        GameObject mirror = new GameObject("Mirror");
        mirror.transform.position = this.transform.position;
        mirror.transform.rotation = this.transform.rotation;
        mirror.transform.localScale = this.transform.localScale;
        mirror.transform.SetParent(this.transform);
 
        mirror.AddComponent<MeshFilter>();
        mirror.AddComponent<MeshRenderer>();
 
        //镜像的网格
        Mesh mesh = new Mesh();
        mesh.Clear();
        mesh.vertices = GenerateVertices(_meshFilter.mesh.vertices);
        mesh.triangles = GenerateTriangles(_meshFilter.mesh.triangles);
        mesh.uv=GetComponent<MeshFilter>().mesh.uv;
        mesh.name = "mirror";
        //重新计算发现(刷新显示)
        mesh.RecalculateNormals();
        mirror.GetComponent<MeshFilter>().mesh = mesh;
        mirror.GetComponent<MeshRenderer>().material = GenerateMaterial(_meshRenderer.material);
    }
 
    /// <summary>
    /// 生成镜像顶点
    /// </summary>
    /// <param name="backVertices">原游戏对象的顶点</param>
    /// <returns></returns>
    private Vector3[] GenerateVertices(Vector3[] backVertices)
    {
        Vector3[] newVertices = backVertices;
 
        switch(m_mirrorDir)
        {
        case MeshMirrorDir.X:
            for (int i = 0; i <= newVertices.Length - 1;i++ )
            {
                newVertices[i].x = newVertices[i].x * -1 + m_mirrorDistance;
            }
            break;
        case MeshMirrorDir.Y:
            for (int i = 0; i <= newVertices.Length - 1; i++)
            {
                newVertices[i].y = newVertices[i].y * -1 + m_mirrorDistance;
            }
            break;
        case MeshMirrorDir.Z:
            for (int i = 0; i <= newVertices.Length - 1; i++)
            {
                newVertices[i].z = newVertices[i].z * -1 + m_mirrorDistance;
            }
            break;
        default:
            break;
        }
 
        return newVertices;
    }
 
 
 
    /// <summary>
    /// 生成镜像三角面
    /// </summary>
    /// <param name="backTriangles">各个顶点的渲染顺序</param>
    /// <returns></returns>
    int[] GenerateTriangles(int[] backTriangles)
    {
        int[] newTriangles = new int[backTriangles.Length];
        //将所有面的顶点渲染顺序颠倒
        for (int i = 0; i < newTriangles.Length; i++)
        {
            newTriangles[newTriangles.Length - i - 1] = backTriangles[i];
        }
 
        return newTriangles;
    }
 
    /// <summary>
    /// 生成材质球
    /// </summary>
    /// <returns>原材质球</returns>
    /// <param name="backMeterial">复制后的材质球</param>
    private Material GenerateMaterial(Material backMeterial)
    {
        Material newMaterial = new Material(backMeterial);
        //不透明
        if (m_mirrorMaterialAlpha >= 1.0f)
        {
            SetMaterialRenderingMode(newMaterial, MeshRendererMode.Opaque);
            if (newMaterial.HasProperty("_Color"))
            {
                newMaterial.SetColor("_Color", m_mirrorMaterialColor);
            }
        }
        //透明
        else
        {
            SetMaterialRenderingMode(newMaterial, MeshRendererMode.Fade);
            if (newMaterial.HasProperty("_Color"))
            {
                m_mirrorMaterialColor.a = m_mirrorMaterialAlpha;
                newMaterial.SetColor("_Color", m_mirrorMaterialColor);
            }
        }
 
        return newMaterial;
    }
 
 
    /// <summary>
    /// 设置纹理渲染模式
    /// </summary>
    /// <param name="material"></param>
    /// <param name="renderingMode"></param>
    private void SetMaterialRenderingMode(Material material, MeshRendererMode renderingMode)
    {
        switch (renderingMode)
        {
        case MeshRendererMode.Opaque:
            material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
            material.SetInt("_ZWrite", 1);
            material.DisableKeyword("_ALPHATEST_ON");
            material.DisableKeyword("_ALPHABLEND_ON");
            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
            material.renderQueue = -1;
            break;
        case MeshRendererMode.Cutout:
            material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
            material.SetInt("_ZWrite", 1);
            material.EnableKeyword("_ALPHATEST_ON");
            material.DisableKeyword("_ALPHABLEND_ON");
            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
            material.renderQueue = 2450;
            break;
        case MeshRendererMode.Fade:
            material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
            material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            material.SetInt("_ZWrite", 0);
            material.DisableKeyword("_ALPHATEST_ON");
            material.EnableKeyword("_ALPHABLEND_ON");
            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
            material.renderQueue = 3000;
            break;
        case MeshRendererMode.Transparent:
            material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            material.SetInt("_ZWrite", 0);
            material.DisableKeyword("_ALPHATEST_ON");
            material.DisableKeyword("_ALPHABLEND_ON");
            material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
            material.renderQueue = 3000;
            break;
        }
    }
}


            3.运行项目看效果哈!


              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值