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.运行项目看效果哈!