1. 程式人生 > >(轉載)[海莉zhe] 【每日一記】Unity3D 實戰練習-實現物體的映象 (十四)

(轉載)[海莉zhe] 【每日一記】Unity3D 實戰練習-實現物體的映象 (十四)

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.執行專案看效果哈!