728x90
반응형
using UnityEngine;
using TMPro;
[ExecuteInEditMode]
public class CurvedText : MonoBehaviour
{
private TextMeshProUGUI _textComponent;
[SerializeField]
private AnimationCurve vertexCurve = new(new Keyframe (0.0f, 0.1f), new Keyframe (0.5f, 0.0f), new Keyframe (1.0f, 0.1f));
[SerializeField]
private float curveScale = 100.0f;
private void Awake ()
{
_textComponent = gameObject.GetComponent<TextMeshProUGUI> ();
}
private void Update ()
{
if (!_textComponent.havePropertiesChanged)
{
return;
}
UpdateCurveMesh ();
}
private void UpdateCurveMesh ()
{
_textComponent.ForceMeshUpdate();
var textInfo = _textComponent.textInfo;
var characterCount = textInfo.characterCount;
if (characterCount == 0)
return;
var boundsMinX = _textComponent.bounds.min.x;
var boundsMaxX = _textComponent.bounds.max.x;
for (int i = 0; i < characterCount; i++)
{
if (!textInfo.characterInfo [i].isVisible)
continue;
int vertexIndex = textInfo.characterInfo [i].vertexIndex;
int materialIndex = textInfo.characterInfo [i].materialReferenceIndex;
var vertices = textInfo.meshInfo [materialIndex].vertices;
Vector3 offsetToMidBaseline = new Vector2 ((vertices [vertexIndex + 0].x + vertices [vertexIndex + 2].x) / 2, textInfo.characterInfo [i].baseLine);
vertices [vertexIndex + 0] += -offsetToMidBaseline;
vertices [vertexIndex + 1] += -offsetToMidBaseline;
vertices [vertexIndex + 2] += -offsetToMidBaseline;
vertices [vertexIndex + 3] += -offsetToMidBaseline;
float x0 = (offsetToMidBaseline.x - boundsMinX) / (boundsMaxX - boundsMinX); // Character's position relative to the bounds of the mesh.
float x1 = x0 + 0.0001f;
float y0 = vertexCurve.Evaluate (x0) * curveScale;
float y1 = vertexCurve.Evaluate (x1) * curveScale;
float charSize = boundsMaxX - boundsMinX;
Vector3 horizontal = new Vector3 (1, 0, 0);
Vector3 tangent = new Vector3 (charSize * 0.0001f, y1 - y0);
float angle = Mathf.Acos (Vector3.Dot (horizontal, tangent.normalized)) * Mathf.Rad2Deg;
Vector3 cross = Vector3.Cross (horizontal, tangent);
angle = cross.z > 0 ? angle : 360 - angle;
var matrix = Matrix4x4.TRS (new Vector3 (0, y0, 0), Quaternion.Euler (0, 0, angle), Vector3.one);
vertices [vertexIndex + 0] = matrix.MultiplyPoint3x4 (vertices [vertexIndex + 0]);
vertices [vertexIndex + 1] = matrix.MultiplyPoint3x4 (vertices [vertexIndex + 1]);
vertices [vertexIndex + 2] = matrix.MultiplyPoint3x4 (vertices [vertexIndex + 2]);
vertices [vertexIndex + 3] = matrix.MultiplyPoint3x4 (vertices [vertexIndex + 3]);
vertices [vertexIndex + 0] += offsetToMidBaseline;
vertices [vertexIndex + 1] += offsetToMidBaseline;
vertices [vertexIndex + 2] += offsetToMidBaseline;
vertices [vertexIndex + 3] += offsetToMidBaseline;
}
_textComponent.UpdateVertexData ();
}
#if UNITY_EDITOR
protected virtual void OnValidate()
{
UpdateCurveMesh ();
}
private void OnEnable()
{
UpdateCurveMesh ();
}
private void OnDisable()
{
_textComponent.ForceMeshUpdate();
}
#endif
}
스크립트 작성 후 텍스트 컴포넌트에 붙여서 쓰면 된다.
728x90
반응형
'프로그래밍 > 유니티' 카테고리의 다른 글
[유니티] FPS 표기 (0) | 2022.10.05 |
---|---|
[유니티] 안드로이드 번들 빌드 오류 모음 (0) | 2022.09.26 |
[유니티] 슬라이더 값이 0인데 이미지가 남아있을 때 (0) | 2022.08.04 |
[유니티] 터치 이펙트 (Click Particle) (0) | 2022.07.12 |
[유니티] Hierarchy의 오브젝트 Path복사 (0) | 2022.03.09 |