내 작업

This commit is contained in:
윤기주_playm 2026-01-30 12:24:13 +09:00
parent 6e02e36997
commit a67ee1fc65
9 changed files with 104 additions and 25 deletions

View File

@ -392,8 +392,8 @@ MonoBehaviour:
m_faceColor: m_faceColor:
serializedVersion: 2 serializedVersion: 2
rgba: 4294967295 rgba: 4294967295
m_fontSize: 36 m_fontSize: 32.1
m_fontSizeBase: 36 m_fontSizeBase: 32.1
m_fontWeight: 400 m_fontWeight: 400
m_enableAutoSizing: 0 m_enableAutoSizing: 0
m_fontSizeMin: 18 m_fontSizeMin: 18
@ -408,7 +408,7 @@ MonoBehaviour:
m_lineSpacingMax: 0 m_lineSpacingMax: 0
m_paragraphSpacing: 0 m_paragraphSpacing: 0
m_charWidthMaxAdj: 0 m_charWidthMaxAdj: 0
m_enableWordWrapping: 1 m_enableWordWrapping: 0
m_wordWrappingRatios: 0.4 m_wordWrappingRatios: 0.4
m_overflowMode: 0 m_overflowMode: 0
m_linkedTextComponent: {fileID: 0} m_linkedTextComponent: {fileID: 0}

View File

@ -392,8 +392,8 @@ MonoBehaviour:
m_faceColor: m_faceColor:
serializedVersion: 2 serializedVersion: 2
rgba: 4294967295 rgba: 4294967295
m_fontSize: 36 m_fontSize: 32.1
m_fontSizeBase: 36 m_fontSizeBase: 32.1
m_fontWeight: 400 m_fontWeight: 400
m_enableAutoSizing: 0 m_enableAutoSizing: 0
m_fontSizeMin: 18 m_fontSizeMin: 18
@ -408,7 +408,7 @@ MonoBehaviour:
m_lineSpacingMax: 0 m_lineSpacingMax: 0
m_paragraphSpacing: 0 m_paragraphSpacing: 0
m_charWidthMaxAdj: 0 m_charWidthMaxAdj: 0
m_enableWordWrapping: 1 m_enableWordWrapping: 0
m_wordWrappingRatios: 0.4 m_wordWrappingRatios: 0.4
m_overflowMode: 0 m_overflowMode: 0
m_linkedTextComponent: {fileID: 0} m_linkedTextComponent: {fileID: 0}

View File

@ -0,0 +1,51 @@
using UnityEngine;
using TMPro; // TextMeshPro를 위해 필수
public class PlayerStatsUI : MonoBehaviour
{
[Header("--- 데이터 연결 ---")]
[SerializeField] private Stats playerStats;
[Header("--- UI 오브젝트 ---")]
[SerializeField] private GameObject statWindowPanel; // C키로 껐다 켤 부모 판넬
[Header("--- 텍스트 UI ---")]
[SerializeField] private TextMeshProUGUI maxHealthText;
[SerializeField] private TextMeshProUGUI strengthText;
[SerializeField] private TextMeshProUGUI damageText;
[SerializeField] private TextMeshProUGUI speedText;
private void Start()
{
// 시작할 때는 창을 닫아둡니다.
if (statWindowPanel != null)
statWindowPanel.SetActive(false);
}
// 창을 열거나 닫는 함수
public void ToggleWindow()
{
if (statWindowPanel == null) return;
bool isActive = !statWindowPanel.activeSelf;
statWindowPanel.SetActive(isActive);
// 창이 켜질 때만 최신 정보로 글자를 갱신합니다.
if (isActive)
{
UpdateStatTexts();
}
}
private void UpdateStatTexts()
{
if (playerStats == null) return;
// Stats.cs의 실제 로직용 프로퍼티에서 데이터를 가져옵니다.
maxHealthText.text = $"MaxHP: {playerStats.MaxHealth}";
strengthText.text = $"Strength: {playerStats.Strength}";
damageText.text = $"Damage: {playerStats.BaseAttackDamage}";
// 스피드는 소수점 한 자리까지 깔끔하게 표시
speedText.text = $"Speed: {playerStats.CurrentMoveSpeed:F1}";
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18c9580976646ab42a48af83ab430afb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -6,15 +6,25 @@ public class PlayerInput : MonoBehaviour
[SerializeField] private PlayerAim aim; [SerializeField] private PlayerAim aim;
[SerializeField] private PlayerInteraction interaction; [SerializeField] private PlayerInteraction interaction;
[SerializeField] private PlayerAttack attack; [SerializeField] private PlayerAttack attack;
[SerializeField] private PlayerStatsUI statsUI; // ⭐ 추가: UI 매니저 연결
private void Update() private void Update()
{ {
if (health != null && health.IsDead) return; if (health != null && health.IsDead) return;
// ⭐ [추가] C키를 누르면 상태창 토글
if (Input.GetKeyDown(KeyCode.C) && statsUI != null)
{
statsUI.ToggleWindow();
}
float h = Input.GetAxisRaw("Horizontal"); float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical"); float v = Input.GetAxisRaw("Vertical");
bool sprint = Input.GetKey(KeyCode.LeftShift); bool sprint = Input.GetKey(KeyCode.LeftShift);
if (movement != null) movement.SetMoveInput(new Vector3(h, 0, v).normalized, sprint); if (movement != null) movement.SetMoveInput(new Vector3(h, 0, v).normalized, sprint);
if (aim != null) aim.RotateTowardsMouse(); if (aim != null) aim.RotateTowardsMouse();
if (Input.GetKeyDown(KeyCode.F) && interaction != null) interaction.TryInteract(); if (Input.GetKeyDown(KeyCode.F) && interaction != null) interaction.TryInteract();
if (attack != null) if (attack != null)
{ {
if (Input.GetMouseButtonDown(1)) attack.StartCharging(); if (Input.GetMouseButtonDown(1)) attack.StartCharging();

View File

@ -47,6 +47,19 @@ public class MonsterClass : MonoBehaviour, IDamageable
OnHealthChanged?.Invoke(currentHP, maxHP); OnHealthChanged?.Invoke(currentHP, maxHP);
} }
// ⭐ [애니메이션 버그 해결] 매 프레임 속도를 체크해서 애니메이터에 전달합니다.
protected virtual void Update()
{
if (isDead) return;
if (agent != null && animator != null)
{
// 에이전트의 현재 이동 속도를 가져와서 "Speed" 파라미터에 넣어줍니다.
float currentSpeed = agent.velocity.magnitude;
animator.SetFloat("Speed", currentSpeed);
}
}
public virtual void TakeDamage(float amount) { OnDamaged(amount); } public virtual void TakeDamage(float amount) { OnDamaged(amount); }
public virtual void OnDamaged(float damage) public virtual void OnDamaged(float damage)
@ -75,9 +88,11 @@ public class MonsterClass : MonoBehaviour, IDamageable
if (isDead) return; if (isDead) return;
isDead = true; isDead = true;
OnMonsterKilled?.Invoke(expReward); // 아이템 날아감 방지: 몬스터 시체의 충돌을 끕니다.
Collider col = GetComponent<Collider>();
if (col != null) col.enabled = false;
// 몬스터 사망 시 아이템 드랍 OnMonsterKilled?.Invoke(expReward);
TryDropItems(); TryDropItems();
if (agent && agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; } if (agent && agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; }
@ -89,13 +104,11 @@ public class MonsterClass : MonoBehaviour, IDamageable
private void TryDropItems() private void TryDropItems()
{ {
// 1. 포션 드랍 체크
if (potionPrefab != null && UnityEngine.Random.Range(0f, 100f) <= potionDropChance) if (potionPrefab != null && UnityEngine.Random.Range(0f, 100f) <= potionDropChance)
{ {
SpawnItem(potionPrefab); SpawnItem(potionPrefab);
} }
// 2. 무기 드랍 체크
if (weaponPrefabs != null && weaponPrefabs.Length > 0 && UnityEngine.Random.Range(0f, 100f) <= weaponDropChance) if (weaponPrefabs != null && weaponPrefabs.Length > 0 && UnityEngine.Random.Range(0f, 100f) <= weaponDropChance)
{ {
int randomIndex = UnityEngine.Random.Range(0, weaponPrefabs.Length); int randomIndex = UnityEngine.Random.Range(0, weaponPrefabs.Length);
@ -103,26 +116,23 @@ public class MonsterClass : MonoBehaviour, IDamageable
} }
} }
// ⭐ [최종 수정] 아이템 생성 함수
private void SpawnItem(GameObject prefab) private void SpawnItem(GameObject prefab)
{ {
Vector3 spawnPos = transform.position + Vector3.up * 0.5f; Vector3 spawnPos = transform.position + Vector3.up * 0.5f;
GameObject item = Instantiate(prefab, spawnPos, Quaternion.identity); GameObject item = Instantiate(prefab, spawnPos, Quaternion.identity);
// ✅ [유저 요청] 인스펙터 변수 없이 '프리팹의 원래 크기'를 그대로 적용합니다. // ✅ [유저 요청] 배율 없이 프리팹의 원래 크기를 100% 그대로 적용
item.transform.localScale = prefab.transform.localScale; item.transform.localScale = prefab.transform.localScale;
// 아이템이 몬스터 몸 안에서 나오는 느낌을 위해 살짝 위로만 튀게 합니다.
if (item.TryGetComponent<Rigidbody>(out var rb)) if (item.TryGetComponent<Rigidbody>(out var rb))
{ {
// 위로 톡 튀어오르게 함 (마찰력 등은 유저님이 리지드바디에서 설정한 대로 돌아감) // 튀어오르는 힘은 유저님이 설정하신 0.02f 유지
Vector3 popDir = Vector3.up * 3f + UnityEngine.Random.insideUnitSphere * 0.5f; Vector3 popDir = Vector3.up * 0.02f + UnityEngine.Random.insideUnitSphere * 0.02f;
rb.AddForce(popDir, ForceMode.Impulse); rb.AddForce(popDir, ForceMode.Impulse);
// 무기일 경우만 약간의 회전을 줘서 역동적으로 떨어지게 합니다.
if (prefab != potionPrefab) if (prefab != potionPrefab)
{ {
rb.AddTorque(UnityEngine.Random.insideUnitSphere * 5f, ForceMode.Impulse); rb.AddTorque(UnityEngine.Random.insideUnitSphere * 0.3f, ForceMode.Impulse);
} }
} }
} }

View File

@ -44,7 +44,7 @@ public class NormalMonster : MonsterClass
animator.applyRootMotion = false; animator.applyRootMotion = false;
} }
void Update() protected override void Update() // 앞 부분에 protected override 추가해줘야 됨
{ {
if (isDead || player == null) return; if (isDead || player == null) return;

View File

@ -5,7 +5,7 @@ AnimationClip:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_Name: walk m_Name: Monster_Walk
serializedVersion: 6 serializedVersion: 6
m_Legacy: 0 m_Legacy: 0
m_Compressed: 0 m_Compressed: 0
@ -981,8 +981,7 @@ AnimationClip:
tangentMode: 0 tangentMode: 0
- serializedVersion: 2 - serializedVersion: 2
time: 0.93333334 time: 0.93333334
value: {x: 0.000000009098822, y: -0.0000000033114052, z: 0.000000003760177, value: {x: 0.000000009098822, y: -0.0000000033114052, z: 0.000000003760177, w: 1}
w: 1}
inSlope: {x: 0.28541204, y: -0.10641777, z: 0.116288796, w: 0.0035440957} inSlope: {x: 0.28541204, y: -0.10641777, z: 0.116288796, w: 0.0035440957}
outSlope: {x: 0.28541204, y: -0.10641777, z: 0.116288796, w: 0.0035440957} outSlope: {x: 0.28541204, y: -0.10641777, z: 0.116288796, w: 0.0035440957}
tangentMode: 0 tangentMode: 0
@ -995,10 +994,8 @@ AnimationClip:
- serializedVersion: 2 - serializedVersion: 2
time: 1.1333334 time: 1.1333334
value: {x: 5.0408852e-14, y: 2.3997057e-15, z: 2.8048359e-15, w: 1} value: {x: 5.0408852e-14, y: 2.3997057e-15, z: 2.8048359e-15, w: 1}
inSlope: {x: -0.0000001903161, y: -0.000000009059964, z: -0.000000010589522, inSlope: {x: -0.0000001903161, y: -0.000000009059964, z: -0.000000010589522, w: 0}
w: 0} outSlope: {x: -0.0000001903161, y: -0.000000009059964, z: -0.000000010589522, w: 0}
outSlope: {x: -0.0000001903161, y: -0.000000009059964, z: -0.000000010589522,
w: 0}
tangentMode: 0 tangentMode: 0
- serializedVersion: 2 - serializedVersion: 2
time: 1.2 time: 1.2