인터랙션 하이라이트 세팅 노출, 연출 추가

This commit is contained in:
Jeonghyeon Ha 2025-08-14 14:08:10 +09:00
parent 2d4edba36c
commit 566a034fdd

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Sirenix.OdinInspector;
using QualityLevel = HighlightPlus.QualityLevel; using QualityLevel = HighlightPlus.QualityLevel;
using HighlightPlus; using HighlightPlus;
namespace DDD namespace DDD
@ -15,10 +15,13 @@ public enum InteractionOutlineType
Objective Objective
} }
[System.Serializable]
public struct InteractionOutlineData public struct InteractionOutlineData
{ {
public Color Color; public Color Color;
[Range(0.1f, 5f)]
public float Width; public float Width;
[Range(0f, 1f)]
public float Opacity; public float Opacity;
} }
@ -27,32 +30,77 @@ public struct InteractionOutlineData
[AddComponentMenu("DDD/Interaction/InteractableHighlight")] [AddComponentMenu("DDD/Interaction/InteractableHighlight")]
public class InteractableHighlight : MonoBehaviour public class InteractableHighlight : MonoBehaviour
{ {
public static Dictionary<InteractionOutlineType, InteractionOutlineData> OutlineData = new() [Title("Outline Styles")]
{ [SerializeField] private InteractionOutlineData _availableStyle = new() {Color = Color.white, Width = 1f, Opacity = 1f};
{InteractionOutlineType.Available, new InteractionOutlineData() {Color = Color.white, Width = 0.5f, Opacity = 1f}}, [SerializeField] private InteractionOutlineData _focusedStyle = new() {Color = Color.yellow, Width = 1f, Opacity = 1f};
{InteractionOutlineType.Focused, new InteractionOutlineData() {Color = Color.yellow, Width = 0.5f, Opacity = 1f}}, [SerializeField] private InteractionOutlineData _unavailableStyle = new() {Color = Color.gray, Width = 0.5f, Opacity = 1f};
{InteractionOutlineType.Unavailable, new InteractionOutlineData() {Color = Color.gray, Width = 0.5f, Opacity = 1f}}, [SerializeField] private InteractionOutlineData _objectiveStyle = new() {Color = Color.cyan, Width = 1f, Opacity = 1f};
{InteractionOutlineType.Objective, new InteractionOutlineData() {Color = Color.cyan, Width = 0.5f, Opacity = 1f}},
{InteractionOutlineType.None, new InteractionOutlineData() {Color = Color.clear, Width = 0.5f, Opacity = 0f}} [Title("Animation Settings")]
}; [SerializeField, Range(0.5f, 10f)] private float _breathingSpeed = 2f;
[SerializeField, Range(0.1f, 1f)] private float _breathingRange = 0.3f;
[SerializeField] private bool _enableBreathingEffect = true;
[Title("Highlight Component Settings")]
[SerializeField, Range(0f, 1f)] private float _alphaCutOff = 0.5f;
[SerializeField] private bool _combineMeshes = true;
[SerializeField] private bool _constantWidth = true;
[SerializeField] private QualityLevel _outlineQuality = QualityLevel.Highest;
[SerializeField] private bool _outlineIndependent = true;
[SerializeField, Range(0, 4)] private int _outlineBlurPasses = 1;
[SerializeField, Range(1f, 20f)] private float _outlineSharpness = 8f;
[Title("Debug")]
[SerializeField, ReadOnly] private InteractionOutlineType _currentOutlineType;
[SerializeField, ReadOnly] private float _currentOpacityMultiplier = 1f;
// 런타임에 생성되는 딕셔너리
private Dictionary<InteractionOutlineType, InteractionOutlineData> _outlineData;
// Private runtime variables
private float _opacityMultiply = 1.0f;
private float _breathingTime;
private HighlightEffect _highlightComponent; private HighlightEffect _highlightComponent;
private RestaurantInteractionComponent _interactionComponent; private RestaurantInteractionComponent _interactionComponent;
private IInteractor _interactor; private IInteractor _interactor;
private InteractionOutlineType _lastAppliedType = InteractionOutlineType.None;
private void Awake() private void Awake()
{ {
// OutlineData 딕셔너리 초기화
InitializeOutlineData();
// Cache HighlightEffect // Cache HighlightEffect
_highlightComponent = GetComponent<HighlightPlus.HighlightEffect>(); _highlightComponent = GetComponent<HighlightPlus.HighlightEffect>();
_interactionComponent = GetComponent<RestaurantInteractionComponent>(); _interactionComponent = GetComponent<RestaurantInteractionComponent>();
// highlightEffect에 alphaCutoff, constantWidth, combineMeshes, outlineQuality, outlineIndependent 등의 필수 옵션이 켜져있는지 확인 // HighlightEffect 설정 적용
_highlightComponent.alphaCutOff = 0.5f; ApplyHighlightSettings();
_highlightComponent.combineMeshes = true; }
_highlightComponent.constantWidth = true;
_highlightComponent.outlineQuality = QualityLevel.Highest; private void InitializeOutlineData()
_highlightComponent.outlineIndependent = true; {
_highlightComponent.outlineBlurPasses = 1; _outlineData = new Dictionary<InteractionOutlineType, InteractionOutlineData>
_highlightComponent.outlineSharpness = 8; {
{InteractionOutlineType.Available, _availableStyle},
{InteractionOutlineType.Focused, _focusedStyle},
{InteractionOutlineType.Unavailable, _unavailableStyle},
{InteractionOutlineType.Objective, _objectiveStyle},
{InteractionOutlineType.None, new InteractionOutlineData() {Color = Color.clear, Width = 0.5f, Opacity = 0f}}
};
}
private void ApplyHighlightSettings()
{
if (!_highlightComponent) return;
_highlightComponent.alphaCutOff = _alphaCutOff;
_highlightComponent.combineMeshes = _combineMeshes;
_highlightComponent.constantWidth = _constantWidth;
_highlightComponent.outlineQuality = _outlineQuality;
_highlightComponent.outlineIndependent = _outlineIndependent;
_highlightComponent.outlineBlurPasses = _outlineBlurPasses;
_highlightComponent.outlineSharpness = _outlineSharpness;
} }
private void Update() private void Update()
@ -60,9 +108,35 @@ private void Update()
FetchPlayerInteractorComponent(); FetchPlayerInteractorComponent();
var currentType = GetCurrentOutlineType(); var currentType = GetCurrentOutlineType();
_currentOutlineType = currentType; // 디버그용
if (_enableBreathingEffect)
{
UpdateBreathingEffect(currentType);
}
else
{
_opacityMultiply = 1f;
_breathingTime = 0f;
}
_currentOpacityMultiplier = _opacityMultiply; // 디버그용
ApplyOutlineType(currentType); ApplyOutlineType(currentType);
}
private void UpdateBreathingEffect(InteractionOutlineType type)
{
if (type == InteractionOutlineType.Available || type == InteractionOutlineType.Focused)
{
_breathingTime += Time.deltaTime;
float sin01 = (Mathf.Sin(_breathingTime * _breathingSpeed) + 1) / 2;
_opacityMultiply = 1f - _breathingRange + sin01 * _breathingRange;
}
else
{
_opacityMultiply = 1f;
_breathingTime = 0f;
}
} }
private void FetchPlayerInteractorComponent() private void FetchPlayerInteractorComponent()
@ -108,24 +182,22 @@ private InteractionOutlineType GetCurrentOutlineType()
} }
} }
private InteractionOutlineType lastAppliedType = InteractionOutlineType.None;
private void ApplyOutlineType(InteractionOutlineType type) private void ApplyOutlineType(InteractionOutlineType type)
{ {
// 같은 타입이면 불필요한 프로퍼티 세팅을 피함 // 같은 타입이면 불필요한 프로퍼티 세팅을 피함
if (lastAppliedType == type) if (_lastAppliedType == type && _enableBreathingEffect == false)
return; return;
lastAppliedType = type; _lastAppliedType = type;
if (!_highlightComponent) if (!_highlightComponent)
return; return;
// OutlineData에서 해당 타입의 스타일 가져오기 // OutlineData에서 해당 타입의 스타일 가져오기
if (!OutlineData.TryGetValue(type, out var data)) if (!_outlineData.TryGetValue(type, out var data))
{ {
// 데이터가 없으면 None 타입 적용 // 데이터가 없으면 None 타입 적용
data = OutlineData[InteractionOutlineType.None]; data = _outlineData[InteractionOutlineType.None];
} }
// HighlightEffect에 적용 // HighlightEffect에 적용
@ -137,9 +209,12 @@ private void ApplyOutlineType(InteractionOutlineType type)
else else
{ {
_highlightComponent.highlighted = true; _highlightComponent.highlighted = true;
_highlightComponent.outlineColor = data.Color; Color color = data.Color;
// color.a = data.Opacity * _opacityMultiply;
color *= _opacityMultiply;
_highlightComponent.outlineColor = color;
_highlightComponent.outlineWidth = data.Width; _highlightComponent.outlineWidth = data.Width;
_highlightComponent.outline = data.Opacity * opacityMultiply; _highlightComponent.outline = 1;
} }
} }
@ -161,5 +236,18 @@ private bool CanExecuteInteraction()
} }
return _interactor.CanInteractTo(_interactionComponent); return _interactor.CanInteractTo(_interactionComponent);
} }
// 런타임에 스타일 변경을 위한 메서드들
[Button("Refresh Outline Data")]
private void RefreshOutlineData()
{
InitializeOutlineData();
}
[Button("Apply Highlight Settings")]
private void ApplyHighlightSettingsButton()
{
ApplyHighlightSettings();
}
} }
} }