
ãã«ããã¬ã€ã€ãŒã²ãŒã ã®åé¡
ãã«ããã¬ã€ã€ãŒã²ãŒã ã®æãé£ããã¿ã¹ã¯ã®1ã€ã¯ããã¹ãŠã®ãã¬ã€ã€ãŒã®ç¶æ ããµãŒããŒã®ç¶æ ãšåæãããããšã§ãã ãã®ãããã¯ã«é¢ããè¯ãèšäºãã€ã³ã¿ãŒãããäžã«ãããŸãã ãã ããã²ãŒã ããã°ã©ãã³ã°ã®åå¿è ãæ··ä¹±ãããå¯èœæ§ã®ãã詳现ãæ¬ ããŠããŸãã ãã®èšäºã§ãã¹ãŠã説æã§ããããšãé¡ã£ãŠããŸãã
ãã®ãããªåé¡ã解決ããããã«äžè¬çã«äœ¿çšãããããã€ãã®ææ³ã®æŠèŠã説æããŸãã åé¡ã«ç§»ãåã«ããã«ããã¬ã€ã€ãŒã²ãŒã ã®ä»çµã¿ãç°¡åã«ç¢ºèªããŸãããã
éåžžãã²ãŒã ããã°ã©ã ã¯ä»¥äžãã·ãã¥ã¬ãŒãããå¿ èŠããããŸãã
ãã¬ã€ã€ãŒãå ¥åããæéãšããŒã¿ã«åºã¥ãç°å¢ã®å€å ã
ã²ãŒã ã¯ç¶æ ãä¿åããããã°ã©ã ã§ãããããæéïŒå®éãŸãã¯è«çïŒã«äŸåããŸãã ããšãã°ãPACMANã¯ãŽãŒã¹ãã絶ãã移åããç°å¢ãã·ãã¥ã¬ãŒãããŸãã
ãã«ããã¬ãŒã€ãŒã²ãŒã ãäŸå€ã§ã¯ãããŸãããããã¬ãŒã€ãŒã®çžäºäœçšã«ããããã®è€éãã¯ã¯ããã«é«ããªããŸãã
ããšãã°ãå€å žçãªã²ãŒã ãSnakeããèããŠã¿ãŸãããã
ã¯ã©ã€ã¢ã³ããµãŒããŒã¢ãŒããã¯ãã£ã䜿çšãããšããŸãã ã²ãŒã ããžãã¯ã¯æ¬¡ã®ããã«æ©èœããŸãã
- ãã¬ã€ã€ãŒãå ¥åããããŒã¿ãèªã¿åããèã®ç§»åæ¹åãå€æŽããŸãã æå³ã¯[âãâãâãâ]ã®ããããã§ãã
- å©çšå¯èœãªå Žåãå ¥åããŒã¿ã®é©çšã ããã«ãããèã®åãã®æ¹åãå€ãããŸãã
- 1åäœã®ã¹ããŒã¹ã§ããã移åããŸãã
- åãããšæµ/å£/äœãšã®è¡çªã®æç¡ã確èªããã²ãŒã ããããããåé€ããŸãã
- ç¹°ãè¿ããµã€ã¯ã«ã
ãã®ããžãã¯ã¯ãäžå®ã®ééã§ãµãŒããŒã§å®è¡ããå¿ èŠããããŸãã 以äžã«ç€ºãããã«ãåã«ãŒãã¯ãã¬ãŒã ãŸãã¯ãã£ãã¯ãšåŒã°ããŸãã
class Server { def main(): Unit = { while (true) { /** * 1. , : [â, â, â, â]. * 2. , . * 3. . * 4. // , . * 5. . */ Thread.sleep(100) } } }
æãåçŽãªã¯ã©ã€ã¢ã³ãã¯ããµãŒããŒã®æŽæ°ãèªã¿åãããã¬ãŒã€ãŒã®ãã¹ãŠã®åä¿¡ãã¬ãŒã ãã¬ã³ããªã³ã°ããŸãã
class Client { def onServerUpdate(state: GameState) = { renderGameState(state) } }
ã¹ãããã¹ããŒã¿ã¹ã®æŽæ°ãä¿®æ£
ã³ã³ã»ãã
ãã¹ãŠã®ã¯ã©ã€ã¢ã³ãã確å®ã«åæãããããã«ããããã®æãç°¡åãªæ¹æ³ã¯ãã¯ã©ã€ã¢ã³ããäžå®ã®ééã§ãµãŒããŒã«æŽæ°ãéä¿¡ããããšã§ãã ããšãã°ã30ããªç§ã®ééããšããŸãã æŽæ°ã«ã¯ããŠãŒã¶ãŒãå ¥åããããŒã¿ãå«ãŸããŸãããã®ããŒã¿ã«ã¯ããŠãŒã¶ãŒãå ¥åããããŒã¿ãªãã®å€ãå«ãŸããå ŽåããããŸã ã
ãã¹ãŠã®ãŠãŒã¶ãŒããå ¥åããŒã¿ãåä¿¡ãããšããµãŒããŒã¯ãã®ããŒã¿ãèæ ®ããŠæ¬¡ã®ã¡ãžã£ãŒã«é²ãããšãã§ããŸãã

äžã®å³ã¯ã1ã€ã®ã¯ã©ã€ã¢ã³ããšãµãŒããŒã®çžäºäœçšã瀺ããŠããŸãã ç§ãšåãããã«åé¡ãããªãã«ãšã£ãŠæçœã§ããããšãé¡ã£ãŠããŸãïŒã¯ã©ã€ã¢ã³ãã¯T0ããT1ãŸã§ã¢ã€ãã«ç¶æ ã«ãªãããµãŒããŒããã®æŽæ°ãåŸ ã€ããšãã§ããŸãã ãããã¯ãŒã¯ã®å質ã«å¿ããŠãé 延ã¯50ã500ããªç§ã®éã§å€åããçŸä»£ã®ãã¬ãŒã€ãŒã¯100ããªç§ãè¶ ããé 延ã«æ°ã¥ããŸãã ãã®ãããäžéšã®ã²ãŒã ã§ã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ã200ããªç§éå¶åããããšã倧ããªåé¡ã«ãªããŸãã
ããã¯ãåºå®ééã¢ãããŒãã®å¯äžã®è€éãã§ã¯ãããŸããã

äžã®å³ã¯ããå°ãè€éã§ãè€æ°ã®ã¯ã©ã€ã¢ã³ãã®ãµãŒããŒãšã®å¯Ÿè©±ã瀺ããŠããŸãã ã¯ã©ã€ã¢ã³ãBã®ãããã¯ãŒã¯æ¥ç¶ã¯é ããããAãšBã¯T0ã«å ¥åããµãŒããŒã«éä¿¡ããŸãããBããã®æŽæ°ã¯T1ã§ã¯ãªãT2ã§ãµãŒããŒã«å°éããŸãã ãããã£ãŠããµãŒããŒã¯ããã¹ãŠã®æŽæ°ãåä¿¡ãããšããã€ãŸãT2ã§ã®ã¿èšç®ãç¶è¡ããŸãã
ããã¯ã©ãããæå³ã§ããïŒ
ã²ãŒã ã®é 延ã¯ãé ããŠãããã¬ã€ã€ãŒèªäœã®é 延ã«çãããªããŸããã
ãã®ãã¡ã®1人ã®æ¥ç¶ãé ãããããã¹ãŠã®ãã¬ãŒã€ãŒã眰ããããšãããããŸããã ãããã£ãŠãé ããæ©ããããã¹ãŠã®ãã¬ã€ã€ãŒãã²ãŒã ãé¢ããŸã...
ã¯ã©ã€ã¢ã³ãBãåæããå¯èœæ§ããããšããäºå®ã¯èšããŸã§ããªããæ¥ç¶ã¿ã€ã ã¢ãŠããæéåãã«ãªããŸã§ãµãŒããŒã¢ã¯ã·ã§ã³ããããã¯ããŸãã
è°è«
äžèšã®2ã€ã®åé¡ã«å ããŠãããã«ããã€ããããŸãã
- ã¯ã©ã€ã¢ã³ãã¯ããµãŒããŒããã¹ããŒã¿ã¹ã®æŽæ°ãåä¿¡ãããŸã§å¿çããŸããïŒããã¯ãŠãŒã¶ãŒã®èŠ³ç¹ããããã°ã²ã©ãã§ãïŒã
- ã²ãŒã ã®å¿çæ§ã¯ãæããé ããŠããããã¬ãŒã€ãŒã«äŸåããŸãã DSLã§åéãšéãã§ããŸããïŒ é 匵ã£ãŠ
- æ¥ç¶ã¯éåžžã«ããã£ãããã«ãªããŸããã¯ã©ã€ã¢ã³ãã¯ããµãŒããŒãç¶ç¶ããããã«å¿ èŠãªãã¹ãŠã®æ å ±ãæã£ãŠããããšã確èªã§ããããã«ãç¡çšãªããŒã¿ãå®æçã«éä¿¡ããå¿ èŠããããŸãã
ãŸããç¹å®ã®ã¿ã€ãã®ã²ãŒã ã¯ãããã®åé¡ã®åœ±é¿ãåããŸãããããšãã°ãã»ãšãã©ã®ã¿ãŒã³ããŒã¹ã®ã²ãŒã ã¯ãã¯ã©ã€ã¢ã³ããåŸ æ©ããå¿ èŠãããããããã®ã¢ãã«ã®ããªãšãŒã·ã§ã³ã䜿çšããŸãã
é ãã²ãŒã ã®å Žåãããããªé 延ã蚱容ãããŸãã ãã®è¯ãäŸãFarm Villeã§ãã
ãã1ã€ã®è¯ãäŸã¯ãã§ã¹ã§ã ã2人ã®ãã¬ã€ã€ãŒã亀代ã§ãããããã®åããçŽ10ç§ç¶ããŸãã
- ãŠãŒã¶ãŒã¯ããäºãã10ç§éåŸ ã€å¿ èŠããããŸãã ãããŠåœŒãã¯åŸ ã£ãŠããŸãã
- 2人ã®ãã¬ãŒã€ãŒãé çªã«äº€ä»£ããã®ã§ãäžæ¹ãé ãããŠãä»æ¹ã«ã¯åœ±é¿ããŸããã
- åã¿ãŒã³ã«ã¯å¹³å5ç§ããããŸãïŒ5ç§ã«1åã®ãªã¯ãšã¹ãã§ååã§ãïŒã
ããããé«éã²ãŒã ã¯ã©ãã§ããïŒ ããšãã°ããã¹ãŠã®FPSã§ã¯ããã®ãããªåé¡ããããããåºå®ééã®ãœãªã¥ãŒã·ã§ã³ã¯é©åã§ã¯ãããŸããã ãã®èšäºã®æ®ãã®éšåã§ã¯ããããã®åé¡ã解決ããæ¹æ³ãåŠã³ãŸãã
顧客ã®äºæž¬
æåã«ãã¬ãŒã€ãŒã®å¿çã®åé¡ã解決ããŸãããã ãã¬ãŒã€ãŒããã¿ã³ãæŒããŠãã500ããªç§åŸã«ã²ãŒã ãåå¿ãããããã²ãŒã ããã»ã¹ãã¯ã©ãã·ã¥ããŸãã
ãã®åé¡ã解決ããã«ã¯ïŒ
ã³ã³ã»ãã
äžéšã®èªè ã¯ãã§ã«çããç¥ã£ãŠããŸãïŒãµãŒããŒãæŽæ°ãããã®ãåŸ ã€ä»£ããã«ãã¯ã©ã€ã¢ã³ãã¯å®éã«ã²ãŒã ããšãã¥ã¬ãŒãããã²ãŒã ããžãã¯ãããŒã«ã«ã«ïŒã€ãŸããã¯ã©ã€ã¢ã³ãã®ãã·ã³ã§ïŒå®è¡ããŸãã
Tn
ã²ãŒã ã®ç¶æ ãèšç®ããã«ã¯ã
Tn-1
ç¶æ ãš
Tn-1
ã«ãŠãŒã¶ãŒãå ¥åããããŒã¿ãç¥ãå¿ èŠããããšããŸãã

èãæ¹ã¯ç°¡åã§ãïŒåºå®æŽæ°ã¬ãŒããäœæããŸãããããã®äŸã§ã¯ãããã¯1åäœã®æéã«çãããªããŸãã
ã¯ã©ã€ã¢ã³ãã¯T0ã®ãµãŒããŒã«å ¥åãéä¿¡ããŠT1ã®ã²ãŒã ã®ç¶æ ããšãã¥ã¬ãŒããããããã¯ã©ã€ã¢ã³ãã¯ãµãŒããŒããã®ã¹ããŒã¿ã¹æŽæ°ãT3ã§ã®ã¿åä¿¡ãããã®ãåŸ ããã«ã²ãŒã ãã¬ã³ããªã³ã°ã§ããŸãã
ãã®ã¢ãããŒãã¯ã次ã®æ¡ä»¶äžã§ã®ã¿æ©èœããŸãã
- ã²ãŒã ã®ç¶æ ã®æŽæ°ã¯ç¢ºå®çã§ãã äºæ ããªããééçã§ãããã¯ã©ã€ã¢ã³ããšãµãŒããŒã¯åãå ¥åããåãã²ãŒã ç¶æ ããã¬ã€ã§ããŸãã
- ã¯ã©ã€ã¢ã³ãã«ã¯ãã²ãŒã ããžãã¯ã®å®è¡ã«å¿ èŠãªãã¹ãŠã®æ å ±ããããŸãã
- 泚ïŒ1 ããã¯åžžã«åœãŠã¯ãŸãããã§ã¯ãããŸããããå¯èœãªéã䌌ããã®ã«ããç°ãªããã©ãããã©ãŒã ã§ã®æµ®åå°æ°ç¹èšç®ãªã©ã®å°ããªéããç¡èŠããæ¬äŒŒã©ã³ãã ã¢ã«ãŽãªãºã ã«åãã·ãŒãã䜿çšããããšãã§ããŸãã
ãã€ã³ã2ãåžžã«æ£ãããšã¯éããŸããã ç§ã説æããŸãïŒ

äžã®å³ã§ã¯ãã¯ã©ã€ã¢ã³ãAã¯T0ã§åä¿¡ããæ å ±ã䜿çšããŠT1ã®ã²ãŒã ã®ç¶æ ããšãã¥ã¬ãŒãããããšããŠããŸããã T0ã®ã¯ã©ã€ã¢ã³ãBã¯ã¯ã©ã€ã¢ã³ãAãç¥ããªãå ¥åããŒã¿ãæ¢ã«éä¿¡ããŠããŸãã
ããã¯ã T1ã«é¢ãã顧客Aã®äºæž¬ã誀ã£ãŠããããšãæå³ããŸãã 幞ããªããšã«ãã¯ã©ã€ã¢ã³ãAã¯ãŸã ãµãŒããŒããT1ã¹ããŒã¿ã¹ãåä¿¡ããŠââããããã T3ã®ãšã©ãŒãä¿®æ£ããããšãã§ããŸãã
ã¯ã©ã€ã¢ã³ãåŽã¯ã以åã®ãšãã¥ã¬ãŒã·ã§ã³ãæ£ãããã©ãããããã³ç«¶åã解決ããæ¹æ³ãèŠã€ããå¿ èŠããããŸãã
çŽäºè§£æ±ºã¯éåžžã å解ãšåŒã°ããŸãã
調æŽã®å®è£ ã¯ãç¹å®ã®äœ¿çšæ¡ä»¶ã«äŸåããŸãã åçŽã«äºæž¬ãæåŠãããµãŒããŒããåãåã£ãæ£ç¢ºãªç¶æ ã«çœ®ãæããåçŽãªäŸã瀺ããŸãã
- ã¯ã©ã€ã¢ã³ãã¯ãäºæž¬çšãšå
¥åããŒã¿çšã®2ã€ã®ãããã¡ãä¿åããå¿
èŠããããŸãã åŸã§äºæž¬ã®èšç®ã«äœ¿çšã§ããŸãã Tnã®ç¶æ
ã¯ãTn-1ã®ç¶æ
ãšãæåã«ç©ºã«ãªãTn-1ã®å
¥åããŒã¿ã«åºã¥ããŠèšç®ãããããšãå¿ããªãã§ãã ããã
- ãã¬ãŒã€ãŒãç¢å°ããŒãæŒããšãå
¥åããŒã¿ãInputBufferã«ä¿åãããã¯ã©ã€ã¢ã³ããäºæž¬ãå®è¡ããŸããäºæž¬ã¯èŠèŠåã«äœ¿çšãããŸãã äºæž¬ã¯PredictionBufferã«ä¿åãããŸãã
- ãµãŒããŒããState0ç¶æ
ãåä¿¡ããæç¹ã§ã¯ãã¯ã©ã€ã¢ã³ãã®äºæž¬Prediction0ãšäžèŽããªãããã Prediction0ãState0ã«çœ®ãæãã Input0ãšState0ãèæ
®ããŠPrediction1ãåèšç®ã§ããŸãã
- ããŽã·ãšãŒã·ã§ã³ã®åŸã State0ãšInput0ããããã¡ããå®å
šã«åé€ã§ããŸãã ããããŠã¯ãããŠããã¹ãŠãæ£ããããšã確èªã§ããŸãã
泚ïŒèª¿æŽã«ã¯æ¬ ç¹ããããŸãã ãµãŒããŒã®ç¶æ ãšã¯ã©ã€ã¢ã³ãã®äºæž¬ã倧ããç°ãªãå Žåãã¬ã³ããªã³ã°äžã«èŠèŠçãªãšã©ãŒãçºçããå¯èœæ§ããããŸãã ããšãã°ãæµãT0ã§åã«ç§»åããŠãããšäºæž¬ãããã T3ã§ã¯æµãåã«ç§»åããããšãç解ããå ŽåããµãŒããŒããã®ç¶æ ã䜿çšããã ãã§ããŒã¿ã調æŽããŸãã æµã¯ãæ£ããäœçœ®ã衚瀺ããããã«çªç¶æ¹åãå€ããŸãã
ãã®åé¡ã«å¯ŸåŠããæ¹æ³ã¯ãããŸããããã®èšäºã§ã¯èª¬æããŸããã
è°è«
ã¯ã©ã€ã¢ã³ãåŽã®äºæž¬ææ³ã«ã¯å€§ããªå©ç¹ããããŸããã¯ã©ã€ã¢ã³ãã¯ç¬èªã®ãªãã¬ãã·ã¥ã¬ãŒãïŒãµãŒããŒã®ãªãã¬ãã·ã¥ã¬ãŒããšã¯ç¡é¢ä¿ïŒã§åäœããããããµãŒããŒããã¹ããŒããŠã³ãããŠããã¯ã©ã€ã¢ã³ããµã€ãã®ãã¬ãŒã ã¬ãŒãã«ã¯åœ±é¿ããŸããã
ãã ããããã¯å¿ ç¶çã«ç¹å®ã®è€éãã«é¢é£ä»ããããŸãã
- ã¯ã©ã€ã¢ã³ãåŽã§ããå€ãã®ç¶æ ãšããžãã¯ïŒäºæž¬ãããã¡ãç¶æ ãããã¡ãäºæž¬ããžãã¯ïŒãåŠçããå¿ èŠããããŸãã
- äºæž¬ãšãµãŒããŒäžã®å®éã®ç¶æ ãšã®ç«¶åã解決ããæ¹æ³ã決å®ããå¿ èŠããããŸãã
ãããŠããŸã å€ãåé¡ããããŸãïŒ
- äžæ£ç¢ºãªäºæž¬ã«ããèŠèŠåãšã©ãŒã
- é »ç¹ãªç¡é§ãªããŒã¿äº€æã
ãããã«
ãã®ããŒãã§ã¯ããã«ããã¬ã€ã€ãŒã²ãŒã ã§ãããã¯ãŒã¯æ¥ç¶ãå®è£ ããããã®2ã€ã®æ¹æ³ãæ€èšããŸããã
- ã¹ãããã¹ããŒã¿ã¹ã®æŽæ°ãä¿®æ£
- ã¯ã©ã€ã¢ã³ãåŽã®äºæž¬
ããããã«ç¬èªã®åŠ¥åç¹ããããŸããããµãŒããŒåŽã§äœãèµ·ãã£ãŠãããã«ã€ããŠã¯ãŸã 詳ããæ€èšããŠããŸããã
èå³æ·±ãé¢é£èšäº
- GabrielããŒã¹ã®éããã«ããã¬ã€ã€ãŒã·ãªãŒãºã®èšäºïŒ
http://www.gabrielgambetta.com/fpm1.html Habréã®èšäºã®ç¿»èš³ïŒ ããŒã1ããã³2 ã ããŒã3 ã ããŒã4 ã - ãªã³ã©ã€ã³ã²ãŒã gafferongamesã®åºæ¬ïŒ
http://gafferongames.com/networking-for-game-programmers/what-every-programmer-needs-to-know-about-game-networking/ - ãã«ãäŒç€Ÿã®èšäºïŒ
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
ãµãŒããŒã®åœ¹å²ã¯äœã§ããïŒ
ãµãŒããŒã¢ã¯ã·ã§ã³ãå®çŸ©ããããšããå§ããŸãããã å žåçãªãµãŒããŒã¿ã¹ã¯ïŒ
aïŒãã¬ãŒã€ãŒã®æ¥ç¶ãã€ã³ã
ãã«ããã¬ã€ã€ãŒã²ãŒã ã§ã¯ããã¬ã€ã€ãŒã¯äºãã«éä¿¡ããããã«å ±éã®ãšã³ããã€ã³ããå¿ èŠã§ãã ããã¯ããµãŒããŒããã°ã©ã ã®åœ¹å²ã®1ã€ã§ãã P2Péä¿¡ã¢ãã«ã§ãããããã¯ãŒã¯æ å ±ã亀æããŠP2Pæ¥ç¶ã確ç«ããããã®æ¥ç¶ãã€ã³ãããããŸãã
bïŒæ å ±åŠç
å€ãã®å ŽåããµãŒããŒã¯ã²ãŒã ã·ãã¥ã¬ãŒã·ã§ã³ã³ãŒããå®è¡ãããã¬ã€ã€ãŒãå ¥åãããã¹ãŠã®ããŒã¿ãåŠçããã²ãŒã ã®ç¶æ ãæŽæ°ããŸãã ããã¯åžžã«èµ·ãããšã¯éããªãããšãèæ ®ãã䟡å€ããããŸããäžéšã®ææ°ã®ã²ãŒã ã§ã¯ãã»ãšãã©ã®åŠçãã¯ã©ã€ã¢ã³ãåŽã«ã·ããããŸãã ãã®èšäºã§ã¯ãã²ãŒã ã®åŠçïŒã€ãŸããã²ãŒã ãã£ãã¯ã®äœæãªã©ïŒãè¡ãã®ã¯ãµãŒããŒã§ãããšæ³å®ããŸãã
cïŒã²ãŒã ã®çã®ç¶æ ã®åäžã®ãœãŒã¹
å€ãã®ãã«ããã¬ã€ã€ãŒã²ãŒã ã§ã¯ããµãŒããŒããã°ã©ã ã¯ã²ãŒã ã®ç¶æ ãå¶åŸ¡ããåãæã£ãŠããŸãã ããã®äž»ãªçç±ã¯ãäžæ£è¡çºã«å¯Ÿããä¿è·ã§ãã ããã«ãã²ãŒã ã®æ£ããç¶æ ãååŸããããã®ãã€ã³ãã1ã€ãããªãå Žåãããã²ãŒããã¯ããã«ç°¡åã«ãªããŸãã
åçŽãªãµãŒããŒå®è£
æãç°¡åãªæ¹æ³ã§ãµãŒããŒã®å®è£ ãéå§ããŸããããããããæ¹åããŸãã
ã²ãŒã ãµãŒããŒã®ã³ã¢ã¯ããŠãŒã¶ãŒå ¥åã«åºã¥ããŠGameStateãæŽæ°ããã«ãŒãã§ãã ãã®ãµã€ã¯ã«ã¯éåžžTICKïŒæž¬å®ïŒãšåŒã°ãã次ã®ããã«æå®ãããŸãã
(STATE n , INPUT n ) => STATE n+1
ç°¡ç¥åããããµãŒããŒã³ãŒãã¹ããããã¯æ¬¡ã®ããã«ãªããŸãã
def onReceivedInput(i: UserInput) = { storeInputToBuffer(i) } while(!gameEnded) { val allUserInputs = readInputFromBuffer() currentState = step(currentState, allUserInputs) // .. (STATEn , INPUTn) => STATEn+1 sendStateToAllPlayers(currentState) }
è°è«
ã³ãŒãã¹ãããããçŽæçã§ãããããããã®ã«ãªã£ãŠããããšãé¡ã£ãŠããŸãããµãŒããŒã¯åã«ãããã¡ããã®å ¥åãåãå ¥ãã次ã®
TICK
é¢æ°ã§ãããé©çšããŠæ°ããGameStateç¶æ ãååŸããŸãã ãã®ã¢ãããŒãã¯ãã§ããã ãæ©ãããŒã¿ãåŠçããããšããããã 貪欲ãªã²ãŒã ã«ãŒããšåŒã³ãŸãããã ããã¯ã倪éœå ã8åã§å°çã«å°éããäžå®å šãªå®å®ã«ã€ããŠèããªããã°ãæ£åžžã§ãã
ããã§ããé 延ãéèŠã«ãªããŸãã
ãµãŒããŒãå
TICK
ã®ãããã¡ãŒããã®å ¥åãåŠçãããšããäºå®ã¯ãGameStateããããã¯ãŒã¯é 延ã«äŸåããŠããããšãæå³ããŸãã 次ã®å³ã¯ããããåé¡ã«ãªã£ãŠããçç±ã瀺ããŠããŸãã

ãã®å³ã¯ãå ¥åããµãŒããŒã«éä¿¡ãã2ã€ã®ã¯ã©ã€ã¢ã³ãã瀺ããŠããŸãã 2ã€ã®èå³æ·±ãäºå®ããããŸãã
- ãªã¯ãšã¹ãã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒéã§ç°ãªãæéãããããŸããã¯ã©ã€ã¢ã³ãAãããµãŒããŒãžã¯1åäœãã¯ã©ã€ã¢ã³ãBãããµãŒããŒãžã¯1.5åäœã§ãã
- 1ã€ã®ã¯ã©ã€ã¢ã³ãã«å¯ŸããŠãªã¯ãšã¹ãã«ãããæéã¯ç°ãªããŸããæåã®ãªã¯ãšã¹ãã«ã¯1åäœã®æéããããã2çªç®ã®ãªã¯ãšã¹ãã«ã¯2åäœã®æéãããããŸããã
ã€ãŸããåãæ¥ç¶ã§ãã£ãŠããé 延ã¯äžè²«ããŠããŸããã
貪欲ãªã²ãŒã ãµã€ã¯ã«ãšçµã¿åããããæç¶çãªé 延ã¯ãããã€ãã®åé¡ã«ã€ãªãããŸãã 以äžã§ããããæ€èšããŸãã
ã¯ã©ã€ã¢ã³ãåŽã®äºæž¬ãæ©èœããªã | ãµãŒããŒãïŒé 延ã®ããã«ïŒå ¥åããŒã¿ãåä¿¡ããæéãäºæž¬ã§ããªãå Žåãé«ç²ŸåºŠã®äºæž¬ãè¡ãããšã¯ã§ããŸããã |
äœã¬ã€ãã³ã·ãŒã®ãã¬ãŒã€ãŒã掻çšãã | å ¥åããŒã¿ãããéããµãŒããŒã«å°éãããšãå ¥åããŒã¿ã¯ããéãåŠçããããããé«éãããã¯ãŒã¯ãæã€ãã¬ãŒã€ãŒã«ãšã£ãŠäžå ¬å¹³ãªå©ç¹ãçãŸããŸãã ããšãã°ã2人ã®ãã¬ã€ã€ãŒãåæã«ãäºãã«æã€å Žåã圌ãã¯åæã«ãäºãã殺ãå¿ èŠããããŸããããã¬ã€ã€ãŒBã¯é 延ãçãããããã¬ã€ã€ãŒAã®ããŒã ãåŠçãããåã«ãã¬ã€ã€ãŒAã殺ããŸãã |
- ã¯ã©ã€ã¢ã³ãåŽã®äºæž¬ã¯äžèŠ
- ãã¹ãŠã®ãã¬ã€ã€ãŒã¯ãæãé ããã¬ã€ã€ãŒãšåãé 延ãæã€ãããåè¿°ã®å©ç¹ã¯ãªããªããŸãã
ãã ããå¿çæ§ãäœãããããã®ã¢ãããŒãã¯é«éã¢ã¯ãã£ãã²ãŒã ã§ã¯æ©èœããŸããã
次ã®ã»ã¯ã·ã§ã³ã§ã¯ããµãŒããŒåŽãé«éã²ãŒã ã§åäœãããæ¹æ³ã«ã€ããŠèª¬æããŸãã
ãµãŒããŒèª¿æŽ
ã¯ã©ã€ã¢ã³ãåŽã§ã®äžæ£ç¢ºãªäºæž¬ã®åé¡ã解決ããã«ã¯ãã¯ã©ã€ã¢ã³ãã®èŠ³ç¹ããã¯ã©ã€ã¢ã³ããšãµãŒããŒã®çžäºäœçšãããäºæž¬å¯èœã«ããå¿ èŠããããŸãã ãã¬ãŒã€ãŒãã¯ã©ã€ã¢ã³ãåŽã§ããŒãæŒããšãã¯ã©ã€ã¢ã³ãããã°ã©ã ã¯ãã®å ¥åããµãŒããŒåŽã§ãã€åŠçãããããç¥ãå¿ èŠããããŸãã
ããããã1ã€ã®å¯èœãªæ¹æ³ã¯ãå ¥åããŒã¿ãé©çšãããå¿ èŠããããšãã¯ã©ã€ã¢ã³ãã«ææ¡ãããããšã§ã ã ãããã£ãŠãã¯ã©ã€ã¢ã³ãåŽã¯ãã¢ããªã±ãŒã·ã§ã³ã®æéãæ£ç¢ºã«äºæž¬ã§ããŸãã ããªãã¡ãŒããšããçšèªã䜿çšãããã®ã¯ãããã䜿ãæãããã«ããããããããã¬ã€ã€ãŒãåªæãå±ããããšããå Žåãªã©ããµãŒããŒããã®ç³ãåºãééã£ãŠããå Žåã«æåŠã§ããããã§ãã
å ¥åããŒã¿ã¯ããã¬ãŒã€ãŒãããŒã¿ãå ¥åããã»ãŒçŽåŸã«é©çšããå¿ èŠããããŸãïŒäŸïŒ T input + X ïŒãããã§ãXã¯é 延ã§ãã å¿çæ§ã¯éåžž100ããªç§æªæºã®é 延ãå¿ èŠãšãããããæ£ç¢ºãªå€ã¯ã²ãŒã ã«ãã£ãŠç°ãªããŸãã Xã¯ãŒãã§ãããããšã«æ³šæããŠãã ããã ãã®å ŽåãããŒã¿ã¯ãŠãŒã¶ãŒå ¥åã®çŽåŸã«é©çšãããŸãã
X = 30 msãšããŸããããã¯ã1ç§ããã30ãã¬ãŒã ã§1ãã¬ãŒã ã«ã»ãŒçãããªããŸãã ããŒã¿ããµãŒããŒã«è»¢éããã®ã«150ããªç§ããããŸããå ¥åããŒã¿ããµãŒããŒã«å°éãããšãå ¥åãã¬ãŒã ãæ¢ã«ã¹ããããããå¯èœæ§ãé«ããªããŸãã
å³ãèŠãŠãã ããïŒãŠãŒã¶ãŒAãTã§ããŒãæŒããŸããã ãã®ããŒã¿ã¯T + 30ããªç§ã§åŠçããå¿
èŠããããŸãããé
延ã«ããå
¥åããŒã¿ã¯T + 150ããªç§ã§ãµãŒããŒã«ãã£ãŠåä¿¡ãããŸãããããã¯æ¢ã«T + 30ããªç§ã®å€ã«ãããŸãã ãã®ã»ã¯ã·ã§ã³ã§ã¯ããã®åé¡ã«å¯ŸåŠããŸãã
ãµãŒããŒã¯ãéå»ã«çºçããã¯ãã®å
¥åãã©ã®ããã«é©çšããŸããïŒ
ã³ã³ã»ãã
ã¯ã©ã€ã¢ã³ãåŽã®äºæž¬ã«ã¯ã察æŠçžæã«é¢ããæ å ±ãäžè¶³ããŠãããããäžæ£ç¢ºãªäºæž¬ãšåãåé¡ããã£ãããšãããããèŠããŠããã§ãããã 誀ã£ãäºæž¬ã¯ã調æŽã䜿çšããŠãµãŒããŒããã®ã¹ããŒã¿ã¹ã®æŽæ°ã«ãã£ãŠåŸã§ä¿®æ£ãããŸããã ããã§ãåãææ³ã䜿çšã§ããŸãã å¯äžã®éãã¯ãã¯ã©ã€ã¢ã³ããå ¥åããããŒã¿ã«åºã¥ããŠãµãŒããŒäžã®GameStateãä¿®æ£ããããšã§ãã
ãã¹ãŠã®ãŠãŒã¶ãŒå ¥åã«ã¯ã¿ã€ã ã¹ã¿ã³ããå¿ èŠã§ãã ãããã®ã©ãã«ã¯ãåŠçãå¿ èŠãªãšãã«ãµãŒããŒã«éç¥ããããã«äœ¿çšãããŸãã

泚ïŒæåã®ç Žç·ã§ã¯ ã æéXã¯ã¯ã©ã€ã¢ã³ãåŽã§ããã æéYã¯ãµãŒããŒåŽã§ãã ããã¯ããã«ããã¬ã€ã€ãŒã²ãŒã ïŒããã³ä»ã®å€ãã®åæ£ã·ã¹ãã ïŒã®èå³æ·±ãæ©èœã§ããã¯ã©ã€ã¢ã³ããšãµãŒããŒãç¬ç«ããŠåäœãããããã¯ã©ã€ã¢ã³ããšãµãŒããŒã®æéã¯éåžžç°ãªããŸãã ã¢ã«ãŽãªãºã ã«ããããã®éãã«å¯ŸåŠã§ããŸãã
äžã®å³ã¯ã1ã€ã®ã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®çžäºäœçšã瀺ããŠããŸãã
- ã¯ã©ã€ã¢ã³ãã¯ã¿ã€ã ã¹ã¿ã³ãä»ãã®å ¥åãéä¿¡ãããã®ã¯ã©ã€ã¢ã³ãAã®ããŒã¿ãæéXã«çºçããããšããµãŒããŒã«äŒããŸãã
- ãµãŒããŒã¯æéYã§ãªã¯ãšã¹ããåä¿¡ããŸããæéXãæéYãããæ©ããšä»®å®ããŸããã¢ã«ãŽãªãºã ãéçºãããšããæéYãæéXããã倧ãããå°ããããšãåãå ¥ããªããã°ãªããŸããã
- èµ€ããã£ãŒã«ãã¯ã調æŽãå®äºããç¬éã§ãã ãµãŒããŒã¯ãå ¥åXãæéXã«è¡šç€ºãããããã«ãå ¥åXãã²ãŒã ã®æåŸã®ç¶æ ã«é©çšããå¿ èŠããããŸãã
- ãµãŒããŒã«ãã£ãŠéä¿¡ãããGameStateã«ã¯ããµãŒããŒåŽãšã¯ã©ã€ã¢ã³ãåŽã®äž¡æ¹ã®ããŽã·ãšãŒã·ã§ã³ã«å¿ èŠãªã¿ã€ã ã¹ã¿ã³ããå«ãŸããŠããŸãã
å¥çŽã®è©³çŽ°ïŒ èµ€ãããã¯ã¹ ïŒ
- ãµãŒããŒã¯ä¿åããå¿
èŠããããŸã
- GameStateHistory - Pæéæ ã§ã®GameStateç¶æ ã®å±¥æŽãããšãã°ãæåŸã®1ç§éã®ãã¹ãŠã®GameStateã
- ProcessedUserInput-æéæ Pããšã«åŠçãããUserInputå ¥åããŒã¿ã®å±¥æŽãããšãã°ãGameStateHistoryæéæ ãšåãå€
- UnprocessedUserInput- Pã¿ã€ã ãã¬ãŒã ã§ãåä¿¡ããããUserInputã«ãã£ãŠãŸã åŠçãããŠããªã
- ãµãŒããŒããŠãŒã¶ãŒããå ¥åãåãåã£ããã UnprocessedUserInputã«æ¿å ¥ããå¿ èŠããããŸãã
- 次ã«ããµãŒããŒã®æ¬¡ã®ãã¬ãŒã ã§
- UnprocessedUserInputã®çŸåšã®ãã¬ãŒã ãããå€ãå ¥åããŒã¿ããã§ãã¯ããŸã
- ããããååšããªãå Žåããã¹ãŠãæ£åžžã§ãããã²ãŒã ããžãã¯ã¯ææ°ã®GameStateãšå¯Ÿå¿ããå ¥åããŒã¿ïŒååšããå ŽåïŒã䜿çšããŠå®è¡ããã顧客ã«ãããŒããã£ã¹ããããŸãã
- ããããã§ããã°ãããã¯ã以åã«çæãããã²ãŒã ã®ç¶æ ã®äžéšãæ å ±ã®æ¬ èœã«ãã誀ã£ãŠããããšãæå³ãããããä¿®æ£ããå¿ èŠããããŸãã
- æåã«ãããšãã°æéNã®éã«æãå€ãæªå å·¥ã®å ¥åãèŠã€ããå¿ èŠããããŸãïŒãã³ãïŒ UnprocessedUserInputããœãŒããããŠããå Žåããã®æäœã¯é«éã§ãïŒã
- 次ã«ã GameStateHistoryããTime Nã®å¯Ÿå¿ããGameStateç¶æ ãååŸãã ProcessedUserInputããTime Nã®åŠçæžã¿å ¥åãååŸããå¿ èŠããããŸã
- ããã3ã€ã®ããŒã¿ã䜿çšããŠãããæ£ç¢ºãªæ°ããGameStateãäœæã§ããŸãã
- 次ã«ãæªåŠçã®å ¥åNã®æªå å·¥ã®å ¥åãProcessedUserInputã«ç§»åããŠãå°æ¥çã«èª¿æŽã®ããã«äœ¿çšã§ããããã«ããŸãã
- GameStateHistoryã§GameState NãæŽæ°ãã
- æåŸã®GameStateãååŸãããŸã§
N+1, N+2 ...
ã«å¯ŸããŠæé 4ã7ãç¹°ãè¿ããŸãã - ãµãŒããŒã¯æåŸã®ãã¬ãŒã ããã¹ãŠã®ãã¬ãŒã€ãŒã«éä¿¡ããŸãã
è°è«
ãµãŒããŒåŽã®ããŽã·ãšãŒã·ã§ã³ã«ã¯ãã¯ã©ã€ã¢ã³ãã®ããŽã·ãšãŒã·ã§ã³ãšåãåé¡ããããŸãã 調æŽãå¿ èŠãªå Žåãããã¯ç§ãã¡ãäœãééã£ãããšãããããšãæå³ããã¹ããŒãªãŒãå€æŽããããšã§ãšã©ãŒãä¿®æ£ããŸãã ããã¯ããã¬ã€ã€ãŒã殺ããªã©ã®äžå¯éçãªçµæãé©çšã§ããªãããšãæå³ããŸãã ãã®ãããªäžå¯éçãªå¹æã¯ã GameStateHistoryããã®ãã®ã§ããå Žåã«ã®ã¿é©çšã§ããŸãã æžãæããããªããªã£ããšãã
ããã«ã誀ã£ãGameStateã«ãããUIãã²ã©ããžã£ã³ãããããšããããŸãã 次ã®å³ã¯ããããã©ã®ããã«èµ·ãããã瀺ããŠããŸãã

ãªããžã§ã¯ãã¯æåã«å·Šäžé ã«é 眮ãããå³ã«ç§»åããŸãããããã®ãã¡5ã€ãå³ã«ç§»åããŸããããµãŒããŒã¯ãŠãŒã¶ãŒå ¥åãåãåãããªããžã§ã¯ããTick Nã§æ¹åãå€æŽããããšãéç¥ããããããµãŒããŒã¯ã²ãŒã ã®ç¶æ ã調æŽããŸãããã®å Žåããªããžã§ã¯ãã¯çªç¶ç»é¢ã®å·Šäžé ã«ãžã£ã³ãããŸãã
ãããããç§ã¯ãã®åœ±é¿ãèªåŒµããŸãããªããžã§ã¯ãããããŸã§ã«åãããé£èºãããã»ã©ç®ç«ããªãããšããããŸãããå€ãã®å Žåãããã¯ãŸã æããã§ããGameStateHistoryãUnprocessedUserInputããã³ProcessedUserInputã®ãµã€ãºãå€æŽããããšã§ããžã£ã³ããå¶åŸ¡ã§ããŸãããããã¡ãµã€ãºãå°ããã»ã©ããžã£ã³ããå°ãããªããŸããããã¯ãéåžžã«é ãå ¥åããŒã¿ã«å¯Ÿãã蚱容床ãäœããªãããã§ããããšãã°ãå ¥åããŒã¿ã100ããªç§ä»¥äžé ãããšããããã¯ç¡èŠãããpingã200ããªç§ãè¶ ãããã¬ãŒã€ãŒã¯ã²ãŒã ããã¬ã€ã§ããªããªããŸãããããã¯ãŒã¯é 延ã®èš±å®¹ç¯å²ã
ç ç²ã«ããŠãã²ãŒã ã®ç¶æ ãããæ£ç¢ºã«æŽæ°ãããããã®éãè¡ãããšãã§ããŸãã
äžæ£ç¢ºãªã²ãŒã ç¶æ ã®åé¡ã«å¯ŸåŠããããã®äžè¬çãªãã¯ããã¯ã®1ã€ããããŸããããã¯ãªããžã§ã¯ãã®è£éïŒãšã³ãã£ãã£è£éïŒã§ããã¢ã€ãã¢ã¯ããžã£ã³ããçæéã§äŒžã°ãããšã§ã¹ã ãŒãºã«ãžã£ã³ãããããšã§ãã

ãã®èšäºã§ã¯ããªããžã§ã¯ãè£éã®å®è£ ã®è©³çŽ°ã«ã€ããŠã¯èª¬æããŸããã ãã ããæåŸã«åœ¹ç«ã€ãªã³ã¯ãæäŸããŸãã
ãŸãšãããš
ã¯ã©ã€ã¢ã³ããšãµãŒããŒããã«ããã¬ã€ã€ãŒã²ãŒã ã§ã©ã®ããã«æ©èœãããã«ã€ããŠèª¬æããŸããã

å šäœçã«ããã«ããã¬ã€ã€ãŒã²ãŒã ã¯ã3ã€ã®èªç±ã«æ¥ç¶ããããµã€ã¯ã«ããããµãŒããŒã®ã²ãŒã ã«ãŒããã¯ã©ã€ã¢ã³ãã®äºæž¬ã«ãŒããšã¯ã©ã€ã¢ã³ãUIã®ã¬ã³ããªã³ã°ãµã€ã¯ã«ãããããã®éã«ãããã¡ãäœæããããšã§ãå®è£ ããã»ã¹ãåå²ã§ããããè¯ãã²ãŒã ãã¬ã€ãäœæããæè»æ§ãæäŸããŸãã
ãããã«
ããã§ããã«ããã¬ã€ã€ãŒã²ãŒã ã«é¢ããç§ã®èšäºã¯çµããã§ãããã®åéã®å°é家ãããã®ãããã¯ã«ã€ããŠå€ãã®ããšãåŠã³ãŸããããŸããåçŽãªãã«ããã¬ã€ã€ãŒã²ãŒã ã®äŸãéåžžã«åœ¹ç«ã¡ãŸããããã«ããŠãŒã¶ãŒãµãŒããŒãå®è£ ããæ¹æ³ã1ã€ã ã瀺ããŸããããä»ã«ããããŸããé©åãªãã®ãéžæãããã©ããã¯ãäœæããŠããã²ãŒã ã®çš®é¡ã«ãã£ãŠç°ãªããŸããç°¡åãªã²ãŒã ãäœæããŠãããã€ãã®ã¢ãããŒããæ€èšããããšããå§ãããŸãã
èªãã§ãããŠããããšããè¯ããããã³ã°ïŒ
ãªã³ã¯ãšè¿œå è³æ
- [ãªããžã§ã¯ãã®è£é]-http ://www.gabrielgambetta.com/fpm3.html
- [ãªããžã§ã¯ãè£é]-http: //gafferongames.com/networked-physics/snapshots-and-interpolation/
- [é ãã®è£å]-https ://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking#Lag_compensation