183 lines
6.7 KiB
C#
183 lines
6.7 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
|
|
public class BattleManager : MonoBehaviour
|
|
{
|
|
[Header("전투 대상 오브젝트 연결")]
|
|
public Player player; // 플레이어 캐릭터
|
|
public Enemy enemy; // 적(Enemy) 캐릭터
|
|
|
|
[Header("UI 연결 (선택 사항)")]
|
|
public TMPro.TMP_InputField skillInputField; // Canvas에 배치한 텍스트 입력창
|
|
public UnityEngine.UI.Button attackButton; // Canvas에 배치한 공격 버튼
|
|
public TMPro.TextMeshProUGUI skillResultText; // 스킬 연성 결과 및 설명 출력용 텍스트 UI 추가 ⭐
|
|
|
|
private string debugInputText = "불화살을 힘차게 쏜다!"; // OnGUI 디버그용 입력 기본값
|
|
private string statusText = "스킬을 입력하여 전투를 시작하세요.";
|
|
private bool isAttacking = false;
|
|
|
|
private void Start()
|
|
{
|
|
// 씬 내의 Player와 Enemy를 지정 안 했을 경우 자동으로 검색하여 매칭합니다.
|
|
if (player == null) player = FindObjectOfType<Player>();
|
|
if (enemy == null) enemy = FindObjectOfType<Enemy>();
|
|
|
|
// Canvas 버튼 클릭 이벤트 바인딩
|
|
if (attackButton != null)
|
|
{
|
|
attackButton.onClick.AddListener(OnAttackButtonClick);
|
|
}
|
|
}
|
|
|
|
// Canvas UI의 공격 버튼을 클릭했을 때 호출되는 함수
|
|
public void OnAttackButtonClick()
|
|
{
|
|
if (isAttacking) return;
|
|
|
|
// 버튼 클릭음 재생
|
|
if (SoundManager.Instance != null)
|
|
{
|
|
SoundManager.Instance.PlayButtonClick();
|
|
}
|
|
|
|
string prompt = "";
|
|
if (skillInputField != null)
|
|
{
|
|
prompt = skillInputField.text;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(prompt))
|
|
{
|
|
statusText = "스킬 묘사 텍스트를 입력해 주세요!";
|
|
return;
|
|
}
|
|
|
|
StartCoroutine(AttackFlowCoroutine(prompt));
|
|
}
|
|
|
|
// AI 스킬 연성 및 턴제 상호작용(플레이어 공격 -> 피격 -> 적 반격)을 관리하는 코루틴
|
|
private IEnumerator AttackFlowCoroutine(string skillPrompt)
|
|
{
|
|
isAttacking = true;
|
|
statusText = "AI가 스킬을 연성하는 중입니다...";
|
|
Debug.Log($"[Battle] 스킬 프롬프트 전송 시도: \"{skillPrompt}\"");
|
|
|
|
// 1. FastAPI 서버의 generate-skill API 호출 (플레이어 레벨 파라미터에는 Generation 세대값 전달)
|
|
string url = "http://192.168.1.7:8000/api/game/generate-skill";
|
|
int playerLevel = (player != null) ? player.Generation : 1;
|
|
|
|
SkillCreateRequest requestData = new SkillCreateRequest
|
|
{
|
|
prompt = skillPrompt,
|
|
player_level = playerLevel
|
|
};
|
|
string jsonPayload = JsonUtility.ToJson(requestData);
|
|
|
|
using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
|
|
{
|
|
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonPayload);
|
|
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
|
request.downloadHandler = new DownloadHandlerBuffer();
|
|
request.SetRequestHeader("Content-Type", "application/json");
|
|
|
|
yield return request.SendWebRequest();
|
|
|
|
if (request.result == UnityWebRequest.Result.ConnectionError ||
|
|
request.result == UnityWebRequest.Result.ProtocolError)
|
|
{
|
|
Debug.LogError($"[Battle] 스킬 연성 실패: {request.error}");
|
|
statusText = "스킬 연성 실패 (서버 에러)";
|
|
isAttacking = false;
|
|
yield break;
|
|
}
|
|
|
|
// 스킬 데이터 파싱
|
|
string responseText = request.downloadHandler.text;
|
|
SkillCreateResponse response = JsonUtility.FromJson<SkillCreateResponse>(responseText);
|
|
|
|
statusText = $"[연성 완료] 스킬: {response.name} | 피해: {response.damage}";
|
|
Debug.Log($"[Battle] 스킬 연성 성공: {response.name} (대미지: {response.damage}) - {response.description}");
|
|
|
|
// AI가 연성한 최종 스킬 정보를 화면상 텍스트 UI에 실시간 갱신 출력합니다.
|
|
if (skillResultText != null)
|
|
{
|
|
skillResultText.text = $"스킬 연성 성공: {response.name} (대미지: {response.damage})\n- {response.description}";
|
|
}
|
|
|
|
// 2. 플레이어 공격 애니메이션 및 적 타격 처리
|
|
if (player != null && player.hp > 0)
|
|
{
|
|
// 플레이어 휘두르기 공격음 재생
|
|
if (SoundManager.Instance != null)
|
|
{
|
|
SoundManager.Instance.PlayAttackSwing();
|
|
}
|
|
|
|
Animator pAnim = player.GetComponentInChildren<Animator>();
|
|
if (pAnim != null)
|
|
{
|
|
pAnim.SetTrigger("2_Attack"); // 공격 모션 가동
|
|
}
|
|
}
|
|
|
|
yield return new WaitForSeconds(0.6f); // 공격 모션 타이밍 대기
|
|
|
|
if (enemy != null)
|
|
{
|
|
enemy.TakeDamage(response.damage); // 적에게 AI로 생성된 데미지 적용
|
|
}
|
|
|
|
// 3. 적이 쓰러졌는지 확인
|
|
if (enemy != null && enemy.hp <= 0)
|
|
{
|
|
statusText = $"[승리] 적 {enemy.enemyName}을(를) 처치했습니다!";
|
|
isAttacking = false;
|
|
yield break;
|
|
}
|
|
|
|
// 4. 적의 생존 시 반격 턴 개시 (1.5초 후 적이 플레이어를 공격)
|
|
yield return new WaitForSeconds(1.5f);
|
|
|
|
if (enemy != null && enemy.hp > 0 && player != null && player.hp > 0)
|
|
{
|
|
statusText = $"적 {enemy.enemyName}의 반격 차례!";
|
|
enemy.Attack(player); // 적의 플레이어 타격 실행
|
|
}
|
|
|
|
yield return new WaitForSeconds(1.2f); // 피격 연출 대기
|
|
|
|
if (player != null && player.hp <= 0)
|
|
{
|
|
statusText = "[패배] 플레이어가 전사했습니다. 씬이 초기화됩니다.";
|
|
}
|
|
else
|
|
{
|
|
statusText = "전투 대기 중... 스킬을 입력하고 공격 버튼을 누르세요.";
|
|
}
|
|
isAttacking = false;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------
|
|
// JSON 연동용 API 페이로드 스키마 정의 클래스
|
|
// ----------------------------------------------------
|
|
[System.Serializable]
|
|
public class SkillCreateRequest
|
|
{
|
|
public string prompt;
|
|
public int player_level;
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class SkillCreateResponse
|
|
{
|
|
public string name;
|
|
public int damage;
|
|
public float speed;
|
|
public string description;
|
|
}
|