삼각형 그래프를 그리고 싶었는데 LineRender는 잘 안되고...
어쩔 수 없이 Mesh를 활용해서 삼각형 그래프를 그려보는 방식으로 시도해봤습니다.
결과는 아래 움짤과 같이 잘 작동하나 코드에 문제가 있을 수 있으니.. 조심히 사용하시길 바랍니다.
코드
using System.Collections.Generic;
using UnityEngine;
namespace IslandMonkey
{
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
#if UNITY_EDITOR
[ExecuteAlways]
#endif
public class PieChartOutline : MonoBehaviour
{
[SerializeField, Range(0,5f)] private float convenience = 2f;
[SerializeField, Range(0,5f)] private float fun = 2f;
[SerializeField, Range(0,5f)] private float productivity = 2f;
[SerializeField, Range(0.1f, 1f)] private float circleSize = 0.2f;
[SerializeField] private Sprite circleSprite;
[SerializeField] private Material material;
private Mesh mesh;
private Dictionary<int, GameObject> circleObjects = new ();
private MeshFilter cachedMeshFilter;
private MeshRenderer cachedMeshRenderer;
private void Awake()
{
cachedMeshFilter = GetComponent<MeshFilter>();
cachedMeshRenderer = GetComponent<MeshRenderer>();
}
private void Start()
{
CreateMesh();
}
private void CreateMesh()
{
mesh = new Mesh
{
name = "PieChartOutlineMesh"
};
Vector3 center = Vector3.zero;
Vector3 top = center + Vector3.up * Convenience; // Todo : From Saved Convenience Value
Vector3 left = center + Quaternion.Euler(0f, 0f, 120f) * (Vector3.up * Fun); // Todo : From Saved Fun Value
Vector3 right = center + Quaternion.Euler(0f, 0f, -120f) * (Vector3.up * Productivity); // Todo : From Saved Productivity Value
// Define vertices (only need vertices for the outline)
Vector3[] vertices = new Vector3[] { top, left, right };
// Define edges (outline lines)
int[] indices = new int[]
{
0, 1, // Line 1: top -> left
1, 2, // Line 2: left -> right
2, 0, // Line 3: right -> top
};
mesh.vertices = vertices;
mesh.SetIndices(indices, MeshTopology.Lines, 0); // Use MeshTopology. Lines to draw lines between vertices
MeshFilter meshFilter = cachedMeshFilter;
meshFilter.mesh = mesh;
MeshRenderer meshRenderer = cachedMeshRenderer;
meshRenderer.material = material;
if (circleObjects.Count <= 0)
{
InstantiateCircleAtVertex(top, 0);
InstantiateCircleAtVertex(left, 1);
InstantiateCircleAtVertex(right, 2);
}
}
private void UpdateMesh()
{
if (circleObjects.Count <= 0) return;
Vector3 center = Vector3.zero;
Vector3 top = center + Vector3.up * Convenience;
Vector3 left = center + Quaternion.Euler(0f, 0f, 120f) * (Vector3.up * Fun);
Vector3 right = center + Quaternion.Euler(0f, 0f, -120f) * (Vector3.up * Productivity);
// Define vertices (only need vertices for the outline)
Vector3[] vertices = new Vector3[] { top, left, right };
// Define edges (outline lines)
int[] indices = new int[]
{
0, 1, // Line 1: top -> left
1, 2, // Line 2: left -> right
2, 0, // Line 3: right -> top
};
mesh.vertices = vertices;
mesh.SetIndices(indices, MeshTopology.Lines, 0); // Use MeshTopology. Lines to draw lines between vertices
MeshFilter meshFilter = cachedMeshFilter;
meshFilter.mesh = mesh;
MeshRenderer meshRenderer = cachedMeshRenderer;
meshRenderer.material = material;
ChangeCircleAtVertex(top, 0);
ChangeCircleAtVertex(left, 1);
ChangeCircleAtVertex(right, 2);
}
private void InstantiateCircleAtVertex(Vector3 vertexPosition, int point)
{
if (transform.childCount > 2) return;
GameObject circleObj = new GameObject("CircleSprite");
circleObj.transform.parent = transform;
circleObj.transform.localPosition = new Vector3(vertexPosition.x, vertexPosition.y, -0.5f);
SpriteRenderer spriteRenderer = circleObj.AddComponent<SpriteRenderer>();
spriteRenderer.sprite = circleSprite;
spriteRenderer.sortingLayerName = "UI";
spriteRenderer.sortingOrder = 2;
circleObj.transform.localScale = new Vector3(CircleSize, CircleSize, 1f);
circleObjects.Add(point, circleObj);
}
private void ChangeCircleAtVertex(Vector3 vertexPosition, int point)
{
// Check if the circleObjects dictionary contains the specified point key
if (circleObjects.ContainsKey(point))
{
GameObject circleObj = circleObjects[point];
if (circleObj != null)
{
circleObj.transform.localScale = new Vector3(CircleSize, CircleSize, 1f);
circleObj.transform.localPosition = new Vector3(vertexPosition.x, vertexPosition.y, -0.5f);
}
else
{
// Handle case where the GameObject has been destroyed or is null
Debug.LogWarning("Circle GameObject is null or destroyed.");
// Optionally, remove the key from the dictionary if needed
//circleObjects.Remove(point);
}
}
else
{
Debug.LogWarning($"Circle GameObject for point {point} not found in dictionary.");
}
}
#if UNITY_EDITOR
private void OnValidate()
{
UpdateMesh();
}
#endif
}
}