Genesis Game Client Project Setup

This commit is contained in:
2026-03-13 12:43:28 +09:00
commit af885151b3
832 changed files with 630533 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
using Game.Network.DTO;
using Newtonsoft.Json;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TextCore.Text;
public class DataManager : MonoBehaviour
{
public static DataManager Instance;
//내 캐릭터들
public List<UserCharacter> MyCharacters = new List<UserCharacter>();
//모든 캐릭터들 데이터(적,NPC,플레이어블)
public Dictionary<string, PlayableCharacter> PlayableCharacterData = new Dictionary<string, PlayableCharacter>();
public Dictionary<string, EnemyCharacter> EnemyCharacterData = new Dictionary<string, EnemyCharacter>();
public Dictionary<string, NpcCharacter> NpcCharacterData = new Dictionary<string, NpcCharacter>();
private void Awake()
{
if (Instance == null)
{
Instance = this; //만들어진 자신을 인스턴스로 설정
}
else
{
Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴
}
}
private async Awaitable Start()
{
await LoadUserCharacters(1);
await LoadPlayableCharacters();
}
public async Awaitable LoadUserCharacters(int userNo)
{
UserCharacterDTO[] characterDTOs = await NetworkManager.Instance.GetDatabaseData<UserCharacterDTO[]>($"userCharacters/{userNo}");
if (characterDTOs != null)
{
MyCharacters.Clear();
foreach ( UserCharacterDTO characterDTO in characterDTOs )
{
UserCharacter uc = new UserCharacter();
uc.UserCharacterNo = characterDTO.userCharacterNo;
uc.UserNo = characterDTO.userNo;
uc.CharacterCode = characterDTO.characterCode;
uc.Lv = characterDTO.lv;
uc.StrStat = characterDTO.strStat;
uc.IntStat = characterDTO.intStat;
uc.MaxHp = characterDTO.maxHp;
uc.MaxMp = characterDTO.maxMp;
uc.DefaultControl = characterDTO.defaultControl;
MyCharacters.Add(uc);
}
}
else
{
Debug.LogError("캐릭터 데이터를 불러오지 못했습니다.");
}
}
public async Awaitable LoadPlayableCharacters()
{
PlayableCharacterDTO[] characterDTOs = await NetworkManager.Instance.GetDatabaseData<PlayableCharacterDTO[]>($"playableCharacters");
if (characterDTOs != null)
{
PlayableCharacterData.Clear();
foreach (PlayableCharacterDTO characterDTO in characterDTOs)
{
PlayableCharacter c = new PlayableCharacter();
c.CharacterCode = characterDTO.characterCode;
c.CharacterType = characterDTO.characterType;
PlayableCharacterData.TryAdd(c.CharacterCode, c);
}
}
else
{
Debug.LogError("캐릭터 데이터를 불러오지 못했습니다.");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0c9262ba3475f9d4482097685346b7e5

View File

@@ -0,0 +1,93 @@
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
public LevelManager Level { get; private set; }
public CameraManager Camera { get; private set; }
private void Awake()
{
if (Instance == null)
{
Instance = this; //만들어진 자신을 인스턴스로 설정
}
else
{
Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴
}
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
// 씬이 로드될 때마다 해당 씬에 있는 Manager들을 찾아서 갱신
// 없으면 자동으로 null이 들어감
Level = FindFirstObjectByType<LevelManager>();
Camera = FindFirstObjectByType<CameraManager>();
if(Level != null) Level.OnSceneLoaded(scene, mode);
if(Camera != null) Camera.OnSceneLoaded(scene, mode);
InputManager.Instance.PlayerInputEnable(true);
GlobalUIManager.Instance.SetSceneLoadingActive(false);
}
public void RequestSceneChange(string sceneName)
{
_ = SceneChange(sceneName);
}
private async Awaitable SceneChange(string sceneName)
{
try
{
GlobalUIManager.Instance.SetSceneLoadingActive(true);
AsyncOperation op = SceneManager.LoadSceneAsync(sceneName);
//자동 전환을 하고 싶지 않을 경우 해당값을 false로 두었다가 true로 바꾸면 그 때 전환됨
op.allowSceneActivation = false;
//화면에 보여줄 로딩 수치
float displayProgress = 0f;
//op.progress 0.9가 데이터 로딩이 끝난 기준 allowSceneActivation이 트루면 바로 다음으로 넘어가면서 op.isDone이 true가 된다.
while (op.progress < 0.9f)
{
//실제 로딩 수치
float realProgress = Mathf.Clamp01(op.progress / 0.9f);
//보여줄 값을 실제값을 향해 부드럽게 이동
displayProgress = Mathf.MoveTowards(displayProgress, realProgress, Time.deltaTime * 0.5f);
// UI에 적용
GlobalUIManager.Instance.SetSceneLoadingProgressValue(displayProgress);
await Awaitable.NextFrameAsync(this.destroyCancellationToken); //자기자신이 파괴될때 토큰에 취소요청을 보냄
}
GlobalUIManager.Instance.SetSceneLoadingProgressValue(1);
// 잠시 대기했다가 전환
await Awaitable.WaitForSecondsAsync(2.0f, this.destroyCancellationToken);
op.allowSceneActivation = true;
Debug.Log("씬 전환됨");
InputManager.Instance.UnPairDevices();
}
catch (OperationCanceledException)
{
Debug.Log("씬 전환 작업이 취소됨");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7e694f93c42d3334cb7ea4ac25d87b5d

View File

@@ -0,0 +1,205 @@
using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Windows;
public enum InputState { Started, Performing, Canceled }
public class InputManager : MonoBehaviour
{
public static InputManager Instance;
private PlayerInput _playerInput;
private InputActionMap _globalInputActionMap;
private InputActionMap _uiInputActionMap;
private InputActionMap _characterInputActionMap;
//콜백 이벤트들
//캐릭터 조작관련은 따로 분류
public event Action<float> OnMouseScrollEvent;
public event Action<Vector2> OnMoveEvent;
public event Action<InputState> OnSprintEvent;
public event Action<InputState> OnJumpEvent;
public event Action OnNormalAttackEvent;
public event Action OnHeavyAttackEvent;
//키조작
public event Action OnKeyDown_UpArrowEvent;
public event Action OnKeyDown_DownArrowEvent;
public event Action OnKeyDown_EnterEvent;
private void Awake()
{
if (Instance == null)
{
Instance = this; //만들어진 자신을 인스턴스로 설정
}
else
{
Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴
}
_playerInput = GetComponent<PlayerInput>();
}
private void Start()
{
SetGlobalInputMap("Global");
}
public void UnPairDevices()
{
if(_playerInput != null)
{
_playerInput.user.UnpairDevices();
PlayerInputEnable(false);
}
}
public void PlayerInputEnable(bool flag)
{
_playerInput.enabled = flag;
}
private void SetGlobalInputMap(string mapName)
{
_globalInputActionMap = _playerInput?.actions?.FindActionMap(mapName);
}
public void SetUIInputMap(string mapName)
{
_uiInputActionMap = _playerInput?.actions?.FindActionMap(mapName);
if (_uiInputActionMap == null) return;
// 맵 활성화
_uiInputActionMap.Enable();
//바인딩
BindActionUI("OnKeyDown_UpArrow", OnKeyDown_UpArrow);
BindActionUI("OnKeyDown_DownArrow", OnKeyDown_DownArrow);
BindActionUI("OnKeyDown_Enter", OnKeyDown_Enter);
}
public void SetCharacterInputMap(string mapName)
{
_characterInputActionMap = _playerInput?.actions?.FindActionMap(mapName);
if (_characterInputActionMap == null) return;
// 맵 활성화
_characterInputActionMap.Enable();
//바인딩
BindActionCharacter("Scroll", OnMouseScroll);
BindActionCharacter("Move", OnMove);
BindActionCharacter("Sprint", OnSprint);
BindActionCharacter("Jump", OnJump);
BindActionCharacter("NormalAttack", OnNormalAttack);
BindActionCharacter("HeavyAttack", OnHeavyAttack);
}
//매핑용 함수
private void BindActionUI(string actionName, Action<InputAction.CallbackContext> callback)
{
InputAction action = _uiInputActionMap.FindAction(actionName);
if (action != null)
{
action.performed -= callback;
action.canceled -= callback;
action.started -= callback;
action.performed += callback;
action.canceled += callback;
action.started += callback;
action.Enable();
}
}
private void BindActionCharacter(string actionName, Action<InputAction.CallbackContext> callback)
{
InputAction action = _characterInputActionMap.FindAction(actionName);
if (action != null)
{
action.performed -= callback;
action.canceled -= callback;
action.started -= callback;
action.performed += callback;
action.canceled += callback;
action.started += callback;
action.Enable();
}
}
#region
private void OnMouseScroll(InputAction.CallbackContext ctx)
{
Vector2 scroll = ctx.ReadValue<Vector2>();
OnMouseScrollEvent?.Invoke(scroll.y);
}
private void OnMove(InputAction.CallbackContext ctx)
{
Vector2 move = ctx.ReadValue<Vector2>();
OnMoveEvent?.Invoke(move);
}
private void OnSprint(InputAction.CallbackContext ctx)
{
if(ctx.performed)
{
OnSprintEvent?.Invoke(InputState.Performing);
}
if(ctx.canceled)
{
OnSprintEvent?.Invoke(InputState.Canceled);
}
}
private void OnJump(InputAction.CallbackContext ctx)
{
if(ctx.started)
{
OnJumpEvent?.Invoke(InputState.Started);
}
if (ctx.canceled)
{
OnJumpEvent?.Invoke(InputState.Canceled);
}
}
private void OnNormalAttack(InputAction.CallbackContext ctx)
{
OnNormalAttackEvent?.Invoke();
}
private void OnHeavyAttack(InputAction.CallbackContext ctx)
{
OnHeavyAttackEvent?.Invoke();
}
#endregion
#region
private void OnKeyDown_UpArrow(InputAction.CallbackContext ctx)
{
if(ctx.started)
OnKeyDown_UpArrowEvent?.Invoke();
}
private void OnKeyDown_DownArrow(InputAction.CallbackContext ctx)
{
if (ctx.started)
OnKeyDown_UpArrowEvent?.Invoke();
}
private void OnKeyDown_Enter(InputAction.CallbackContext ctx)
{
if (ctx.started)
OnKeyDown_EnterEvent?.Invoke();
}
#endregion
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bee5878dce649df468827634987718b7

View File

@@ -0,0 +1,53 @@
using Game.Network;
using Game.Network.DTO;
using Newtonsoft.Json;
using System;
using UnityEngine;
using UnityEngine.Networking;
public class NetworkManager : MonoBehaviour
{
public static NetworkManager Instance;
private string _baseGameDBUrl = "https://localhost:7134/myGame";
//private string _baseGameDBUrlHttp = "http://localhost:5281/myGame";
private void Awake()
{
if (Instance == null)
{
Instance = this; //만들어진 자신을 인스턴스로 설정
}
else
{
Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴
}
}
public async Awaitable<T> GetDatabaseData<T>(string endPoint)
{
string url = $"{_baseGameDBUrl}/{endPoint}";
using UnityWebRequest request = UnityWebRequest.Get(url); //앞의 using은 사용이 끝난(메서드 종료) 외부 리소스 객체들을 알아서 지워주도록 설정하는 예약어이다
request.certificateHandler = new BypassCertificate();
try
{
await request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
string json = request.downloadHandler.text;
ApiResponse<T> container = JsonConvert.DeserializeObject<ApiResponse<T>>(json);
Debug.Log($"응답 : data = {container.data}, count = {container.count}, message = {container.message}");
return container.data;
}
}
catch (Exception e)
{
Debug.LogException(e);
}
return default;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 603b990f633737340b3c056ba1cbf300

View File

@@ -0,0 +1,17 @@
using UnityEngine;
public class SoundManager : MonoBehaviour
{
public static SoundManager Instance;
private void Awake()
{
if (Instance == null)
{
Instance = this; //만들어진 자신을 인스턴스로 설정
}
else
{
Destroy(gameObject); //이미 인스턴스가 있으면 자신을 파괴
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 571d986dc1fe8bd4aa48335d392008a4