模型的剖切功能需要将模型的材质shader进行特定的更改,需要一定的语言功底,下面将附上挂在需要被剖切的模型上的代码以及需要自己添加的新的shader代码。
这些ui需要自己进行添加。
解下来是挂在模型上的脚本:
using UnityEngine;
using UnityEngine.UI;
public class PoushiDemo : MonoBehaviour
{
public Slider sliderX;
public Slider sliderY;
public Slider sliderZ;
public Image image;
public Shader cutShader;
private Vector3 cutNormal;
private string cutAxis;
private bool cuttingEnabled = false; // 剖切功能的开关
private Renderer[] renderers;
private Shader[][] originalShaders;
void Start()
{
if (cutShader == null)
{
Debug.LogError("Cut Shader is not specified!");
return;
}
renderers = GetComponentsInChildren<Renderer>();
if (renderers.Length == 0)
{
Debug.LogError("No Renderer component found on children!");
return;
}
originalShaders = new Shader[renderers.Length][];
for (int i = 0; i < renderers.Length; i++)
{
originalShaders[i] = new Shader[renderers[i].materials.Length];
for (int j = 0; j < renderers[i].materials.Length; j++)
{
originalShaders[i][j] = renderers[i].materials[j].shader;
}
}
Bounds totalBounds = renderers[0].bounds;
for (int i = 1; i < renderers.Length; i++)
{
totalBounds.Encapsulate(renderers[i].bounds);
}
sliderX.minValue = totalBounds.min.x;
sliderX.maxValue = totalBounds.max.x;
sliderX.value = sliderX.minValue;
sliderX.onValueChanged.AddListener(delegate { cutAxis = "x"; UpdateCutNormal(); });
sliderY.minValue = totalBounds.min.y;
sliderY.maxValue = totalBounds.max.y;
sliderY.value = sliderY.minValue;
sliderY.onValueChanged.AddListener(delegate { cutAxis = "y"; UpdateCutNormal(); });
sliderZ.minValue = totalBounds.min.z;
sliderZ.maxValue = totalBounds.max.z;
sliderZ.value = sliderZ.minValue;
sliderZ.onValueChanged.AddListener(delegate { cutAxis = "z"; UpdateCutNormal(); });
SwitchCuttingMaterial(cuttingEnabled);
}
public void ToggleCutting()
{
cuttingEnabled = !cuttingEnabled;
SwitchCuttingMaterial(cuttingEnabled);
image.gameObject.SetActive(!image.gameObject.activeSelf);
}
void SwitchCuttingMaterial(bool cutting)
{
for (int i = 0; i < renderers.Length; i++)
{
Renderer renderer = renderers[i];
if (renderer.materials.Length > 0)
{
Material[] materials = new Material[renderer.materials.Length];
for (int j = 0; j < renderer.materials.Length; j++)
{
Material originalMaterial = renderer.materials[j];
Material newMaterial = new Material(cutting ? cutShader : originalShaders[i][j]);
newMaterial.color = originalMaterial.color;
materials[j] = newMaterial;
}
renderer.materials = materials;
}
}
}
void UpdateCutNormal()
{
switch (cutAxis)
{
case "x":
cutNormal = Vector3.right;
break;
case "y":
cutNormal = Vector3.up;
break;
case "z":
cutNormal = Vector3.forward;
break;
}
}
private void Update()
{
if (!cuttingEnabled || cutShader == null || sliderX == null || sliderY == null || sliderZ == null)
{
return;
}
Vector4 cutPos = new Vector4(sliderX.value, sliderY.value, sliderZ.value, 0);
foreach (Renderer renderer in renderers)
{
if (renderer.materials.Length > 0)
{
foreach (Material material in renderer.materials)
{
material.SetVector("_CutPos", cutPos);
material.SetVector("_CutNormal", cutNormal);
}
}
}
}
}
shader的Demo如有需要请关注加私信,谢谢!
(在校生的第一次博客!)