如何在Unity中创建非矩形UI?基于运行时数值生成人格图表
Got it, let's walk through exactly how to create that personality chart using Unity's RectTransform and vertex manipulation—perfect for visualizing those 0-10 scores after a quiz. Here's a practical, step-by-step implementation:
We'll treat the target Panel as a bounding rectangle where each of the four personality attributes corresponds to a direction (e.g., top, right, bottom, left). Each score (0-10) translates to a distance from the panel's center to that direction's edge—so a score of 10 means the vertex hits the panel's edge, 5 is halfway, etc. We'll then generate a custom mesh connecting these four vertices to form the personality shape.
- Create a new Canvas (use Screen Space - Overlay for simplicity, though World Space works too).
- Add a Panel as the chart's container: set its size to something like 400x400, center it on the canvas, and give it a light background color so the chart stands out.
- Optional: Add four text labels around the panel (e.g., "Openness" at top, "Conscientiousness" at right, "Extraversion" at bottom, "Neuroticism" at left) to label each attribute.
We'll make a reusable script that inherits from MaskableGraphic (Unity's base class for custom 2D graphics) to handle mesh generation. Create a new C# script called PersonalityChart:
using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(RectTransform))] public class PersonalityChart : MaskableGraphic { // Public fields to assign scores (0-10) in Inspector or via code [Range(0, 10)] public float scoreTop = 5; [Range(0, 10)] public float scoreRight = 5; [Range(0, 10)] public float scoreBottom = 5; [Range(0, 10)] public float scoreLeft = 5; // Color of the chart fill public Color chartColor = new Color(0.2f, 0.6f, 1f, 0.7f); protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); RectTransform rectTransform = GetComponent<RectTransform>(); Vector2 center = rectTransform.rect.center; Vector2 halfSize = rectTransform.rect.size / 2; // Calculate vertex positions based on scores Vector2 topVertex = center + new Vector2(0, halfSize.y * (scoreTop / 10f)); Vector2 rightVertex = center + new Vector2(halfSize.x * (scoreRight / 10f), 0); Vector2 bottomVertex = center + new Vector2(0, -halfSize.y * (scoreBottom / 10f)); Vector2 leftVertex = center + new Vector2(-halfSize.x * (scoreLeft / 10f), 0); // Convert local positions to UI space for VertexHelper Vector3[] uiVertices = new Vector3[] { topVertex, rightVertex, bottomVertex, leftVertex }; for (int i = 0; i < uiVertices.Length; i++) { uiVertices[i] = rectTransform.TransformPoint(uiVertices[i]); uiVertices[i] = transform.root.InverseTransformPoint(uiVertices[i]); } // Add vertices to the mesh UIVertex vertex = UIVertex.simpleVert; vertex.color = chartColor; vertex.position = uiVertices[0]; vh.AddVert(vertex); vertex.position = uiVertices[1]; vh.AddVert(vertex); vertex.position = uiVertices[2]; vh.AddVert(vertex); vertex.position = uiVertices[3]; vh.AddVert(vertex); // Add triangles to form a quad (two triangles make up the four-sided shape) vh.AddTriangle(0, 1, 2); vh.AddTriangle(0, 2, 3); } // Call this to update the chart after quiz completion public void UpdateScores(float top, float right, float bottom, float left) { scoreTop = Mathf.Clamp(top, 0, 10); scoreRight = Mathf.Clamp(right, 0, 10); scoreBottom = Mathf.Clamp(bottom, 0, 10); scoreLeft = Mathf.Clamp(left, 0, 10); SetVerticesDirty(); // Trigger mesh refresh } }
- Attach the
PersonalityChartscript to your base Panel. - In the Inspector, you can tweak the default scores to see the shape update in real-time.
When the user finishes their quiz, calculate the four attribute totals (each between 0-10), then call the UpdateScores method from your quiz logic:
// Example: After calculating quiz scores float opennessScore = 8; float conscientiousnessScore = 6; float extraversionScore = 4; float neuroticismScore = 7; PersonalityChart chart = FindObjectOfType<PersonalityChart>(); chart.UpdateScores(opennessScore, conscientiousnessScore, extraversionScore, neuroticismScore);
- Add an outline: Create a child Image under the Panel, set its color to a dark shade, and use a
RectMask2Don the parent to clip it to the chart shape. - Add animation: Tween the scores from 0 to their final values over 1-2 seconds for a satisfying reveal after the quiz.
- Adjust the shape: If you want a smoother look, you can add more vertices between the four main points, or use a bezier curve to round the edges.
This approach is lightweight, uses Unity's built-in UI system, and updates dynamically based on your runtime scores. Let me know if you need help tweaking any part!
内容的提问来源于stack exchange,提问作者Dtb49

