가운데가 하프밉맵 적용한 오브젝트.
다른 스프라이트는 해상도에 따라서 좀 흐려져도 그러려니 하지만
주인공만은 어떻게든 선명하게 보여주고 싶었다.
하지만 밉맵은 1/2 사이즈로 점차 줄어드니까 그 사이에 있는 1.5 / 2에서는 좀 덜 선명한 상황 발생.
그렇다면 그 1.5 / 2에도 밉맵을 추가하면 어떨까 싶어서 만들어본 기능.
카메라 높이나 게임 해상도가 변화하면 이벤트 받아서 현재 화면상의 스프라이트 크기를 구해서
원본 스프라이트와 0.75배 스프라이트 중에서 골라서 LateUpdate에서 반영하도록 하였다.
무작정 사이즈만 0.75배로 줄인 텍스쳐를 만들면 유니티가 Non power of two라면서 신경질내므로 전용 스프라이트 아틀라스를 또 하나 뽑아줘야한다.
그리고 0.75배 텍스쳐는 Pixels Per Unit도 원본 텍스쳐의 75%로 해주어야 한다.
스프라이트 한 장 한 장을 매핑해서 Dictionary에 등록해주기 너무 귀찮았으므로 그냥 스프라이트 이름으로 구분하도록 하였다.
조잡함!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HalfMipmapSprite : MonoBehaviour {
public SpriteRenderer _sRenderer;
public Sprite[] halfMipmapSpriteList;
private Dictionary<int, Sprite> spriteNameToSpriteDic = new Dictionary<int, Sprite>();
public int originalMipmapLevel;
[ReadOnly]
public float currentSize;
[ReadOnly]
public int applyingLevel;
[ReadOnly]
public Vector2[] mipmapRanges;
private float originalSize;
private void Reset() {
if (_sRenderer == null) _sRenderer = GetComponent<SpriteRenderer>();
}
private void Awake() {
for (int i = 0; i < halfMipmapSpriteList.Length; i++) {
spriteNameToSpriteDic.Add(halfMipmapSpriteList[i].name.GetHashCode(), halfMipmapSpriteList[i]);
}
originalSize = _sRenderer.sprite.rect.size.x;
int totalLength = originalMipmapLevel + originalMipmapLevel - 1;
float unitSize = originalSize / totalLength;
float[] sizes = new float[totalLength];
float tempSize = originalSize;
for (int i = sizes.Length - 1; i >= 0; i--) {
if (i % 2 == 0) {
sizes[i] = tempSize;
tempSize = tempSize * 0.5f;
} else {
sizes[i] = (tempSize + tempSize * 2) * 0.5f;
}
}
mipmapRanges = new Vector2[totalLength];
float midSize = 0;
for (int i = 0; i < mipmapRanges.Length; i++) {
float tempNewMidSize = 99999;
if (i + 1 < mipmapRanges.Length) tempNewMidSize = (sizes[i] + sizes[i + 1]) * 0.5f;
mipmapRanges[i] = new Vector2(midSize, tempNewMidSize);
midSize = tempNewMidSize;
}
GameManager.gameResolutionChangeDGT += OnResolutionChangeEvent;
GameManager.mainCameraManageUpdateDGT += OnResolutionChangeEvent;
}
private void OnDestroy() {
GameManager.gameResolutionChangeDGT -= OnResolutionChangeEvent;
GameManager.mainCameraManageUpdateDGT -= OnResolutionChangeEvent;
}
private void OnResolutionChangeEvent() {
Vector2 spriteSize = _sRenderer.sprite.rect.size;
Vector2 pixelSize = spriteSize / _sRenderer.sprite.pixelsPerUnit;
Vector3 world_size = pixelSize;
world_size.x *= transform.lossyScale.x;
world_size.y *= transform.lossyScale.y;
Vector3 screen_size = 0.5f * world_size / Camera.main.orthographicSize;
screen_size.y *= Camera.main.aspect;
Vector3 in_pixels = new Vector3(screen_size.x * Camera.main.pixelWidth, screen_size.y * Camera.main.pixelHeight, 0) * 0.5f;
currentSize = in_pixels.x;// / spriteSize.x * originalSize;
}
private void LateUpdate() {
int hash = _sRenderer.sprite.name.GetHashCode();
if (spriteNameToSpriteDic.ContainsKey(hash)) {
for (int i = 0; i < mipmapRanges.Length; i++) {
if ((currentSize >= mipmapRanges[i].x) && (currentSize <= mipmapRanges[i].y)) {
applyingLevel = i;
if (applyingLevel % 2 == 1) {
_sRenderer.sprite = spriteNameToSpriteDic[hash];
}
break;
}
}
}
}
}