SetAtlasUvs.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. #if UNITY_EDITOR
  4. using UnityEditor;
  5. #endif
  6. [ExecuteInEditMode]
  7. public class SetAtlasUvs : MonoBehaviour
  8. {
  9. [SerializeField] private bool updateEveryFrame = false;
  10. private Renderer render;
  11. private SpriteRenderer spriteRender;
  12. private Image uiImage;
  13. private bool isUI = false;
  14. void Start()
  15. {
  16. if (GetRendererReferencesIfNeeded()) GetAndSetUVs();
  17. if (!updateEveryFrame && Application.isPlaying) this.enabled = false;
  18. }
  19. void OnWillRenderObject()
  20. {
  21. if (updateEveryFrame)
  22. {
  23. GetAndSetUVs();
  24. }
  25. }
  26. public void GetAndSetUVs()
  27. {
  28. if (!GetRendererReferencesIfNeeded()) return;
  29. if (!isUI)
  30. {
  31. Rect r = spriteRender.sprite.rect;
  32. r.x /= spriteRender.sprite.texture.width;
  33. r.width /= spriteRender.sprite.texture.width;
  34. r.y /= spriteRender.sprite.texture.height;
  35. r.height /= spriteRender.sprite.texture.height;
  36. render.sharedMaterial.SetFloat("_MinXUV", r.xMin);
  37. render.sharedMaterial.SetFloat("_MaxXUV", r.xMax);
  38. render.sharedMaterial.SetFloat("_MinYUV", r.yMin);
  39. render.sharedMaterial.SetFloat("_MaxYUV", r.yMax);
  40. }
  41. else
  42. {
  43. Rect r = uiImage.sprite.rect;
  44. r.x /= uiImage.sprite.texture.width;
  45. r.width /= uiImage.sprite.texture.width;
  46. r.y /= uiImage.sprite.texture.height;
  47. r.height /= uiImage.sprite.texture.height;
  48. uiImage.material.SetFloat("_MinXUV", r.xMin);
  49. uiImage.material.SetFloat("_MaxXUV", r.xMax);
  50. uiImage.material.SetFloat("_MinYUV", r.yMin);
  51. uiImage.material.SetFloat("_MaxYUV", r.yMax);
  52. }
  53. }
  54. public void ResetAtlasUvs()
  55. {
  56. if (!GetRendererReferencesIfNeeded()) return;
  57. if (!isUI)
  58. {
  59. render.sharedMaterial.SetFloat("_MinXUV", 0f);
  60. render.sharedMaterial.SetFloat("_MaxXUV", 1f);
  61. render.sharedMaterial.SetFloat("_MinYUV", 0f);
  62. render.sharedMaterial.SetFloat("_MaxYUV", 1f);
  63. }
  64. else
  65. {
  66. uiImage.material.SetFloat("_MinXUV", 0f);
  67. uiImage.material.SetFloat("_MaxXUV", 1f);
  68. uiImage.material.SetFloat("_MinYUV", 0f);
  69. uiImage.material.SetFloat("_MaxYUV", 1f);
  70. }
  71. }
  72. public void UpdateEveryFrame(bool everyFrame)
  73. {
  74. updateEveryFrame = everyFrame;
  75. }
  76. private bool GetRendererReferencesIfNeeded()
  77. {
  78. if (spriteRender == null) spriteRender = GetComponent<SpriteRenderer>();
  79. if (spriteRender != null)
  80. {
  81. if (spriteRender.sprite == null)
  82. {
  83. #if UNITY_EDITOR
  84. EditorUtility.DisplayDialog("No sprite found", "The object: " + gameObject.name + ",has Sprite Renderer but no sprite", "Ok");
  85. #endif
  86. return false;
  87. }
  88. if (render == null) render = GetComponent<Renderer>();
  89. isUI = false;
  90. }
  91. else
  92. {
  93. if (uiImage == null)
  94. {
  95. uiImage = GetComponent<Image>();
  96. if (uiImage != null)
  97. {
  98. #if UNITY_EDITOR
  99. Debug.Log("You added the SetAtlasUv component to: " + gameObject.name + " that has a UI Image\n " +
  100. "This SetAtlasUV component will only work properly on UI Images if each Image has a DIFFERENT material instance (See Documentation Sprite Atlases section for more info)");
  101. #endif
  102. }
  103. else
  104. {
  105. #if UNITY_EDITOR
  106. EditorUtility.DisplayDialog("No Valid Renderer Component Found", "Looks like you have no Sprite Renderer or UI Image on: '"
  107. + gameObject.name + "'\n This SetAtlasUV component will now get destroyed", "Ok");
  108. #endif
  109. DestroyImmediate(this);
  110. return false;
  111. }
  112. }
  113. if (render == null) render = GetComponent<Renderer>();
  114. isUI = true;
  115. }
  116. if (spriteRender == null && uiImage == null)
  117. {
  118. #if UNITY_EDITOR
  119. EditorUtility.DisplayDialog("No Sprite Renderer", "Looks like you are missing a Sprite Renderer on: '"
  120. + gameObject.name + "'\n SetAtlasUvs only works with Sprite Renderers since it needs a 'sharedMaterial' property that UI images lack." +
  121. " This SetAtlasUV component will now get destroyed", "Ok");
  122. #endif
  123. DestroyImmediate(this);
  124. return false;
  125. }
  126. return true;
  127. }
  128. }