if (_currentHighlightTarget?.targetCollider != null)
{
if (target?.targetCollider != _currentHighlightTarget?.targetCollider)
_currentHighlightTarget?.targetCollider?.GetComponentInChildren<OutlineDrawer>(true)?.SetActive(false);
}
target?.targetCollider?.GetComponentInChildren<OutlineDrawer>(true)?.SetActive(true);
_currentHighlightTarget = target;
InteractSystem
클래스에서 매 프레임 상호작용을 할 수 있는 오브젝트를 검사하고 있다.
검사를 진행하고 현재 시점에 상호작용이 가능한 오브젝트에게 아웃라인으로 하이라이트 효과를 줘서 유저가 시각적으로 볼 수 있는 기능을 추가하려한다.
하지만, 탐색은 OverlapSphere()
를 이용해서 받아온 Collider
객체들을 이용하고 있고, 이 콜라이더 객체들에게 GetComponentInChildren<OutlineDrawer>(true)
를 매 프레임 진행하는 것은 살짝 무거운 작업이 될 것 같았다.
public class OutlineManager
{
private Dictionary<UnityEngine.Object, OutlineDrawer> _outlineDict;
public void RegistOutlineDrawer(UnityEngine.Object key, OutlineDrawer drawer)
{
_outlineDict.TryAdd(key, drawer);
}
public void ReleaseOutlineDrawer(UnityEngine.Object key)
{
_outlineDict.Remove(key);
}
public OutlineDrawer FindOutlineDrawer(UnityEngine.Object key)
{
if (key == null)
return null;
_outlineDict.TryGetValue(key, out var drawer);
return drawer;
}
...
}
public class OutlineDrawer : MonoBehaviour
{
...
private OutlineManager _manager;
[SerializeField] private UnityEngine.Object _managedKeyObject;
private void Awake() => Initialize();
private void OnDestroy() => Dispose();
private void Initialize()
{
...
_manager.RegistOutlineDrawer(_managedKeyObject, this);
}
public void Dispose()
{
_manager?.ReleaseOutlineDrawer(_managedKeyObject);
}
...
}
OutlineDrawer
는 생성되면 OutlineManager
에게 자신을 등록한다.
딕셔너리에 등록하는 것이기 때문에, 인스펙터에서 Key로 사용할 오브젝트를 할당해줬다.
InteractSystem
은 Collider
를 이용해 검색할 것이기 때문에 InteractSystem
에 의해 검출되는 Collider
를 _managedKeyObject
에 할당했다.
public class InteractSystem
{
...
private void HighlightTarget(InteractableTarget? target)
{
GameManager.OutlineManager.TryHighlightObject(target?.targetCollider);
}
}
public class OutlineManager
{
private Dictionary<UnityEngine.Object, OutlineDrawer> _outlineDict;
private OutlineDrawer _currentHighlight;
...
public bool TryHighlightObject(UnityEngine.Object key)
{
var drawer = FindOutlineDrawer(key);
bool res = false;
if (drawer != _currentHighlight)
{
if (_currentHighlight != null)
_currentHighlight.SetActive(false);
if (drawer != null)
{
drawer.SetActive(true);
res = true;
}
}
_currentHighlight = drawer;
return res;
}
public OutlineDrawer FindOutlineDrawer(UnityEngine.Object key)
{
if (key == null)
return null;
_outlineDict.TryGetValue(key, out var drawer);
return drawer;
}
}
InteractSystem
이 엄선한 콜라이더를 넘겨주면, OutlineManager
에서는 넘겨받은 키를 이용해 새로운 아웃라인을 검색한 다음, 이전의 아웃라인을 끄고 새로운 아웃라인을 켠다 !
이전에는 예외처리도 InteractSystem
에서 모두 진행해서 되게 지저분했는데, 가독성도 많이 좋아졌다는 느낌이 든다.