블로그 이미지
지누구루

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2015. 2. 6. 09:46 자유글

어제 오랜만에 2시간정도?

스팀판 울스파에서 한국분 1분과 거의 2시간정도 대전을 했다.

 

아주 예전에 PS3 판에서도 뵌 적이 있는 분이었는데(슈스파4 시절. AE 나오기전)

아마 그 분은 날 기억 못하시겠지 ㅎㅎ

 

여튼 거의 4~50판정도 한거 같은데 이긴 건 3판?

그것도 그분이 방심하셨거나, 울콤 질러서 이긴 게임 뿐.

예전에도 20여판해서 3판인가 이겼는데, 그 때보다도 실력차이가 벌어진 느낌이었다.

 

10시가 넘어가면 그만해야지 했다가 결국 10시 30분 정도까지 더 했는데,

끝나고 나서 스팀친구 신청을 보내고,

'실력차이가 많는 나는데 계속 게임해줘서 감사하다'는 메시지를 보냈다.

메시지를 보내니까, 응답으로 이런 저런 조언을 해주셨는데,

일단 칼승룡 칭찬을 해주신 뒤에,

"잡기풀기"만 늘어도 잘하실거 같다. 라고 말씀해주셨다.

 

사실 알고 있던 나의 문제이긴 했지만,

누군가가 딱, "이게 문제에요" 라고 알려주니, 더 확실해지는 느낌...

사실 잡기 풀기를 잘못하는 문제는 스파4를 처음하던 시절부터 있던건데...

이론적으로는 이해 했는데도, 불구하고 잘못하겠다.

 

지금 잡기 풀기를 잘 못하는 이유는

 

1) 앉아 잡풀 버릇 

서서 풀다가 자꾸 하단을 맞아서 생긴 버릇. 인데,

이게 기상 공방에서는 앉아 잡풀이나 잡풀 세이빙 백대시 같은걸로 해결을 해야 하는데,

무의식적으로 앉아 잡풀을 한다

이러면 기상에 겹쳐 놓는 잡기에도, 기본기에도 다 맞는 병신같은 짓인데도 불구하고,

계속 기상공방에서 앉아 잡풀을 하고 있는 게 문제다.

(스파의 잡기는 발생 3프레임이고, 3프레임째 타격과 겹치면 잡기가 우선순위가 높다.

 그렇기 때문에, 일어나기 전부터 잡기를 입력할 수 있는 공격자쪽이 압도적으로 잡기가 유리하고,

 서서 잡풀을 하는걸 노린 하단 기본기 깔아두기도 앉아 잡풀을 하면 약발이 발동 되기 때문에,

 더욱 무섭게 기본기를 카운터로 쳐맞게 된다.. 그래서 기상공방에서 잡기를 풀면서,

 공격일 경우는 세이빙 백대시를 하는 입력방법이 있는데,

 이게 울스파 오면서 어느정도 제약이 걸렸다)

 

2) 근접 타이밍에 잡기 풀기 타이밍을 놓침

상대가 언제 잡기를 할지에 대한 예측이 너무 부족하다. 가장 심각한건,

상대방이 기술 -> 세캔 대시 한 뒤에 잡기하는건데,

울스파 오면서 대부분의 기술들이 세캔뒤 프레임이 불리해졌음에도 불구하고,

내 반응이 더 느려서 잡풀을 못한다-_-+

 

이런거 고치고 나도 잡풀 잘하고 싶다... 잡풀 잡풀.

으아아아아아

 

posted by 지누구루
2015. 1. 30. 14:20 생각

최근에 가장 열심히 하는 핸드폰 게임은 '크루세이더 퀘스트'(이하 줄여서 '크퀘') 입니다.

크퀘의 재미 요소는 여러가지가 있지만,

그중에서 다른 게임들과의 가장 큰 차이점이라고 생각 하는 점은

"자동 전투가 아니라 직접 플레이 해야하는데, 지루하지 않고 재미있다"

라는 부분이라고 생각합니다.

 

반복 플레이를 아주 많이 해야 하는데, 전투가 재미 없다면,

자동 전투등으로 시간을 보내는 식으로 플레이 하는 경우가 많아지고,

그렇다면 결국 영웅(or 다른 게임에서의 카드), 장비를 모으는 재미 이외에는 없게 됩니다.

즉, 그 부분에서 한계가 명확해지면 재미가 급속도록 반감하게 된다고 생각합니다.

 

크퀘의 전투는. 총 3명의 영웅을 데리고 전장으로 나가며,

시간 단위로 충전되는 덱? 을 잘 조합하여, 1체인, 2체인, 3체인을 쌓고,

그동안 쌓은 SP를 통해서 필살기를 사용하는 형태입니다.

여기서 1체인,2체인등의 체인은 같은 덱이 연속으로 있는 경우 사용할 때 사용하는 것을 말합니다.

 

"어릴때 FC나 SFC로 플레이 했던 카드 배틀 드래곤볼 시리즈가 모바일 형태로 나오면 참 재밌을텐데"

라는 생각을 항상 하고 있었는데,

(카드 선택 행동을 터치로)

 

어? 그렇다면 크퀘식으로 덱이 일정 시간간격으로 추가되면서, 덱의 조합으로 필살기를 쓸수 있는 드래곤볼이면?

(크퀘식의 카드 보충 방식에, FC용 드래곤볼 Z외전 형식의 필살기 사용 구조라면? 어떨까?)

하는 생각이 문득 들었습니다.

 

FC용 드래곤볼 Z외전의 경우, 카드덱의 한자 조합으로 필살기를 사용할 수 있었는데

(가메하메파가 체폭광? 이었던가?)

이 경우 장점이

'약한 스킬은 적은 카드덱으로 만들고 강한 스킬은 여러장의 카드 덱으로 만든다.'

와 같이 스킬의 강력함을 조절할 수 있고,

크퀘로 치면 2체인 스킬을 여러개 등록할 수도 있으며.

조합을 통해 4~5조합 스킬까지 만들수 있다는 장점이 생깁니다.

 

단점이라면, 이 경우, 한 캐릭터의 스킬 사용에 집중되어, 있고,

이걸 파티 단위로 같은 덱에서 쓰게 한다면,

재미를 떠나서 게임 플레이가 너무 어려워지지 않을까 하는 생각이 듭니다.

 

게다가 크퀘는 실시간 전투이며, 드래곤볼Z 외전의 경우 턴제 플레이 인데,

위에서 생각한 방법대로 플레이 하려면, 실시간 전투가 나을지, 턴제가 나을지 잘 모르겠고..

이게 결정나지 않으면 던전 진행 방식을 결정 할 수가 없게 됩니다...

 

지금 팀의 게임 캐릭터와 맵을 조합해서 만들면 꽤 괜찮을것 같기도 한데...

이런 고민들이 해결되면, 은근슬쩍 간단한 기획서라도 써봐야겠습니다....

 

 

posted by 지누구루
2015. 1. 29. 13:53 공부

이번에 쓸 내용은 구지 게임 서버에 국한된 내용은 아니고,

여러 케이스에 적용되는 내용으로, 문장으로 표현하면

 

"수치에 의해서 계산가능한 단계 정보를 따로 저장할 것이냐, 아니며 계산해서 사용할 것이냐"

 

의 문제입니다.

 

(1) 경험치 수치

 

가장 먼저 생각할 수 있는 케이스는 바로 캐릭터의 "경험치"와 "레벨"의 관계입니다.

'총 경험치'를 저장하고, 총 경험치로 부터 레벨을 계산하는 방식이 있을수 있고,

레벨과, 현재 경험치를 저장하는 방식이 있을수 있습니다.

각 경우의 장단점을 간단히 보겠습니다.

 

[1] '총 경험치' 를 저장하고, 총 경험치로부터 레벨을 계산하는 방식

+ 장점

레벨이 따로 저장되지 않기 때문에, 캐릭터 정보의 저장 공간이 줄어듬.

경험치와 레벨이 맞지 않는 현상이 나타나지 않음

(경험치는 10렙 경험치인데 레벨은 9인 경우가 존재할 수 없음)

+ 단점

총 경험치를 저장하는 데이터 타입에 따라 한계값이 존재함(총 경험치가 INT MAX를 넘을수 없다던가)

경험치 테이블이 변경될 경우, 보정이 없으면 레벨 다운이나 레벨업 현상이 일어날 수 있음.

=> 반드시 보정이 필요하다.

경험치 보정이 필요한 경우, 다수의 데이터에 대해 쿼리만으로 해결 하기가 어렵다.

 

[2] '레벨'을 저장하고, 해당 레벨에서의 현재 경험치를 저장하는 방식

+ 장점

경험치 -> 레벨로 변환하는 과정이 없으므로 연산횟수가 약간 적다

DB에서 바로 레벨을 알아 보기 쉽다.

경험치 테이블이 변경될 경우, 레벨은 그대로 유지할 수 있다.

경험치 보정이 필요할 경우, 쿼리만으로 해결할수 있는 가능성이 있다.

+ 단점

경험치 총 획득량과 레벨이 맞지 않는 경우가 발생할 수 있다.

 

인데, 각각의 장단점이 있고, 각 단점을 보완할 수 있는 방법이 있기 때문에,

결국은 선택의 문제가 될 것 같습니다.

그리고 가장 개인적으로 가장 중요하다고 생각하는 점은

 "경험치 테이블이 변경되었을때 얼마나 지원해줄 것인가? "

와 "얼마나 자주 변경이 일어날 것인가" 가 중요한 결정 요소라고 생각합니다.

 

비슷한 상황이 경험치 이외의 곳에서도 필요한 경우가 있습니다.

경험치와는 상황이 다르면서, 비슷한 경우는 "스킬 포인트"가 있는 경우입니다.

 

[2] 스킬 포인트

스킬 포인트는, 레벨업 과정이나 다른 방법을 통해서 획득하고,

스킬을 배우거나, 더 강하게 만들거나(레벨업이나 강화) 할때 소모한다고 가정할 경우

MAX 스킬 포인트만 저장(이것 또한 계산에 의해서 얻을 수 있는 경우도 있습니다) 하고

남아 있는 스킬 포인트를 저장할 것인가?

아니면 현재의 스킬포인트 상태를 보고 -> 사용한 스킬 포인트를 확인 ->

남은 스킬 포인트를 계산하는 형태로 할 것인가?

를 결정해야 할 수도 있습니다.

 

사실 스킬포인트의 경우 더 어려운 점이 있는데,

일부 게임에서는 이 "스킬 포인트"를 아이템 사용 형식으로 더 늘려줄수 있기 때문입니다.

이 경우는 MAX 스킬포인트를 저장 하거나

해당 아이템 사용횟수를 저장해야 하는데, 이 부분의 구현도 여러가지 선택지를 가지게 됩니다.

 

이런 선택지에 영향을 주게 되는 요소는

결국 또 스킬 개편에 의해서 어느 부분이 어떻게 얼마나 자주 변경될것인가? 에 영향을 받게 됩니다.

1) 스킬을 배우거나, 강화할때 사용하는 스킬 포인트가 변경될 경우

2) 스킬 포인트 획득 수치의 변경

3) 스킬 포인트 지급 아이템의 조정에 의한 변경

등을 고려해 볼 수 있습니다.

 

만약 스킬 포인트를 20올려주는 아이템과 50 올려주는 아이템 두 종류가 있었는데,

만약 밸런스 조정에 의해서 이걸 각각 10과 20으로 변경했을때,

기존에 이 아이템을 사용한 유저들에 대한 보정은 어떻게 해줘야할까? 등등

아주 복잡한 선택지를 가지게 됩니다.

(던X 팀에 있을때 SP책 아이템이 있을때 이런 지옥을 겪었었지요..)

 

게다가, 만약 아이템 오류나, 다른 시스템상의 오류로 이런 아이템들이 복사되어 퍼지거나,

의도치 않게 많이 획득할 수 있는 방법이 유저에게 노출되어

일부 유저가 해당 아이템을 엄청 사용했다면,

이런 부분을 쉽게 찾아서 쉽게 보정할수 있는 방법까지도 미리 고려해야 합니다.

(경험치 책은 이정도 고민은 필요 없겠지요..)

("스킬 포인트를 올려주는 아이템을 만듭시다" 라는 한 마디가 미치는 파장이 이정도로 큽니다)

 

 

이런 부분들을 보았을 때,

수치로만 저장할 것인지, 일부분은 계산된 수치값을 저장할 것인지의 결정은 상당히 어렵고,

어떤 특징을 가지는지에 대한 확실한 이해가 필요합니다.

개인적으로 가장 중요한 것은 "어떤 부분이 어떤 범위로 변경될 것인지"에 대한 범위 결정이라고 생각합니다.

 

 

posted by 지누구루
2015. 1. 27. 20:59 공부

먼저, 온라인이 아닌 게임에서의 타격 과정에 대해서 살펴 보겠습니다.

여러 액션게임중에서도 일단은 쉽게 설명하기 위해서, 1:1 대전 게임을 생각해 보겠습니다.

1:1 대전게임이면 1P의 캐릭터 A, 2P의 캐릭터 B가 있다고 가정하겠습니다.

 

일반적으로 게임은 일정 시간(대부분은 1프레임)동안 입력된 동작을 모아서

다음 프레임에 그 입력에 대한 액션을 실행하는 형태로 진행이 됩니다.

(이걸 프레임이라고 해야 하는지 정확한 용어는 모르겠지만, 내부에서는 저는 Tick이란 용어를 사용합니다. 이해를 위해서 일단 게이머들에게 익숙한 프레임이라는 표현을 사용했습니다. 게이머들에게 입력이나 화면 갱신의 최소단위가 프레임인거 같아서 입니다.)

 

온라인이 아닌 게임에서는

1) 1P가 공격 버튼을 입력 

2) 다음 프레임에 A의 공격이 나감과 동시에 타격이 발생(타격판정 발생 프레임 같은 내용은 일단 무시)

3) 같은 프레임에 데미지 계산

4) 같은 프레임에 발생한 데미지에 대한 B의 체력 게이지 화면 정보 갱신

공격의 발생부터 타격, 그리고 데미지 계산, 그리고 데미지의 표시까지 한번의 프레임에서 모두 나타낼 수 있습니다(2,3,4번 과정)

 

그렇다면 온라인 게임에서는 어떤게 달라질까요?

데미지 계산을 어떤 방식으로 하냐에 따라서 크게 달라질 수 있지만,

보통 클라이언트 해킹(변조)의 위험으로부터 보호 하기 위해 "데미지 계산"을 서버에서 하는 경우가 일반적입니다.

(충돌체크까지 서버에서 하는 경우도 있습니다)

 

그렇다면 위에서 말한 2)번 단계 이후 인 데미지 계산 -> 적용의 과정이 한 프레임에서 일어나지 않게 됩니다.

즉, 타격이 발생했으니까 처리를 해달라! 라고 서버로 요청하게 되고, 응답을 받을 때까지 시간이 흐르게 됩니다.

문제는 이게 온라인, 즉, 네트워크를 타고 움직이기 때문에, 항상 일정하지 않고, 몇 초후에 올 수도 있습니다,

이 과정에서, 온라인상에서 응답시간이 길어져서, 늦게 오게 되는 현상이 일반적으로 서버측 "렉"이라고 부르는 녀석입니다.

 

이 렉에 대한 처리를 어떤 방식으로 하느냐에 따라서, 렉이 나타나는 현상도 다르게 되는데,

제가 아는 현상중에 아래와 같은 것들이 해당됩니다.

 

1) 버튼을 눌렀는데, 공격이 한참 뒤에 나감

- 공격의 발생도 서버의 통신 후에 나가는 경우입니다. 구지 검증이나 데미지 처리가 아니더라도, 서버로 부터 응답을 받고 공격이 발생하는 경우는 이런 렉이 발생합니다.

 

2) 공격은 나갔고, 타격도 발생했는데, 데미지가 나~~중에 들어감

- 공격 발생과 타격은 서버통신을 거치지 않고 먼저 실행 하고, 데미지 계산을 서버 응답으로 처리하는 경우입니다. 보통 타격 피드백을 중요시 하는 게임에서 많이 사용하는 방법입니다.

 

3) 공격은 나갔고, 타격도 발생, 데미지도 이미 들어간 거 같은데, 나중에 갑자기 상대방의 체력이 변경됨.

(상대방의 체력을 다 깎았는데, 안죽는 경우도 이쪽 계열)

- 공격 발생과 타격, 데미지 계산까지 클라이언트에서 했지만, 서버 응답에 의해 보정을 하는 경우 입니다. 2번 경우보다 타격감이 좀 더 좋지 않나.. 하고 생각합니다.

 

 개인적인 생각으로는 약간 예외적인 케이스가 디아블로3가 아니었나 싶습니다. 특히 마법이나 화살같은 투사체의 경우인데, 공격을 쏘는 모션자체는 클라이언트에 바로 뿌려주지만, 투사체의 발생 자체가 서버렉으로 인해 늦게 나가는 경우였습니다. 정확한 방식은 발표된 바가 없어서 알 수 없지만, 투사체 발생자체는 서버검증과 계산을 거쳐서 발생하는데, 공격 모션은 이와 상관없이 재생되는 경우였다고 생각합니다.

 

 

이런 현상에서 한발짝 더 나가서 생각을 해봅시다.

사실 진짜로 하고 싶었던 이야기는 이쪽입니다 ㅎㅎ

지금까지 설명한 내용을 요약하면 'A가 B를 타격하면 서버를 거쳐서 데미지 계산이 된다'이며,

'처리방식에 따라서 서버렉이 나타나는 유형도 다르다'는 것도 간단히 설명하였습니다.

 

자 여기서 이제 1:1 게임이 아니라, 여러 캐릭터가 다수의 몬스터를 타격하는 게임에 이 방식을 적용한다고 생각해 봅시다.

특히, 범위타격의 기술을 10마리의 몬스터가 모여 있는 곳에 내려치는데, 이 공격이 초당 5회 공격을 한다고 가정해 봅시다.

단순 계산으로 아무 최적화도 거치지 않는다면. 이론상 1회의 공격으로 1초간 50개의 패킷이 발생합니다(10마리 * 5회).

10마리고 초당 5회라고 가정했을때 이정도인데,

만약에 4명의 파티원이 30마리의 몬스터가 있는 곳에 같은 기술을 동시에 사용했다고 가정하면?

4(파티원) * 30 * 5 = 600

초당 600개의 패킷이 하나의 서버에 몰리게 됩니다.

물론 이 4명만 있으면 초당 600개 패킷을 처리하는건 크게 문제가 안될 수 있지만....

동시에 플레이 하는 유저가 몇천명, 몇만명 단위가 된다면?

 

그렇기 때문에 위에 말한 내용을 최적화 하는 과정이 필요하게 됩니다.

일정 시간내 데미지 계산을 몰아서 한다던지,

스킬에 의한 총 데미지 계산은 한번에 하고 보여주는 것만 나눠서 보여준다던지 하는 방법들을 사용하게 됩니다.

하지만 이런 방법들은 실제 게임 플레이의 타격감이나, 좋은 피드백에 영향을 줄 수 있기 때문에, 실제 개발시에 어떤 방법으로 최적화 할지 결정하는 것도 중요한 요소입니다.

 

다시 한번 말하면, 서버에 의한 데미지를 계산하는 이유는, 클라이언트에서 이 계산을 하게 되면, 클라이언트 해킹으로 마음대로 데미지를 줄 수 있게 될 가능성이 열리기 때문입니다.

(이런 것 때문에 위치 검증이나, 충돌체크도 서버에서 하는 경우도 있는거라고 보시면 됩니다)

 

하지만 이런 최적화도, 결국 절대적인 타격수(패킷수) 앞에서는 장사가 없습니다.

그렇기 때문에 온라인으로 여러명의 유저가 동시에 몬스터와 싸우는 게임들은 보통

(1) 파티원의 수

(2) 동시 출현 몬스터의 수

(3) 범위 스킬인데 동시타격 개체의 수

가 제한되게 됩니다.

(또는 몬스터를 멀리 떨어뜨려 소환하고, 구역별로 처리를 따로 하는 방법이라던가)

 

이런 것을 제한하지 않고, 마음껏 할 수 있게 하고, 동시 발생 패킷수가 많아지면,

결국 서버의 초당 패킷 처리 속도를 초과하여, 서버에 처리못한 패킷이 쌓이게 되고,

결국 서버가 점점 느려져서 문제가 발생하게 됩니다.

 

물론 단순히 하나의 서버에 접속하는 접속자의 수를 제한하고,

사람이 늘어날수록 서버를 늘려서 대응하는 방법도 있습니다.

특히 요즘은 클라우드 컴퓨팅에 의해서, 서버 추가 삭제가 쉬워졌기 때문에, 이 방법도 어느정도 희망이 있지만,

반응성을 중요시하는 액션게임의 서버로 클라우드 서버를 사용하는 것은 아직은 시기 상조가 아닌가 싶습니다.

(물론 개인적인 의견입니다)

 

 

틀린 내용이 있으면 지적 감사히 받겠습니다.

 

posted by 지누구루
2015. 1. 14. 16:25 공부

정확히 어느 버전부터 가능한지는 잘 모르겠지만,

개인적으로 사용하는 디버깅 기능중에, 꽤 유용하게 사용하고 있는 기능이 있어서 정리해봅니다.

 

원래는 이런 것도 팁이냐, 당연히 다 아는거 아니냐 라고 생각했는데,

더 기본적인 것도 알려주는 글이 있길래... 요것도 한번 남겨 봅니다 ㅎㅎㅎ

 

간단한 코드부터 잠시 보겠습니다.

그냥 VS화면을 캡쳐 했습니다.

 

 

아주 간단한 코드입니다.

testArray 라는 배열을 만들고,

index가 10의 배수인 곳의 값을 10으로 세팅한 다음,

루프를 돌면서 모든 배열의 값을 출력합니다.

 

여기서 잘 보시면 두번째 for문에 마름모 모양의 브레이크 포인트를 볼수 있습니다.

그리고 그 가운데 하얗게 표시가되어 있습니다.

 

해당 위치에 F9로 브레이크 포인트를 건 뒤에

붉은색 원으로 표시되는 부분에 마우스 우클릭을 하면 몇가지 메뉴가 뜹니다.

 

그중에서 여기서 소개할 메뉴는

"적중될 때" 메뉴 입니다.

 

이 메뉴는 해당 브레이크 포인트가 걸릴때,

실행을 멈추지 않고, 해당 메뉴에서 등록된 내용을 출력창에 뿌려주는 기능입니다.

게다가 "조건" 항목과 같이 사용할 수 있기 때문에,

'특정 조건에 걸릴때, 내가 원하는 값을 출력 창에 뿌려라' 라는 명령을 할수 있습니다.

 

위의 브레이브 포인트에 설정된 값은 다음과 같습니다.

 

 

요건 조건값으로 testArray[i]에 0보다 큰 값이 들어 있는 경우에.

 

 

 

testArray Value - i : {i}, value : {testArray[i]}

를 출력해라. 라는 의미입니다.

 

창에 설명이 있지만 어떤 값을 출력하려면 {} 로 감싸서 변수를 지정하면 되고,

그 안에 들어가는 내용은 변수가 아닌 함수 호출이어도 되지만, 리턴값은 존재 해야 합니다.

느낌상으로는 {} 사이에 있는 코드를 evaluate 해서 출력하는 것 같습니다.

(evaluate를 여기서 적절히 뭐라고 한글로 적어야 할지 모르겠어서 걍 evaluate라고 씀)

 

위의 내용을 디버그 모드로 실행하면

출력창에 요렇게 찍힙니다.

 

 

조건에 맞춰서, 출력하려는 값이 출력되는걸 볼 수 있습니다.

위의 예에서는 제가 지워버렸지만,

기본적으로 제공하는 값으로, 어느 함수에서 호출되는지 같은것도 찍어줄 수 있습니다.

 

브레이크를 실제로 걸어서 멈춰버리면 멀티쓰레드 상황에서 디버깅이 너무 어려운 경우라던가,

일정 시간 이상 ping에 응답이 없으면 disconnect 처리를 해놨는데,

디버깅하다가 걸리는 일도 있었고 ...

사실 특정 조건일 때, 몇몇 상태값만 확인하면 되는데, 일일이 멈춰서 단계 따라가는게 귀찮았는데,

마침 같이 일하던 동료가 이 기능을 알려줘서 

아주 유용하게 사용하였고, 그 이후로 지금도 애용하고 있습니다.

 

별거 아닌 팁이지만, 남겨둬 봅니다 ㅎㅎㅎ

 

posted by 지누구루
2014. 12. 11. 14:51 공부

오랜만에 업무와 관련된 내용으로 글을 써봅니다.

꽤 오래전에 만든 구조이긴 한데, 현재까지 사용해본 결과 나름 괜찮은 구조라고 생각해서 글로 남겨봅니다.

 

관련된 내용은

"게임에서 아이템을 사용했을때의 효과" 를 서버측에서 필요한 기능을 구현 하는 내용입니다.

어렵지 않은 내용이고,

이미 존재하는 패턴이라서 특별히 좋은 구조다 라고 할만한 건 아닙니다.

 

일단 기본적인 생각은

1) 아이템을 사용 하고 차감하는 기능

2) 아이템을 사용함으로써 발동되는 기능

을 분리하자고 생각한 것에서 출발한 구조입니다.

 

분리하자고 느낀 이유는 가장 처음에 몸담았던 게임의 아이템 사용 구조가,

아이템에 새로운 기능을 추가할때마다, 완전히 각각 새로 구현해야 하는게 비효율적이라고 느꼈기 때문이며,

그리고 같은 기능인데, 적용하는 수치가 다르다거나 하는 정도의 변경만 가지는 새로운 아이템 추가,

또는 완전히 같은 기능인데, 아이템을 새로 만들어야 하는 경우

(같은 옵션인데 이벤트로 지급하기 위해 기간제로 만들거나 하는 경우)

그때마다, 아이템 작업을 프로그래머가 직접 해야 하는 것이 비효율적이라고 생각했기 때문입니다.

 

+ 아이템 사용쪽 코드 흐름

- 네이밍 규칙은 회사에서 사용중인 부분이 좀 있습니다. 함수 이름에 'on' 을 붙이는건 어떤 행동이 일어 났을 때 처리되어야 하는 함수를 뜻합니다. onUseItem -> 아이템이 사용되었을때 처리해야 하는 일

void useItem(playerInfo,itemInfo,parameter)
{
    // 1. 아이템 사용 조건체크 - 수량 체크나 쿨타임 체크 등등
    if( isItemUsableState(playerInfo,itemInfo) == false )
        return;

    // 2. 아이템에 연결된 기능을 실행
    if( executeItemFunction(playerInfo,itemInfo,parameter) != no_error )
        return;

    // 3. 아이템 사용 후속 조치 - 쿨타임 갱신 등등
    onUseItem(playerInfo,itemInfo);

    // 4. 사용 아이템 삭제(내용에 따라 한번에 여러개 삭제도 가능)
    deleteItem(playerInfo,itemInfo,parameter);
}

 

받는 파라메터는

playerInfo : 아이템을 사용한 플레이어 정보(캐릭터 정보가 포함될수도)

itemInfo : 사용한 아이템의 정보(현재 가지고 있는)

parameter : 아이템 사용에 필요한 추가 정보

추가 정보의 경우, 예를 들어, 장비에 사용하는 아이템이라면 해당 장비의 정보까지 포함이 됩니다. 이 내용은 아이템마다 내용이 다르므로 범용적으로 받을 수 있어야 합니다.

범용적으로 데이터를 받는 방법에는 여러가지가 있겠지만, 저는 그냥 스트링으로 넘기고 사용하는 쪽에서 파싱해서 쓰도록 했습니다.

 

"아이템에 연결된 기능이 실패하면 아이템 사용이 되지 않습니다"

 

이중에서 밑줄 그은 executeFunction() 함수의 내부는 아래와 같습니다.

error_code executeFunction(playerInfo,itemInfo,parater)
{
    functionType = itemInfo->getFunctionType();
    functionExcutor = getProperExecutor(functionType);

    return functionExecutor->execute(playerInfo,itemInfo,parameter);
}

내용을 간단히 보면.

(1) 아이템에 연결된 기능이 무엇인지 찾은 다음

(2) 해당 기능을 실행할 executor 를 찾아서

(3) 해당 executor의 기능을 실행 합니다.

 

여기서 아이템에 연결된 기능, 코드에서는 functionType만 파라메터로 사용해도 무관합니다.

사실 itemInfo는 여기까지만 존재해도 되는경우가 많습니다.

이 코드에서 itemInfo를 다 넘기는 이유는,

기능과 연결된 아이템의 정보를 다시 검증하기 위한 용도와,

기능 사용에 필요한 추가적인 데이터가 아이템 정보에 있을 경우를 위함입니다.

반드시 있어야 하는 파라메터는 아닙니다.

 

위 내용중 getProperExecutor() 함수는 함수로 빼놓기는 햇지만 큰 기능이 있는건 아니고,

type에 연결된 executor를 그냥 돌려주는 용도입니다.

저는 배열로 만들어 놓고, type에 해당하는 index에 있는 executor를 그냥 돌려주도록 했습니다.

 

이제부터는 실행되는 Function Executor에 대한 내용을 살펴볼텐데,

template method 패턴이 사용되기 때문에 미리 코드를 보고 다시 설명하겠습니다.

class CFunctionExecutor
{
private :
    playerInfo_;
    itemInfo_;

public :
    error_code execute(playerInfo,itemInfo,paramter)
    {
        itemInfo_ = itemInfo;
        playerInfo_ = playerInfo;
        if( _parseParameter(parameter) == false )
            return error_parse;

        error_code = _execute();
        _clear();

        return error_code;
    }

protected :
    virtual bool        _parseParameter(parameter){};
    virtual error_code  _execute()=0;
    virtual void        _clear() {};
};

class CEmptyExecutor : public CFunctionExecutor
{
protected :
    virtual error_code  _execute() {return no_error;}
};

 

CFunctionExecutor 가 최상위 클래스이며,

CEmptyExecutor 는 상속받아 만들어진 클래스 입니다.

(생성자,파괴자는 생략하였습니다)

 

CFunctionExecutor의 execute() 함수를 보시면

_parseParamter(), _execute(), _clear() 가 차례대로 사용되고 있습니다.

 

이중에 _execute() 함수만 순수 가상함수로, 상속 받은 클래스들은 반드시 이 함수를 구현해야 합니다.

parse와 clear의 경우는 할 필요가 없는 기능들이 많아서 빈 함수로 일단 넣어놓고,

상속받은 클래스에서 재정의 할 필요가 있으면 재정의 해서 사용하도록 하였습니다.

 

일단 아무 기능도 하지 않는 EmptyExeucotr()의 경우 parse와 clear역시 할게 없기 때문에 _execute() 함수만 재정의 하였습니다.

 

_parseParameter() 함수는 넘어온 파라메터에서 필요한 파라메터를 다시 정리하는 부분입니다.

_execute() 함수에서는 파싱된 데이터를 기반으로 기능을 실행하고

_clear() 함수에서는 기능 실행에 사용된 데이터를 초기화 하도록 합니다.

 

예를 들어, 사용할 경우 플레이어에게 버프를 주는 아이템을 만들고 싶다. 라고 하면

class CBuffExecutor : public CFunctionExecutor
{
protected :
    buff_info_;

protected :
    virtual bool        _parseParameter(parameter);
    virtual error_code  _execute();
};

bool CBuffExecutor::_parseParameter(parameter)
{
    // buff_info_ = 데이터 만들기.
}

error_code CBuffExecutor::_execute()
{
    // 버프 시스템 호출
    // CBuffSystem::buff(playerInfo_,buffinfo);
}

 

정도로 구현됩니다.

(실제 적용된 코드와는 많은 차이가 있습니다)

 

이렇게 되면 새로운 아이템 기능 추가의 경우

새로운 클래스를 CFunctionExecutor 상속받아서 생성하고

경우에 따라 _parseParameter(), _execute(), _clear() 를 구현하면 완성 됩니다.

 

이미 있는 기능을 새 아이템에 넣고 싶다면

아이템 정보에서 functionType을 같은 걸로 연결만 하면 가능합니다.

(이건 아이템 스크립트 작업자의 몫!!)

 

좀더 복잡한 기능이 필요한 경우에는,

복잡한 기능에 필요한 데이터를 parameter에 같이 넘기거나,

아이템 정보에 포함시켜 놓아서 연결해도 괜찮습니다.

 

구조 자체는 예~~~전에 보았던 Test Unit 쪽 코드와 구조가 완전히 동일합니다.....(어디서 봤더라-_-)

prepare 하고 test 하고 post 뭐시기 하고 이런 과정이었던거 같습니다.

 

글이 꽤 길어졌습니다.

이만 마무리!!!

 

 

 

posted by 지누구루
2014. 10. 31. 20:01 자유글

못버티겠다는 느낌이 들어서 점심먹고 집에와서 누움.

엄청난 악몽들만 잔뜩 꾸고...

잠에서 깼는데, 너무 무서워서 눈을 뜨지도 못하겠는 상태로 다시 잠들고 악몽을 꿈..

 

자고 있는 나를 누가 막 때리는거 같아서 눈을 떴더니 왼팔이 나를 막 때리고 있음..

헉 하고 놀라면서 멈춤. 근데 이게 꿈인지 레알인지 기억이 안남..

느낌적인 느낌으로는 자면서 막 말도 하고 있는거 같음..(잠결에 내 목소리를 내가 들은 거 같음)..

 하아... 요즘 악몽을 꾸는 빈도수도 너무 높음... 잠은 좀 편하게 자게 해줘...

 

인생에 3번째 악몽시즌...(1-졸업논문쓸때, 2-던x 넥슨빌링 작업할 때)

 

이런거 보면 게임 서버 개발자라는 직군이 나랑 안맞는건 아닐까.. 하고

다시 생각해보게 된다..

 

posted by 지누구루
2014. 10. 25. 16:04 예전에 했던 게임/스파4

스파4를 해보기 이전까지는

킹오파 02? 정도가 그나마 콤보 연습도 좀 해보고, 잘하려는 노력을 해본 마지막 게임이었다.

심지어 캡콤 게임은 제일 처음 오리지날판의 스트리트 파이터2 이후에 열심히 했던 게임은

없다고 말해도 좋을 정도로 많이 하진 않았다..

(그나마 스파제로1이나, 사립 저스티스 학원 정도?)

 

그러다 스파4를 조금 깊게 플레이 하면서 이런 저런 시스템들을 알게 됐는데,

그런 시스템상의 결정들을 하게 된 이유는 정확히 알 수 없더라도,

그 시스템의 심오함? 같은 것에 매료 되었다

 

그래서 알고 있는 스트리트 파이터4 시리즈의 시스템들을 정리해두기 위한 글이다.

 

+ 기본기들의 동시 입력 우선규칙.

스파4시리즈는 킥이 펀치보다 우선순위가 높으며, 강력한 쪽이 더 우선 순위가 높다.

예를 들어, 약펀치 + 약킥 을 동시에 입력하면 약킥이 발동되며,

약펀치 + 중펀치 를 동시에 입력하면 중펀치가 발동된다.

 

+ 세이빙 우선 규칙

기본기와 세이빙이 같이 눌러졌다면 세이빙이 나간다. 잡기와 세이빙이 겹쳐도 세이빙이 나간다.

=> 필살기 입력과 겹칠경우 우선순위는 확인이 필요할 듯(예를 들어 류로 236 중펀치+중킥을 누르면 뭐가 나가는지...)

=> 테스트 결과 236 중펀치+중킥 입력시 세이빙이 나간다. 필살기 입력보다 세이빙이 우선순위가 높다.

 

+ 잡기는 보고 풀 수 없도록

스파4 시리즈의 잡기는 게임에서 가장 빠른 기본기와 발동이 동일하며, 기본기와 겹칠 경우 기본기를 이기도록 되어 있다.

즉 프레임의 유불리 없이 똑같이 내밀 경우, 잡기를 이길수 있는건 잡기보다 빠른 발동 프레임을 가진 일부 필살기 뿐이다(또는 무적 or 잡기 무적이 달린 필살기류)

잡기의 발동은 3프레임이며, 잡기 풀기입력 가능 프레임은 7프레임(신생의 서 참고).

서서 잡풀과 앉아 잡풀의 경우 조금 다를 수 있는데, 앉아 잡풀의 경우 잡기와 잡풀이 동시에 입력되었다고 가정할 경우, 막는쪽에서 앉아 약킥이 발동되어 버리므로, "경직중엔 잡풀 안됨" 규칙에 의해서 잡풀이 되지 않는다.

서서 잡풀의 경우, 자신의 잡기가 발동되는 3프레임 중에도 잡기 풀기로 인정되기 때문에, 서서 잡기를 푸는 쪽이 3프레임만큼 더 입력이 쉽다.

여튼 스파4는 잡기를 보고 풀 수 없도록 했기 때문에 근접 공방이 대부분 이 잡기 or 잡풀과 관련되어 이루어지게 된다.

 

+ 캔슬 규칙

연타 캔슬 - 약 공격에만 성립하는 캔슬로 약 공격은 공격 발동후 가드나 히트 경직중이라도 다시 캔슬해서 공격을 낼 수 있다. 모든 약공격에 적용되는 것은 아니며, 연타 캔슬이 불가능한 약공격 들도 있다(ex 가이 하단 약킥, 양 하단 약킥). 공격이 히트될 때, 밀려나는 거리가 있기 때문에, 아무리 연타 캔슬이 빨리 된다고 하더라도 결국 서로 밀려나서 3~4히트 정도까지는 가능하다. 대신에 아래에서 설명할 강제 연결로 연결한게 아니라면 연타캔슬로 연결된 기본기에서는 필살기로의 캔슬이 불가능하다.

기본기 캔슬 필살기 - 기본기 발동이후 유지 / 경직을 캔슬하고 필살기로 연결할 수 있다(불가능한 필살기들도 있음. 이건 각 필살기의 특성이 '캔슬 가능'인지 불가능인지에 달려 있다)

EX 세이빙 캔슬 - 원래는 캔슬이 불가능한 기본기나 필살기라도 EX 세이빙 캔슬을 통해 게이지 2개를 소모하며 캔슬 시킬 수 있다(불가능한 기본기/필살기들도 있음)

하이 점프 캔슬 - 일부 캐릭터들(이부키,바이퍼)이 가지고 있는 캔슬로, 하이 점프를 캔슬하여 대시나 필살기로 연결할 수 있다. 하이점프 입력에 의해 캐릭터는 점프를 하려고 하지만, 점프 하기전에 캔슬할수 있는 타이밍이 있어서, 대시나, 다른 필살기 입력으로 점프를 캔슬할 수 있다.

 

+ 음입력

 버튼을 눌렀다가 뗄 때에도 입력이 들어가는 것을 말한다. 예를 들어 류로 강펀치 버튼을 눌러놓은 채로, 파동권 커맨드를 레버 입력후 버튼을 떼도 파동권이 나간다. 대표적인 활용처는 파동권 견제할 때 사용하는 방법이 있다. 파동권을 1번 쓰고 난뒤, 상대방이 가드할것을 예상한 타이밍에 다시 파동권을 입력을 넣었는데, 상대방이 제자리 점프등으로 파동권을 피해버리면, 1화면 파동권 1개 규칙에 의해서 파동권이 나가지 않고, 해당 펀치 버튼의 기본기가 그냥 나가게 된다. 이때 음입력으로 파동권을 사용했다면 아무 기본기도 발동되지 않기 때문에, 이 헛방을 노린 공격에 당하지 않게 된다.


+ 선입력

경직은 여러가지가 있는데, 공격이 지속시간을 끝내고 거둬들이기까지의 경직, 상대의 공격을 가드했더나, 히트당했을 때의 경직등이 있다. 이때는 버튼을 누르거나, 레버를 돌려도 아무것도 나가지 않는데(경직중이니까 당연), 이때 필살기의 레버 입력을 미리 해놓으면, 경직이 끝난후 버튼 입력만으로 필살기가 나가는 시스템이다. 이 시스템이 없다면, 경직이 끝나는 프레임에 바로 나가는 리버설 입력이 거의 불가능해지므로 리버설 시스템과도 밀접한 연관이 있다고 할수 가 있다. 이 시스템이 있기 때문에, 할수 있는게 여러가지가 생기는데, 기본기를 깔아두고, 필살기 레버 입력을 한 다음, 히트 확인후 버튼 입력만으로 필살기를 확정 히트 시킨다거나, 레버를 2바퀴 돌리는 류의 지상 울콤을 가능하게 해주는 스킬이다(장기에프로 대시후 울콤1이나 기본기 깔아두고 울콤1 발동이 여기에 해당).

추가로 상대방의 슈퍼콤보나 울트라 콤보 발동시 연출되는 암전 상황에도 선입력이 가능하다. 이게 가능하기 때문에, 상대방 필살기에 의한 암전시에, 무적을 가진 기술을 선입력해놓음으로써 파훼할 수도 있다.

 

+ 강제 연결

강제연결. 이란 말이 어디서 정의된 말인지는 모르겠지만 캔슬이 아닌 콤보연결시 사용한다. 기본적으로는 기본기든 필살기든, 어떤 공격이든지 발생 -> 지속 -> 회수의 프레임을 가지게 된다. 그리고 공격을 맞는 쪽은, 히트시 "경직" 프레임을 가지게 된다. 히트시 경직은 다른 기술이 나가지 않고, 히트 모션이 출력되는 시간을 말하게 되므로, 만약 이 경직중에 다른 공격이 들어온다면 가드할 수가 없게 된다. 여기서 조금더 생각을 뻗어 나가면, 공격을 히트 시켰을때, 상대방의 경직이 풀리는 시간 보다, 나의 다음 공격의 발생이 더 빠르면 이 공격은 캔슬이 아님에도 불구하고 연속으로 입력이 가능하게 된다. 이게 강제연결의 기본 원리이다.

예를 들어, 류의 앉아 약펀치의 경우, 히트시 유리 프레임이 +5 이다. 즉, 류의 앉아 약펀치가 히트한뒤, 모션을 모두 회수했지만, 상대방은 5프레임뒤에 히트 경직이 풀린다는 뜻이다. 그렇다면? 발생이 5프레임 이하인 모든 공격기술을 아주 정확하게 입력하면 연결이 가능하다는 말이다. 대표적으로 승룡권은 3프레임 발생의 필살기이다. 즉, 약펀치를 캔슬해서 승룡권을 사용하지 않더라도, 강제 연결로 연결이 가능하다. 게다가 류는 하단 강킥이 발생 5프레임이므로, 앉아 약손 -> 하단 강킥이 강제연결로 콤보가 성립된다.

하지만 이런 경우 아주 여유롭게 강제연결이 가능한 기술은 매우 드물고, 공격이 히트하게 되면 상대방이 히트 경직과 함께 조금씩 거리가 멀어지기 때문에, 하단 약손을 무한으로 넣을 수는 없다. 게다가 이 연결은 1~2프레임의 아주 짧은 시간에 정확히 입력해야 하기 때문에, 프레임단위로 버튼을 계속해서 연타할수 없다면, 정확한 입력을 요구한다. 즉, 앉아 연타 한다고 해서, 무조건 히트 시킬수는 없다(물론 류의 앉아 약펀치는 연타캔슬 가능한 기본기이기 때문에 마구 연타하면 연결은 된다. 하지만 연타 캔슬에서는 필살기 연결이 되지 않기 때문에, 약손 연타로만 공격이 끝나게 된다). 류의 앉아 중펀치가 연속으로 들어가는 기본기이지만, 연타할 경우 연결될때도 있고, 안될때도 있다.

 

+ 츠지식 입력

 츠지라는 일본 사람이 처음 고안했다고 하는 입력 방식이다. 슬라이드 입력법과 유사한데, 약간 다르다. 강제연결시 1프레임의 여유를 더 가질 수 있게 해주는 입력 방식이다. 예를 들어 류로 앉아 중펀치 -> 앉아 중펀치 강제 연결일 경우 첫 중펀치는 그냥 중펀치를 누르고 두번째 중펀치는 중펀치 -> 약펀치를 아주 빠르게 아주 약간의 틈을 두고 연속으로 입력을 한다. 이렇게 되면 트레이닝 모드에서 살펴볼 경우, 중펀치 -> 중펀치 + 약펀치 로 입력이 나타나는데, 스파는 강한 공격 우선 법칙이 있기 때문에, 아주 짧은 시간에 중펀치를 2번 입력한것과 같은 효과가 나타난다(뒤의 중펀치 + 약펀치가 중펀치로 인정된다). 츠지식 입력은 강제 연결에 1프레임의 여유를 주기 때문에, 강제 연결 난이도를 낮추는데 많은 기여를 한다(그래도 어렵긴 어렵다 ㅠㅠ)


+ 주입(option select)

 주입과 option select는 개념이 조금 다르긴 하지만 기본적으로는 "같은 입력으로 상대방의 여러 행동에 대응" 하는 것을 통칭한다고 보아도 좋다. 기본적인 개념은 경직또는 여러 이유로 필살기가 발생하지 않는 상황을 이용하는 것이다. 가장 쉬운 예로, 류로 점프 강펀치를 치면서 아주 빨리 강용권을 입력할 경우, 상대가 강펀치를 맞거나, 가드하면 히트 or 가드 경직에 의해 강용권이 발생하지 않고, 세이빙으로 받아 내거나, 백대시를 하면 강용권 선풍각이 발동되는 입력법이다. 이 내용은 울트라 콤보에도 적용되는데, 페이롱을 예로 들경우, 앉아 약킥을 입력하며 아주빨리 울트라 콤보를 입력해두면, 상대방이 히트 or 가드가 되면 앉아 약킥 -> 앉아 약펀치(or 서서 약펀치)가 나가며(약공격 연타 캔슬 우선 법칙에 의함), 상대가 백대시하거나 세이빙으로 받으면 울트라 콤보가 나가는 방식이다. 가장 쉬운 주입은 류로 앉아 중발 -> 파동권을 항상 입력해두는 것인데, 상대가 가드하거나 맞으면 파동권이 나가고, 그렇지 않으면 앉아 중발만 나가게 된다.


. 일단 이정도로 마무리..  

 

posted by 지누구루
2014. 10. 22. 14:13 예전에 했던 게임/스파4

 9월 초중반? 에 했던 봉봉마루와의 게임..

생각보다 잘말아 먹어서 남겨봅니다.

posted by 지누구루
2014. 10. 7. 09:43 자유글

지금까지 총 3개의 게임 프로젝트에 서버 개발자로 참가 했다.

 

경험했던 일중에, 이런건 정말 어쩔수가 없나? 싶었던 내용인데,

이번 프로젝트에서 적용했고, 어느정도 꽤 좋은 효과를 얻고 있는 내용에 대한 공유이다.

 

내용은 이러하다.

서버가 크래시 나는 일은 막을수가 없다. 사람은 실수를 하기 마련이기 때문이다.

하지만 서버 크래시가 날 경우 DB에 데이터를 동기화 할수 없기때문에,

이전 DB 데이터 동기화 시간부터 서버가 떨어지는 시간까지의 데이터는 보존해 줄수가 없다.

 

비슷한 일로 디아블로 3에서의 아이템 복사 사건도 있었는데, 서버를 죽이는 방법 알고 있다면.

아이템 드랍이나 거래로 아이템을 넘겨주고, 받은 사람은 다른 서버로 이동해서 아이템을 저장.

넘겨준쪽이 서버를 고의로 죽임으로써 아이템 복사가 성립된다.

(물론 아이템 uuid 사용 같은 방법으로 복사를 막는 방법이 있을수 있긴하지만 그건 일단 논외로..)

 

서버가 떨어지기 직전에 획득한 아이템이 사라져 있다거나,

서버 크래시 직전에 레벨업을 했는데, 레벨이 돌아가 있거나 하는 일시적인 백섭 현상이 생기게 된다.

(내가 있었던 게임들은 대부분 최대 5분정도의 백섭이 발생할 수 있었다)

 

그 이유는 캐릭터의 정보가 변경되었다고 해서, 그걸 모두 동적으로 DB 동기화 하지 않기 때문인데,

그건 동적으로 할 경우 DB 부하가 몰릴수 있고, 너무 자주 update가 발생하니까, 모아서 한번에 처리하기 위함이다

예를 들면, 몬스터 10마리를 잡아서 경험치를 10씩 획득, 총 100의 경험치를 획득했다면,

10씩 올라갈때마다 DB에 업데이트를 보내면 10번 업데이트를 해야 하지만,

모아서 보내면 1번에 100을 업데이트하는 방식으로 쿼리를 줄일수 있다는 이야기 이다.

(너무 당연한 거라서 길게 설명하지 않음)

 

여튼, 이 글에서 말하고자 하는건.

저 "일시적인 백섭" 현상을 줄일수 없을까? 하는 논의 에서 시작된.. 일종의 꽁수이다.

(이걸 생각해보게 된 경위는.. 서버가 떨어진것만도 신경이 쓰이는데, CS 에서 들어오는 유저 문의중에 아이템이 없어졌다는 문의 대응을 위해서는 찾아봐야 할게 너무 많아서.. ㅠㅠ 사실 여부 판단에 상당한 시간이 소모된다는 점 때문..)

 

내용 자체는 초 심플하다.

내가 있었던 프로젝트는 모두 리눅스를 사용했는데,

 

서버가 크래시나는 시그널(Ex - SIGFPE나 SIGSEGV 같은)을 받으면

시그널 핸들러에서 현재 해당 서버에 접속중인 모든 유저에 대해서

데이터 동기화를 다시 시도하도록 한다.

 

이게 끝인데..

 

이걸로 인해서 DB Thread가 사망하신게 아니라면

거의 모든 유저에 대한 데이터 정리가 완료 되고 종료되었다.

 

굉장히 간단하고.. 어쩌면 다른 프로젝트들에서는 당연하게 처리되고 있는지도 모르겠지만,

여튼 저런 단순처리만으로도 상당한 효과를 보고 있다...

 

 

부가적으로, 현재 프로젝트에서는 실제 게임을 플레이하는 서버가 크래시로 인해 떨어질 경우,

게임에서 완전히 접속이 끊어지는게 아니라, 캐릭터 선택화면으로 돌아가게 만들었는데,

(캐릭터 선택까지는 다른 서버가 하기 때문에 가능)

그로 인해 한두 서버의 크래시가 동접이 꺾이게 하지 않고,

서버 크래시로 인해 일시적인 백섭도 발생하지 않기 때문에..

운영적인 측면에서.. 서버 다운 피해로, 백섭에 대한 CS가 폭주하거나 하는 상황이 발생하지 않게 된것도

매우 잘한 조치라고 생각한다.

 

내가 직접 작업한건 아니지만

아이디어가 좋았다고 개인적으로 생각하는 부분이라서, 일단 기록해둠.

 

posted by 지누구루