'도전과제'에 해당되는 글 1건

원문: https://partner.steamgames.com/doc/features/achievements

통계 및 업적(Stats and Achievements)

개요

Steam 통계 및 업적은 게임에서 사용자에게 지속적인 로밍 업적 및 통계 추적을 제공할 수 있는 쉬운 방법을 제공합니다. 사용자의 데이터는 Steam 계정과 연결되며, 각 사용자의 업적과 통계는 형식이 지정되어 Steam 커뮤니티 프로필에 표시될 수 있습니다.

장점

업적은 게임 플레이어에게 높은 가치의 보상을 제공하는 것 외에도 팀워크와 플레이어 상호 작용을 장려하고 보상하며, 게임 목표에 추가적인 차원을 부여하고, 게임에서 더 많은 시간을 보낸 사용자에게 보상을 제공하는 데 유용합니다.

통계는 플레이 시간, 파워업 사용 횟수 등과 같은 세분화된 정보를 추적합니다. 예를 들어, 여러 대의 컴퓨터에서 수집한 여러 세션의 게임 플레이 통계를 기반으로 업적을 부여하는 등 단순히 게임 내부 데이터를 추적하는 데 사용할 수도 있습니다.

구현 개요

게임의 업적 및 통계 정의

도전 과제는 애플리케이션에 따라 다르며 Steamworks 파트너 사이트의 앱 관리자 페이지에서 설정할 수 있습니다.

게임에서 저장할 수 있는 통계에는 세 가지 유형이 있습니다:

  • INT - A 32-bit (signed) integer (e.g. number of games played)
  • FLOAT - A 32-bit floating point value (e.g. number of miles driven)
  • AVGRATE - A moving average. See: The AVGRATE stat type

Steamworks 파트너 웹사이트는 게임의 통계와 업적을 정의하고 업데이트할 수 있는 인터페이스를 제공합니다. 이를 사용하면 다음과 같이 할 수 있습니다:

  • 초기 통계 및 성과 정의
  • 추가 통계 및 업적 추가
  • 업적 이름, 설명 및 아이콘 업데이트
  • 통계 매개변수 및 제약 조건 업데이트(최대/최소값, 이동 평균 창 크기 등)

통계에는 다음과 같은 속성이 있습니다:

  • ID - 각 스탯에 대해 자동으로 생성된 숫자 ID입니다.
  • Type - 이 통계의 유형 - INT, FLOAT, or AVGRATE.
  • API Name - API를 사용하여 이 통계에 액세스하는 데 사용되는 문자열입니다.
  • Set By - 통계를 수정할 수 있는 사용자를 설정합니다. 기본값은 클라이언트입니다. 자세한 내용은 게임 서버 통계(Game Server Stats)를 참조하세요.
  • Increment Only - 이 스탯을 설정하면 시간이 지남에 따라 값만 증가하도록 허용됩니다.
  • Max Change - 설정하면 통계 값이 한 SetStat 호출에서 다음 호출로 변경될 수 있는 양에 제한을 설정합니다.
  • Min Value - 설정하면 이 통계가 취할 수 있는 최소 숫자 값입니다. 기본적으로 최소값은 기본 숫자 유형(INT_MIN 또는 -FLT_MAX)의 최소값입니다.
  • Max Value - 설정하면 이 통계가 취할 수 있는 최대 숫자 값입니다. 기본적으로 최대값은 기본 숫자 유형(INT_MAX 또는 FLT_MAX)의 최대값입니다.
  • Default Value - 설정하면 새 사용자에 대해 이 통계가 처음에 설정되는 기본값이 됩니다. 설정하지 않으면 기본값은 0입니다.
  • Aggregated - 이 옵션을 설정하면 Steam은 이 통계의 글로벌 총합을 유지합니다. 자세한 내용은 아래의 글로벌 통계를 참조하세요.
  • Display Name - 앱에 표시되는 이 통계의 이름입니다.

AVGRATE 통계에는 다음과 같은 추가 속성이 있습니다:

  • Window - 데이터를 평균화하는 데 사용되는 '슬라이딩 창'의 크기입니다.

AVGRATE 통계는 Steam에서 자동으로 평균을 내는 통계입니다. 자세한 내용은 아래 AVGRATE 섹션을 참조하세요.

업적에는 다음과 같은 속성이 있습니다:

  • ID - 각 업적에 대해 자동으로 생성된 숫자 ID입니다.
  • API Name - API를 사용하여 이 업적에 액세스하는 데 사용되는 문자열입니다.
  • Progress Stat - 커뮤니티에서 이 업적의 진행률 표시줄로 사용되는 스탯을 지정합니다. 스탯이 잠금 해제 값에 도달하면 업적도 자동으로 잠금 해제됩니다.
  • Display Name - 이 업적의 이름은 클라이언트 알림 팝업과 커뮤니티에서 확인할 수 있습니다. 현지화될 수 있습니다.
  • Description - 커뮤니티에 표시하기 위한 이 업적에 대한 설명입니다. 현지화될 수 있습니다.
  • Set By - 업적을 잠금 해제할 수 있는 사용자를 설정합니다. 기본값은 클라이언트입니다. 자세한 내용은 게임 서버 통계(Game Server Stats)를 참조하세요.
  • Hidden? - True라면, '숨겨진' 업적은 사용자가 달성할 때까지 사용자의 커뮤니티 페이지에 전혀 표시되지 않습니다.
  • Achieved Icon - 달성 시 표시되는 아이콘입니다.
  • Unachieved Icon - 아직 달성하지 못한 경우 표시되는 아이콘입니다.

다음은 Steamworks API 예제 애플리케이션(SpaceWar)의 업적 목록입니다:

 

특별 고려 사항

  • 업적 이름과 아이콘은 모든 연령대에 적합한 것이어야 합니다.
  • 기본적으로 게임은 처음에는 100개의 도전 과제로 제한됩니다. 앱이 프로필 기능(Profile Features)의 임계값에 도달하면 업적을 더 추가할 수 있습니다.

사용 방법

게임 내에서 통계 및 도전 과제에 액세스하기:

AVGRATE 통계 유형

이 유형의 통계는 독특하고 매우 유용한 기능을 제공하지만 설명하려면 조금 더 자세한 설명이 필요합니다.

"시간당 획득한 포인트"와 같은 평균 통계를 추적하고자 하는 경우를 생각해 보겠습니다. 한 가지 접근 방식은 두 개의 통계, 즉 INT "총 포인트"와 FLOAT "총 플레이 시간 시간"을 가진 다음 포인트를 시간으로 나누어 시간당 포인트를 구하는 것입니다.

이 구현의 단점은 플레이어가 상당한 양의 플레이 시간을 누적하면 계산된 평균이 매우 느리게 변한다는 것입니다. 실제로 사용자가 게임을 더 많이 플레이할수록 평균의 반응성이 떨어집니다. 사용자가 100시간 동안 게임을 플레이했다면, 계산된 평균은 그 중 약 50시간 정도 "지연"됩니다. 스킬이 증가해도 시간당 포인트가 기대만큼 증가하지 않습니다.

평균 통계 유형을 사용하면 평균에 "슬라이딩 윈도우" 효과를 구현할 수 있습니다. 예를 들어, 이전 몇 시간의 게임 플레이만 활용할 수 있으므로 통계에 플레이어의 현재 스킬 레벨이 더 정확하게 반영됩니다.

이전 20시간의 게임 플레이만 값에 영향을 미치는 "시간당 포인트"를 구현하기 위해 AVGRATE 통계를 설정해 보겠습니다. 이렇게 하려면 다음과 같이 하세요:

  • 평균은 "시간당"이므로 이 통계와 관련된 모든 시간 매개변수의 시간 단위는 "시간"이 됩니다. 이는 통계 자체의 Window 프로퍼티와 아래의 UpdateAvgRateStat에 전달된 "dSessionLength" 파라미터에도 적용됩니다.
  • "AvgPointsPerHour"라는 AVGRATE 통계와 20.0의 Window 속성을 만듭니다(이 값은 "시간" 단위임을 기억하세요).
  • 게임 중 적절한 시점에 다음 매개변수를 사용하여 ISteamUserStats::UpdateAvgRateStat를 호출합니다:
    • pchName - "AvgPointsPerHour"
    • flCountThisSession - UpdateAvgRateStat를 마지막으로 호출한 이후 플레이어가 획득한 포인트 수입니다.
    • dSessionLength - UpdateAvgRateStat를 마지막으로 호출한 이후의 게임 시간입니다. 단위는 통계의 창 프로퍼티에 있는 단위와 동일해야 합니다. 이 경우 "시간"입니다.
  • 예를 들어, 플레이어가 0.225시간(13.5분) 동안 지속된 마지막 라운드에서 77점을 획득했다면, SteamUserStats()->UpdateAvgRateStat( "AvgPointsPerHour", 77, 0.225 )가 됩니다.

위의 예에서 Steam은 현재 라운드 평균 점수인 시간당 342.2점(77을 0.225로 나눈 값)을 이전 값과 혼합합니다. 결과는 플레이어의 지난 20시간 게임 시간 동안의 총 평균을 반영합니다. 현재 사용자에 대한 스탯이 처음 업데이트된 경우 현재 값은 342.2가 됩니다.

이 예에서는 시간 단위로 '시간'을 사용했지만 원하는 시간 단위를 사용할 수 있습니다. 다만 "dSessionLength" 및 Window 프로퍼티의 기본 단위로 해당 단위를 일관되게 사용해야 한다는 점만 기억하세요.

다른 사용자에 대한 통계 가져오기

ISteamUserStats::RequestUserStats를 사용하여 다른 사용자의 통계를 가져올 수 있습니다. 그런 다음 ISteamUserStats::GetUserStat, ISteamUserStats::GetUserAchievementISteamUserStats::GetUserAchievementAndUnlockTime을 사용하여 해당 사용자에 대한 데이터를 가져올 수 있습니다. 이 데이터는 다른 사용자가 새 통계를 업로드해도 자동으로 업데이트되지 않으므로 데이터를 새로 고치려면 ISteamUserStats::RequestUserStats를 다시 호출하면 됩니다.

너무 많은 메모리를 사용하지 않기 위해 최근 사용량(LRU) 캐시가 유지되고 다른 사용자의 통계가 가끔 언로드됩니다. 이런 일이 발생하면 ISteamUserStats::UserStatsUnloaded_t 콜백이 자동으로 전송됩니다. 이 콜백이 전송되면 ISteamUserStats::RequestUserStats가 다시 호출될 때까지 지정된 사용자의 통계를 사용할 수 없게 됩니다.

오프라인 모드

Steam은 통계 및 업적 데이터의 로컬 캐시를 유지하여 오프라인 모드에서도 API를 정상적으로 사용할 수 있도록 합니다. 커밋할 수 없는 통계는 사용자가 다음에 온라인 상태가 될 때를 위해 저장됩니다. 두 대 이상의 컴퓨터에서 수정이 이루어진 경우, Steam은 자동으로 업적을 병합하고 더 많이 진행된 통계 세트를 선택합니다. Steam은 통계 데이터의 로컬 캐시를 보관하므로 게임에서 디스크에 데이터의 로컬 캐시를 보관할 필요는 없습니다. 이러한 캐시가 충돌하는 경우가 종종 발생하며, 충돌이 발생하면 사용자에게는 진행 상황이 되돌아간 것처럼 보이므로 매우 불쾌한 경험이 될 수 있습니다.

게임 서버 통계

ISteamUserStats와 유사하게 게임 서버를 위한 ISteamGameServerStats가 있습니다. 이 서버는 클라이언트와 동일한 방식으로 사용자 통계를 가져올 수 있습니다(위에서 설명한 대로). 또한 통계를 설정하고 업적을 수여할 수도 있지만, '설정 기준'이 GS(게임 서버) 또는 공식 GS로 설정된 경우에만 가능합니다. 게임 서버와 공식 게임 서버의 차이점은 공식 게임 서버는 회원님이 직접 호스팅하고 관리하는 서버라는 점입니다. 공식 게임 서버를 사용하여 통계를 설정하면 사용자가 자신의 게임 서버를 수정하거나 게임 서버로 위장할 수 있으므로 부정행위에 대한 보안이 강화됩니다. 공식 게임 서버를 정의하려면 여기에 서버의 IP 범위를 입력합니다.

게임 서버에서 설정할 수 있는 통계 및 도전 과제는 클라이언트에서 설정할 수 없습니다. 게임 서버는 현재 서버에서 플레이 중인 사용자의 스탯과 도전 과제만 설정할 수 있습니다. 사용자가 서버를 떠나는 경우 최종 통계를 설정할 수 있는 짧은 유예 기간이 있지만, 그 이후에는 새로운 업로드가 거부됩니다. 이는 일관성을 보장하고 악의적인 게임 서버가 언제든지 다른 사람의 통계를 설정할 수 없도록 하기 위한 조치입니다. 이러한 제한을 고려할 때, 스탯을 설정하기 위해 라운드가 끝날 때까지 기다리지 않는 것이 중요합니다. 사용자가 종료할 때 저장할 수 있도록 지속적으로 설정해야 합니다.

클라이언트는 게임 서버가 스탯을 변경하면 자동으로 업데이트됩니다. 그러나 클라이언트와 마찬가지로 서버가 다른 사용자를 위해 로드한 통계는 자동으로 새로 고쳐지지 않으며 오래될 수 있습니다.

통계 초기화

개발 중에는 테스트를 위해 계정 또는 모든 계정의 통계와 업적을 완전히 지우는 것이 바람직한 경우가 종종 있습니다. 계정의 통계를 초기화하려면 bAchievementsToo를 true로 설정한 상태에서 ISteamUserStats::ResetAllStats를 호출하여 업적도 초기화하세요. 이 함수를 호출한 후에는 통계와 도전 과제를 다시 실행하고 메모리 내 게임 상태를 초기화하는 것을 잊지 마세요. 모든 사용자의 스탯과 도전 과제를 전역적으로 지울 수 있는 방법은 없습니다. 그 이유 중 하나는 전역 초기화를 수행하더라도 진행 중인 게임이 초기화를 인식하지 못하고 인메모리 값을 다시 기록할 수 있기 때문입니다. 다행히도 게임에 글로벌 초기화 시스템을 쉽게 구축할 수 있는 방법이 있습니다. 방법은 다음과 같습니다:

  • "버전"과 같은 이름으로 스탯을 정의합니다.
  • 게임에 하드코딩된 통계 버전 번호 넣기
  • 통계가 로드되면 '버전' 통계를 하드코딩된 버전 번호와 비교합니다.
  • 일치하지 않는 경우 ISteamUserStats::ResetAllStats를 호출한 다음 "버전" 통계를 하드코딩된 번호로 설정하세요.

이렇게 하면 전역 초기화를 원할 때마다 하드코딩된 통계 버전 번호만 변경하면 됩니다. 그러면 사람들이 새 빌드를 받을 때 전역 삭제가 수행됩니다.

통계 일관성

관련 통계가 어떻게 일관성이 없어질 수 있는지 고려하는 것이 좋습니다. 예를 들어 "GamesWon", "GamesLost", "GamesPlayed" 통계가 세 개 있을 수 있습니다. 최선의 의도에도 불구하고 통계는 서로 동기화되지 않을 수 있고 실제로 동기화되지 않습니다. 이 경우 이긴 게임과 잃은 게임이 총 플레이한 게임에 합산되지 않을 수 있습니다. "GamesLost" 통계를 제거하고 대신 "GamesPlayed" - "GamesWon"으로 계산하여 이 문제를 해결했다면, 불일치로 인해 "GamesLost"가 음수가 될 수 있습니다. 이 경우 "GamesPlayed" 통계를 삭제하고 "GamesWon" + "GamesLost"로 계산하는 것이 가장 좋습니다.

글로벌 통계

관리자 페이지에서 통계를 집계된 것으로 표시하여 Steam이 모든 사용자의 통계 값을 전체적으로 합산하도록 할 수 있습니다. 이를 통해 경제의 총 돈, 총 킬 수, 좋아하는 무기, 좋아하는 지도, 어느 팀이 더 잘하는 경향이 있는지에 대한 데이터를 얻을 수 있습니다. 반대로 '최다 킬 수'와 같은 통계에는 여러 사용자에 대해 합산하는 것은 의미가 없으므로 사용해서는 안 됩니다. 통계는 사용자의 손에 달려 있기 때문에 이 데이터는 조작될 수 있습니다. 따라서 집계된 통계를 사용할 때는 최소값, 최대값, 증분만(적절한 경우), 최대 변화에 대한 적절한 범위를 설정하는 것이 중요합니다. 최대 변화는 집계된 통계에서 특별한 의미를 갖습니다. 새 값이 업로드되면 글로벌 값은 최대 변경 값보다 더 많이 변경되지 않습니다. 이는 부정 행위자가 글로벌 총계에 얼마나 빨리 영향을 미칠 수 있는지를 제한합니다.

글로벌 총계에 액세스하려면 각 글로벌 통계에 대해 ISteamUserStats::RequestGlobalStats를 호출한 다음 ISteamUserStats::GetGlobalStat를 호출하세요. 지정된 일수만큼의 기록에 대한 ISteamUserStats::RequestGlobalStats를 요청할 수도 있습니다. 이 기록은 매일 통계가 변경된 양입니다. 이 기록은 ISteamUserStats::GetGlobalStatHistory로 액세스할 수 있습니다.

클라이언트에 글로벌 업적 완료 비율을 요청할 수도 있습니다. 이렇게 하려면 먼저 ISteamUserStats::RequestGlobalAchievementPercentages를 호출합니다. 그런 다음 ISteamUserStats::GetMostAchievedAchievementInfoISteamUserStats::GetNextMostAchievedAchievementInfo를 호출하여 가장 많이 완료한 것부터 가장 적게 완료한 것 순서로 업적을 반복합니다. 또한 ISteamUserStats::GetAchievementAchievedPercent를 호출하여 특정 업적의 완료 비율을 얻을 수도 있습니다.

테스트

앱이 출시되기 전에는 Steam 커뮤니티나 라이브러리에서 어떤 도전 과제를 획득했는지 확인할 수 없습니다. 앱에서 사용자가 획득한 업적을 출력할 수 있는 방법이 필요합니다.

게임에 코드를 추가하지 않고 도전 과제나 통계를 지우려면 Steam 클라이언트 콘솔을 사용하면 됩니다. 그런 다음 steam.exe -console로 실행하세요:

  • achievement_clear <appid> <achievement name>
  • reset_all_stats <appid>

Steam 커뮤니티

게임이 출시되면 개인 및 글로벌 업적 진행 상황에 대한 정보가 Steam 커뮤니티에 표시됩니다. 각 플레이어는 커뮤니티 프로필에서 자신이 달성한 업적과 아직 잠금 해제하지 않은 업적을 보여주는 페이지로 이동할 수 있는 링크를 받게 됩니다.

NOTE: 앱이 커뮤니티에 어느 정도 공개될 때까지 업적은 표시되지 않습니다.

각 업적은 Steamworks 제어판에 설정된 대로 해당 아이콘과 이름 및 설명이 표시됩니다. 업적 이름과 설명이 사용자가 선택한 언어로 현지화된 경우 해당 언어로 표시됩니다.

또한 이 페이지와 게임의 기본 Steam 페이지에서 게임의 글로벌 업적 통계로 연결되는 링크가 있습니다. 여기에는 가장 일반적인 업적부터 가장 희귀한 업적까지 순서대로 각 업적을 달성한 Steam 플레이어의 비율이 표시됩니다. 이 정보는 플레이어가 재미있게 볼 수 있을 뿐만 아니라 개발자에게도 유용한 자료가 됩니다: 특별 업적이 충분히 어려운가요? 아니면 너무 어려운가요? (이 정보는 판매 및 활성화 보고서 사이트에서도 확인할 수 있습니다).

'_Diary > Dev' 카테고리의 다른 글

[Stations In Seoul] Devlog #11  (0) 2023.08.25
[Find with Seoul] Devlog #18  (0) 2023.08.25
[Stations In Seoul] Devlog #10  (0) 2023.08.17
[Find with Seoul] Devlog #17  (0) 2023.08.17
[Stations In Seoul] Devlog #9  (0) 2023.08.10
블로그 이미지

RIsN

,