
오늘은 목표한 구간까지 어느정도 윤곽이 잡혀, 팀원들끼리 서로의 코드를 공유하고 서로 피드백을 하는 시간을 가졌었다.
내가 담당했던 TimeManager의 경우 다음 부분에 피드백이 있었다.
private void StartTime()
{
CheckPlayTime();
_lastCheckedRealTime += Time.deltaTime;
if (_lastCheckedRealTime % _realTimeSecondPerInGameMinuteUnit < Time.deltaTime)
{
_inGameMinute += _inGameMinuteUnit;
CalculateInGameTime();
DebugGetInGameTime();
}
}
위 코드는 Update 메서드에서 호출되어, Time.deltaTime을 이용해, 특정 시간마다, 인게임 시간을 흐르게 하는 메서드이다.
지적이 있었던 부분은 나머지 연산을 하는 부분이었다.
나눗셈과 나머지 연산은 다른 연산에 비해 상대적으로 높은 성능적 부하가 생기는데, 해당 작업을 매 프레임마다 하는 것은 성능적으로 불 필요할 수도 있다는 지적이 있었다.
위와 같은 방식을 사용했던 이유는, 밤낮에 따른 조명을 구현할 때, 하루가 지나는데 걸리는 총 시간과, 진행하며 누적된 시간을 이용해, 애니메이션 커브에서 적절한 값을 이용하기 위해서였다.
이를 이용해 부드러운 조명 전환을 구현할 수는 있었다.
그러나 게임 시스템 상에서 그 부드러운 조명이 많이 중요한 요소는 아니기에, 해당 부분을 포기하며, 다음과 같은 일반적인 타이머로 변경하였다.
private void StartTime()
{
_lastCheckedRealTime += Time.deltaTime;
if (_lastCheckedRealTime >= _realTimeSecondPerInGameMinuteUnit)
{
_inGameMinute += _inGameMinuteUnit;
CallTimeCheck();
_lastCheckedRealTime = 0f;
DebugGetInGameTime();
}
}
그외에 따로 피드백이 있던 부분은 아니었지만, 날짜를 계산하는 부분을 수정했었다.
처음에는 날짜를 계산시 다음과 같이 했다.
private ESeason _season;
private EWeekday _weekday;
private int _inGameYear;
private int _inGameTotalDay;
private int _inGameDay;
public int InGameYear { get { return _inGameYear; } }
public ESeason CurrentSeason { get { return _season; } }
public EWeekday CurrentWeekDay { get { return _weekday; } }
public int InGameTotalDay { get { return _inGameTotalDay; } }
public int InGameDay { get { return _inGameDay; } }
각 날짜, 요일, 년 과 같은 변수들을 선언하고,
public void CalculateSeason()
{
if (_inGameDay > 28)
{
if (_season == ESeason.Winter)
{
_season = ESeason.Spring;
_inGameYear++;
}
else
{
_season++;
}
_inGameDay = 1;
}
}
private void GoToNextWeekDay()
{
if (_weekday == EWeekday.Sunday)
{
_weekday = EWeekday.Monday;
return;
}
_weekday++;
}
일정 조건마다 이를 체크하며, 수동으로 변화를 주는 식으로 진행했었다.
그러나 나는 TotalDay를 이용한다면, 위 과정을 좀더 간략화 할 수 있을 것이라 생각해 다음과 같이 수정하였다.
private int _inGameTotalDay;
public int InGameYear { get { return (_inGameTotalDay / 112) + 1; } }
public ESeason CurrentSeason { get { return (ESeason)((_inGameTotalDay / 28) % 4); } }
public EWeekday CurrentWeekDay { get { return (EWeekday)(_inGameTotalDay % 7); } }
public int InGameDay { get { return (_inGameTotalDay % 28) + 1; } }
_inGameTotalDay 필드만 가지고, 각 프로퍼티는 전체 날짜를 기반으로 계산하는 방식이었다.
그러나 이렇게 할 경우, 걸리는 점은, 위 프로퍼티를 호출할 때마다 저 연산을 계속 하는 것은 다소 불필요하다고 생각이 들었다.
최종적으로는 다음과 같은 방식을 사용했다.
private int _currentGameYear;
private ESeason _currentSeason;
private EWeekday _currentWeekday;
private int _currentGameDay;
private int _lastCalculatedDay;
public int InGameYear
{
get
{
UpdateDate();
return _currentGameYear;
}
}
public ESeason CurrentSeason
{
get
{
UpdateDate();
return _currentSeason;
}
}
public EWeekday CurrentWeekDay
{
get
{
UpdateDate();
return _currentWeekday;
}
}
public int InGameDay
{
get
{
UpdateDate();
return _currentGameDay;
}
}
private void UpdateDate()
{
if (_lastCalculatedDay != _inGameTotalDay)
{
_currentGameYear = (_inGameTotalDay / 112) + 1;
_currentSeason = (ESeason)((_inGameTotalDay / 28) % 4);
_currentWeekday = (EWeekday)(_inGameTotalDay % 7);
_currentGameDay = (_inGameTotalDay % 28) + 1;
_lastCalculatedDay = _inGameTotalDay;
}
}
적어도 해당 연산을 하루에 한번 작동 시키면 그 다음부터는 캐싱된 값을 return하는 방식을 사용했다.
이러면 적어도 이전 방식과는 다르게 불필요하게 계속 요일을 연산하는 것은 줄어들 것으로 생각된다.
추가적인 개선 점으로는 매일 갱신되는 요일, 일 과는 다르게, 계절과 년도는 매일 갱신할 필요는 없다는 점이다.
해당 부분은 다른 기준을 통해 갱신을 한다면 프로퍼티를 불러올 때 하는 연산의 수를 더 줄일 수 있을 것으로 보인다.
결국 해당 값을 캐싱하기 위한 필드를 다시 생성하고, 이를 계산하기 위한 메서드를 만든 점에서 약간 원점으로 돌아온듯한 기분이 들었다.
그래도 요일과 계절, 년도를 각각 계산을 하던 때 보단 더 간결해진 듯한 느낌을 받았다.
'내일배움캠프 TIL' 카테고리의 다른 글
| 내일배움캠프 56일차 TIL "Rule Tile" (0) | 2024.12.05 |
|---|---|
| 내일배움캠프 55일차 TIL "시간마다 갱신되는 UI만들기" (0) | 2024.12.04 |
| 내일배움캠프 53일차 TIL "Sprite Library와 Sprite Resolver를 이용한 Sprite 처리" (0) | 2024.12.02 |
| 내일배움캠프 52일차 TIL "Happy Harvest 작물 시스템 분석" (0) | 2024.11.29 |
| 내일배움캠프 51일차 TIL "AnimationCurve를 이용한 조명구현" (0) | 2024.11.28 |