독립 체가 자신의 움직임을 처리해야합니까?

Dec 06 2020

저는 현재 2D 배열의 Tile 개체로 구성된 Room으로 간단한 턴 기반 게임을 만들고 있습니다. WallTile 또는 FloorTile이 될 수 있습니다. 타일 ​​개체에는 북쪽, 동쪽, 남쪽 및 서쪽 이웃이 있습니다. FloorTiles에는 상위 엔티티를 쉽게 그릴 수 있도록 엔티티 스택이 있습니다.

이제 플레이어가 움직일 때 플레이어가 해당 로직을 처리해야합니까, 아니면 플레이어를 보유한 게임을 처리해야합니까?

첫 번째 경우에는 다음과 같은 내용이 있습니다.

class Player : Entity {
    public Tile CurrentLocation

    public bool CanMoveTo(Direction) {
        // Let's say that direction is East
        return CurrentLocation.EastNeighbour == FloorTile
    }

    // This method does the actual move
    public void MoveTo(Direction)
}

두 번째 경우에는 다음과 같습니다.

class Game {
    public Player Player;
    public Room Room;

    public void Update() {
        // Lets say we get direction from some input from somewhere
        if Room.TileAt(player.Y, player.X) is FloorTile then MoveThere()
    }
}

두 가지 옵션 중 가장 좋은 것이 무엇인지 잘 모르겠습니다. 처음에는 첫 번째 해결책에 대해 생각하고 있습니다. 어떤 도움이나 조언을 주시면 감사하겠습니다.

답변

4 Philipp Dec 06 2020 at 11:26

일을하는 데에는 옳고 그른 방법이 없습니다. 당신을 위해 일하거나 당신을 위해 일하지 않는 유일한 방법.

주류 게임 아키텍처에는 몇 가지 경쟁 철학이 있습니다.

A : 객체 지향 아키텍처

모든 엔티티는 객체로 표현되어야합니다. 이러한 개체는 자체 논리를 모두 포함하고 내부 상태를 캡슐화하고 잘 정의 된 인터페이스를 통해 다른 개체와 통신해야합니다. 핵심 게임 엔진은 루프에있는 모든 엔티티의 "Update"및 "Render"메소드를 호출 한 다음 엔티티가 나머지 작업을 수행하도록합니다.

일부 기능을 공유하는 객체가있는 경우 일반적으로 상속을 통해 공통 기능을 공통 기본 클래스로 추출하여이를 수행합니다. 예를 들어, 모든 전투 코드를 포함하는 Combatant 클래스에서 상속하고 이동을위한 기본 코드를 포함하는 Entity에서 상속하는 클래스 Player와 Enemy 클래스를 가질 수 있습니다. 그리고 Enemy는 모든 적에게 공통된 로직 만 포함하는 추상 클래스 일 가능성이 높으며, Enemy에서 상속 된 클래스에서 구현 된 다양한 적 유형과 고유 한 동작을 포함합니다.

기본적으로 책에 의해 OOP를 수행해야하는 방식입니다.

이 스타일은 응용 프로그램 개발에서 온 개발자들에게서 자주 볼 수 있습니다. 그리고 응용 프로그램에서 작동하는 것이 게임에서 반드시 완전히 잘못된 것은 아닙니다.

B : 엔터티 구성 요소 아키텍처

이 스타일은 상속 보다 합성을 선호합니다 . 엔터티는 하나의 개체가 아니라 각 개체가 해당 엔터티의 다른 기능을 구현하는 개체의 모음입니다. 따라서 플레이어가 할 수있는 모든 일을 구현하는 "Player"클래스가 없습니다. "Sprite", "Mover", "Shooter", "Hitpoints"및 "PlayerInput"구성 요소가있는 일반 엔티티가 있습니다.

이 접근 방식의 장점은 새로운 종류의 게임 엔터티를 만들기 위해 구성 요소를 매우 쉽게 혼합하고 일치시킬 수 있다는 것입니다. 이것은 게임 디자인의 빠른 반복에 매우 유용합니다. 일부 인기있는 게임 엔진에서 가장 선호하는 접근 방식입니다. 예를 들어 Unity처럼.

C : 엔티티-컴포넌트-시스템 아키텍처

엔티티는 "Entity-Component"아키텍처에서와 같이 구성 요소의 모음이어야합니다. 그러나이 아키텍처에서 이러한 구성 요소는 멍청한 데이터 소유자 여야합니다. 일반적으로 공용 변수 만 있고 메서드가없는 구조 형태입니다. 모든 논리는 시스템에 있어야합니다. 각 시스템은 한 유형의 구성 요소 또는 구성 요소 집합을 관리합니다. 예를 들어, Movement 컴포넌트로 모든 엔티티의 Position 컴포넌트를 업데이트하는 MovementSystem이 있습니다.

그러나 이것은 단지 지나치게 단순화 된 것입니다. 자세한 내용은 "순수 ECS 란 무엇입니까?"라는 질문을 확인하십시오. . entity-component-system 태그 에서 다른 질문을 볼 수도 있습니다 .

ECS 접근 방식은 현재 매우 유행하고 있습니다. 이에 대한 주된 주장은 Entity-Component 접근 방식의 모듈 성과 반복 속도를 희생하지 않고 매우 깔끔한 성능 최적화 (특히 메모리 지역성 및 멀티 스레딩과 관련하여)를 허용한다는 것입니다. 그러나 단점은 견고하고 유연한 ECS 아키텍처에는 "뒤에서"실행되는 아키텍처 코드가 많이 필요하고 초보자에게는 구현하기 어려울 수 있다는 것입니다.

어느 것을 사용해야합니까?

그것은 당신이 스스로 알아내는 데 필요한 것입니다. 그러나 게임에 어떤 접근 방식을 선택하든 그대로 유지하는 것이 좋습니다. 가능한 경우 게임에서 혼합 및 일치 아키텍처 패턴을 피하십시오.

Turing Dec 09 2020 at 19:08

기본적으로 게임 네트워크를 통과하는 데이터의 양에 따라 다릅니다. 대규모 멀티 플레이어는 누가 항상 무엇을하고 있는지 추적해야합니다 (그렇지 않으면 대규모 부정 행위가 발생합니다). 그러나 서버에서 모든 클라이언트 (권한 서버라고 함)로 패킷을 수신하고 보내는 것은 중요 사용자 수에 관계없이 실용적이지 않습니다. 따라서 철학은 플레이어가 다른 플레이어에게 영향을주지 않고 제어 할 수있는 논리의 정도 인 것 같습니다. 즉, 귀하와 귀하에게만 영향을 미치는 사항 (약탈 제외)은 클라이언트가 처리 할 수 ​​있습니다. 여러 플레이어에게 영향을 미치는 것은 서버에서 처리해야합니다. 또는 취급하지 않는 경우 효과가 발생하기 전에 최소한 승인됩니다.