chore: Assets 디렉토리 구조 정리 및 네이밍 컨벤션 적용

- Assets/_Game/ 하위로 게임 에셋 통합
- External/ 패키지 벤더별 분류 (Synty, Animations, UI)
- 에셋 네이밍 컨벤션 확립 및 적용
  (Data_Skill_, Data_SkillEffect_, Prefab_, Anim_, Model_, BT_ 등)
- pre-commit hook으로 네이밍 컨벤션 자동 검사 추가
- RESTRUCTURE_CHECKLIST.md 작성

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 19:08:27 +09:00
parent 309bf5f48b
commit c265f980db
17251 changed files with 2630777 additions and 206 deletions

View File

@@ -0,0 +1,167 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class ExpressionSwitcher : MonoBehaviour
{
private Animator _animator;
// Define a list of expression names (will be dynamically populated)
private List<string> _expressionNames = new List<string>();
private int _currentIndex = 0;
// Reference to the UI text to display the current emotion
[SerializeField] private Text _emotionText;
// Reference to the button to cycle expressions
[SerializeField] private Button _cycleButton;
// Reference to the UI slider to adjust transition time
[SerializeField] private Slider _transitionTimeSlider;
private float _transitionTime = 0.2f; // Default transition time
void Start()
{
_animator = GetComponent<Animator>();
// Ensure the Animator is assigned
if (_animator == null)
{
Debug.LogWarning("[ExpressionSwitcher] No Animator component found on the GameObject.");
return;
}
// Populate the expression names from the Animator states in the specified layer
PopulateExpressionNames();
// Debug: Check what was found
Debug.Log($"[ExpressionSwitcher] Found {_expressionNames.Count} expressions:");
foreach (var expr in _expressionNames)
Debug.Log($" - {expr}");
// Debug: Check the layer
int layerIndex = _animator.GetLayerIndex("Emotion_Additive");
Debug.Log($"[ExpressionSwitcher] Layer 'Emotion_Additive' index: {layerIndex}");
// Wire up the button
if (_cycleButton != null)
{
_cycleButton.onClick.AddListener(CycleExpressions);
Debug.Log("[ExpressionSwitcher] Button wired up successfully");
}
else
{
Debug.LogWarning("[ExpressionSwitcher] No button assigned in Inspector!");
}
// Ensure the slider is assigned
if (_transitionTimeSlider != null)
{
_transitionTimeSlider.minValue = 0.0f;
_transitionTimeSlider.maxValue = 1.0f;
_transitionTimeSlider.value = _transitionTime;
// Read the initial value from the slider to set the transition time
UpdateTransitionTime(_transitionTimeSlider.value);
// Add a listener to handle value changes
_transitionTimeSlider.onValueChanged.AddListener(UpdateTransitionTime);
}
}
private void PopulateExpressionNames()
{
RuntimeAnimatorController ac = _animator.runtimeAnimatorController;
if (ac != null)
{
Debug.Log($"[ExpressionSwitcher] Scanning {ac.animationClips.Length} animation clips...");
foreach (AnimationClip clip in ac.animationClips)
{
if (clip.name.Contains("A_FacePose") && !_expressionNames.Contains(clip.name) && !clip.name.Contains("Neutral"))
{
_expressionNames.Add(clip.name);
}
}
}
else
{
Debug.LogError("[ExpressionSwitcher] AnimatorController is not found.");
}
}
public void CycleExpressions()
{
Debug.Log("[ExpressionSwitcher] CycleExpressions() called");
if (_animator == null)
{
Debug.LogError("[ExpressionSwitcher] Animator is null!");
return;
}
if (_expressionNames.Count == 0)
{
Debug.LogError("[ExpressionSwitcher] No expressions found in list!");
return;
}
string layerName = "Emotion_Additive";
int layerIndex = _animator.GetLayerIndex(layerName);
if (layerIndex == -1)
{
Debug.LogError($"[ExpressionSwitcher] Layer '{layerName}' not found!");
return;
}
string expressionName = _expressionNames[_currentIndex];
int stateHash = Animator.StringToHash(expressionName);
bool hasState = _animator.HasState(layerIndex, stateHash);
Debug.Log($"[ExpressionSwitcher] Trying expression: '{expressionName}' (index {_currentIndex})");
Debug.Log($"[ExpressionSwitcher] State hash: {stateHash}, HasState: {hasState}");
if (hasState)
{
_animator.CrossFadeInFixedTime(expressionName, _transitionTime, layerIndex);
Debug.Log($"[ExpressionSwitcher] Playing '{expressionName}'");
}
else
{
Debug.LogWarning($"[ExpressionSwitcher] State '{expressionName}' not found, trying 'Neutral'");
_animator.CrossFadeInFixedTime("Neutral", _transitionTime, layerIndex);
}
// Update the emotion text after playing the animation
UpdateEmotionText();
// Move to the next expression in the list
_currentIndex = (_currentIndex + 1) % _expressionNames.Count;
}
private void UpdateEmotionText()
{
if (_emotionText != null && _expressionNames.Count > 0)
{
string expressionName = _expressionNames[_currentIndex];
int underscoreIndex = expressionName.LastIndexOf('_');
if (underscoreIndex != -1 && underscoreIndex < expressionName.Length - 1)
{
_emotionText.text = expressionName.Substring(underscoreIndex + 1);
}
else
{
_emotionText.text = expressionName; // Fallback if no underscore found
}
}
}
private void UpdateTransitionTime(float value)
{
_transitionTime = value;
}
}