Unity 3D饼状图效果
一. 效果展示
二.基础类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawCylinder : MonoBehaviour
{
// 网格渲染器
MeshRenderer meshRenderer;
// 网格过滤器
MeshFilter meshFilter;
// 用来存放顶点数据
List<Vector3> verts; // 顶点列表
List<int> indices; // 序号列表
public int count = 270;
private int preCount;
private int height = 1;
private Color preColor;
public Color color = Color.blue;
private Material material;
public int Index;
public static List<int> Counts = new List<int>() { 180,90,11,36,43};
private void Start()
{
Debug.Log("DrawCylinder count " + count);
verts = new List<Vector3>();
indices = new List<int>();
meshRenderer = GetComponent<MeshRenderer>();
meshFilter = GetComponent<MeshFilter>();
material = meshRenderer.material;
Generate();
}
private void Update()
{
if (preCount != count)
{
preCount = count;
verts.Clear();
indices.Clear();
Generate();
}
if (preColor != color)
{
preColor = color;
material.SetColor("_Color", color);
}
}
public void Generate()
{
int avgAngle = 1;
Vector3 twoVert = new Vector3(1, 0, 0);
for (int i = 0; i < count; i++)
{
int angle = avgAngle * (i + 1);
verts.Add(Vector3.zero);
verts.Add(twoVert);
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(new Vector3(0, -height, 0));
verts.Add(twoVert + new Vector3(0, -height, 0));
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), -height, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(twoVert);
verts.Add(twoVert + new Vector3(0, -height, 0));
verts.Add(Vector3.zero);
verts.Add(twoVert + new Vector3(0, -height, 0));
verts.Add(new Vector3(0, -height, 0));
verts.Add(Vector3.zero);
verts.Add(Vector3.zero);
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), -height, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), -height, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(new Vector3(0, -height, 0));
verts.Add(Vector3.zero);
verts.Add(twoVert);
verts.Add(twoVert + new Vector3(0, -height, 0));
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(twoVert + new Vector3(0, -height, 0));
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), -height, -Mathf.Sin(angle * Mathf.Deg2Rad)));
verts.Add(new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, -Mathf.Sin(angle * Mathf.Deg2Rad)));
for (int j = i * 24; j < 24 * (i + 1); j++)
{
indices.Add(j);
}
twoVert = new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, -Mathf.Sin(angle * Mathf.Deg2Rad));
}
Mesh mesh = new Mesh();
mesh.SetVertices(verts);
mesh.SetIndices(indices, MeshTopology.Triangles, 0);
// 自动计算法线
mesh.RecalculateNormals();
// 自动计算物体的整体边界
mesh.RecalculateBounds();
// 将mesh对象赋值给网格过滤器,就完成了
meshFilter.mesh = mesh;
//设置角度
int c = 0;
for (int i = 0; i < Counts.Count; i++)
{
if (i > Index)
{
break;
}
c += Counts[i];
transform.localEulerAngles = new Vector3(0, -c, 0);
}
//设置位置
int max = 0;
for (int i = 0; i < Counts.Count; i++)
{
if (Counts[i] > max)
{
max = Counts[i];
}
}
if (max == count)
{
transform.localScale = new Vector3(1, 1, 1);
transform.localPosition = Vector3.zero;
}
else
{
float h = count * 1f / max;
transform.localScale = new Vector3(1, h, 1);
transform.localPosition = new Vector3(0, -(height - h), 0);
}
}
}
三.UI目录
四. 子节点上添加MeshRender和MeshFilter组件, 把DrawCylinder脚本挂在每个子节点上,调整参数,count占的份额,总份额是360,index是索引。注意,子节点上面显示的count和index,需要和DrawCylinder类里面的Counts列表索引和数额对应一样。
五.给子节点换上Cull Off 的材质,新建材质球,把shader拖到材质球上,再把材质球给到每个子节点,shader代码如下
Shader "Unlit/DrawCylinderShader"
{
Properties
{
_Color ("Color", Color) = (0,0,0,0)
_Diffuse("Diffuse", Color) = (1,1,1,1)
_Value("Diffuse", float) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
fixed4 _Color;
uniform fixed4 _Diffuse;
float _Value;
struct v2f
{
float2 uv : TEXCOORD0;
float3 worldNormal:TEXCOORD1;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 lambert = saturate(dot(worldNormal, worldLightDir));
fixed3 albedo = (lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz) * _Value;
return fixed4(_Color.xyz * albedo,1) ;
}
ENDCG
}
}
}