주차별 개발 과정
1차 마일 스톤 개발 주요 항목 (6.05 ~ 6.30)
•
GitHub연동 (완료)
•
코드 규칙 재정리 (완료)
•
어드레서블 적용(AWS) (완료)
•
UI매니저 ver 0.1 제작 (완료)
•
오디오 매니저 제작 (완료)
•
리소스 매니저 제작 (완료)
•
셰이더 적용 (완료)기타 플러그인(오딘, ES3, GPM, SRDebugger 등등) (완료)
•
플레이어 제작 (완료)
•
미니 게임 -> 구축(미니 게임 시작) (제작 중)
◦
씬 이동 셰이더 및 전환 시스템 제작 (완료)
◦
미니 게임 시작 UI 및 기획
◦
미니 게임 시작 시스템
•
미니 게임(레이싱 게임) (제작 중)
◦
전반적인 시스템 구축 (완료)
◦
사용할 모델 (완료)
◦
게임 시스템 (제작 중)
◦
메시 피드 연동
•
미니 게임 (인형뽑기)
•
어드레서블 정리 (기본 리소스등) (완료)
◦
어드레서블 로딩 시스템 (RawResources) (완료)
◦
어드레서블 로딩 화면 (완료)
•
메스 피드 연동
•
UI 아틀라스 적용
•
1차 사운드, 파티클
개발 항목
씬 이동 셰이더 및 전환 시스템 제작
화면 전환을 좀 더 깔끔하게 하기 위해, 셰이더를 사용해서 화면 전환을 했습니다.
예쁘게 하고 싶었는데.. 현재로선 검은 화면이 가장 예쁘네요. 퀄업 기간 동안에는 씬 전환 가운데에 고양이 얼굴을 넣어보겠습니다!
이전 화면과 다음 화면으로의 전환 전후에 action을 통해 다음 행동을 진행할 수 있도록 static 메소드로 구현되었습니다.
아래는 Transition UI의 코드입니다.
public class Transition_Screen : ScreenUI
{
public new enum EComponents
{
Transition_Screen,
}
private const float TRANSITION_TIME = 1.5f;
private Image _maskTransition = null;
private float _screenHeight = 0f;
private float _screenWidth = 0f;
private float _elapsedTime = 0.0f;
private Coroutine _fadeInCoroutine = null;
private Coroutine _fadeOutCoroutine = null;
protected override void BindingUI()
{
base.BindingUI();
_maskTransition = GetControl<Image>(EComponents.Transition_Screen);
}
protected override void OpenInit()
{
base.OpenInit();
}
public void FadeOutAnimation(UnityAction action = null)
{
InitShader(false);
if (_fadeOutCoroutine.IsUnityNull() == false) StopCoroutine(_fadeOutCoroutine);
_fadeOutCoroutine = StartCoroutine(CoFadeOutAnimation());
if (action.IsUnityNull() == false) action.Invoke();
}
public void FadeInAnimation(UnityAction action = null)
{
InitShader(true);
if (_fadeInCoroutine.IsUnityNull() == false) StopCoroutine(_fadeInCoroutine);
_fadeInCoroutine = StartCoroutine(CoFadeInAnimation());
if (action.IsUnityNull() == false) action.Invoke();
}
private void InitShader(bool isFadeIn)
{
if (_maskTransition.IsUnityNull()) return;
_maskTransition.material.SetFloat("_Radius", isFadeIn ? 0f : 1f);
}
private IEnumerator CoFadeOutAnimation()
{
if (_maskTransition.IsUnityNull()) yield break;
_elapsedTime = 0.0f;
while (_elapsedTime < TRANSITION_TIME)
{
_elapsedTime += Time.deltaTime;
_maskTransition.material.SetFloat("Radius", 1f - _elapsedTime / TRANSITION_TIME);
yield return null;
}
_maskTransition.material.SetFloat("Radius", 0f);
}
private IEnumerator CoFadeInAnimation()
{
if (_maskTransition.IsUnityNull()) yield break;
_elapsedTime = 0.0f;
while (_elapsedTime < TRANSITION_TIME)
{
_elapsedTime += Time.deltaTime;
_maskTransition.material.SetFloat("Radius", _elapsedTime / TRANSITION_TIME);
yield return null;
}
_maskTransition.material.SetFloat("Radius", 1f);
Close();
}
}
C#
복사
미니 게임(레이싱) 제작
레이싱 게임에 사용할 주변 모델을 직접 만들고 싶었지만, 한 두 시간 해보고 도저히 안 되겠다 싶어 유니티 템플릿을 그대로 사용하기로 결정했습니다.
..
이번 공모전을 하면서, 그래픽 디자이너 분들의 소중함을 진심으로 느꼈습니다.
사실, 코드 작업은 그리 복잡하지 않았습니다. 오히려, 템플릿의 코드를 제거하는 작업이 오래 걸렸죠.
그 대신, 스테이트를 대략적으로 작성했습니다.
스테이트의 기본이 되는 추상 클래스
public abstract class StateBase
{
public abstract void Enter();
public abstract void Exit();
public abstract void UpdateTime();
public abstract string GetName();
}
C#
복사
기본 Room의 State 클래스
public class RoomState : StateBase
{
public override void Enter()
{
UIManager.Instance.CloseAllUI();
Init();
}
public override void Exit()
{
}
public override string GetName()
{
return "RoomState";
}
public override void UpdateTime()
{
}
private async void Init()
{
await ResourceManager.Instance.LoadSceneAsync("Room");
var player = await ResourceManager.Instance.LoadGameObjectAsync("Player");
if (player.IsUnityNull()) return;
player.transform.position = new Vector3(0f, 0.2f, 0f);
GameManager.Instance.PlayerGameObject = player.gameObject;
CameraManager.Instance.CurrentVirtualCamera.Follow = player.transform;
PublicStaticMethod.FadeIn();
}
}
C#
복사
어드레서블 정리 및 로딩 화면 제작
어드레서블을 정리하고 로딩 화면을 제작했습니다.
로딩 화면은 어드레서블이 로드되기 전에 등장해야 하므로 어드레서블 리소스 폴더와 RawResource(빌드에 포함될 리소스)를 분리했습니다.
위 작업에 따라 ResourceManager에서 어드레서블 로드 뿐만 아니라, Resource 폴더에서도 로드할 수 있도록 수정했습니다.
public async UniTask<GameObject> LoadGameObjectAsync(string gameObjectName)
{
if (_addressableLocation.ContainsKey(gameObjectName) == false)
{
var result = Resources.Load<GameObject>($"RawResources/Prefab/{gameObjectName}");
return result;
}
var prefabGameObject = await AddressablesManager.LoadAssetAsync<GameObject>(_addressableLocation[gameObjectName]);
var gameObject = PoolManager.Instance.spawnObject(prefabGameObject);
return gameObject;
}
public async UniTask<T> LoadUIPrefabAsync<T>() where T : UIBase
{
var uiName = PublicStaticMethod.GetTypeName<T>();
GameObject prefabGameObject = null;
if (_addressableLocation.ContainsKey(uiName) == false) prefabGameObject = Resources.Load<GameObject>($"RawResources/Prefab/{uiName}");
if (prefabGameObject.IsUnityNull()) prefabGameObject = await AddressablesManager.LoadAssetAsync<GameObject>(_addressableLocation[uiName]);
var gameObject = PoolManager.Instance.spawnObject(prefabGameObject);
var uiComponent = gameObject.GetComponent<T>();
return uiComponent;
}
C#
복사
시스템적으로는 잘 작동하지만, 외관이 조금 부족한 것 같습니다 ㅠㅠ.
아래 로딩바를 만들기 위해 몇 시간을 노력했는데, 이게 미용실을 떠올리게 하네요. ㅋㅋㅋㅋ
느낀점
이번 주 개발에서는 코드보다 디자인에 더 많은 시간을 썼습니다.
거의 80%는 디자인이고 20%는 코딩이었습니다.
그리고, 참고로 왼쪽 아래에 있는 고양이 컨트롤러는 제가 만들었습니다! ㅎㅎ.
제가 만든 것 중 가장 예쁜 것 같네요.
디자인을 하면서 힘들기도 했지만, 생각보다 재밌었습니다.
너무 열심히 했는데 결과가 엉망이라 웃음밖에 나오지 않습니다. ㅋㅋㅋㅋ
정말, 코드를 작성하는 것은 쉬운 일인 것 같습니다. 제 슬로건은 ‘코딩에는 오답은 있어도 정답은 없다’인데, 오히려 이 말이 아트 분야에 더 어울리는 것 같네요.
마지막으로, 저는 아트 분야에서 오답을 잘 찾는 것 같습니다!!!
ps. 개발일지도 이쁘게 만들려고 노력한 건 비밀!