XNA GameComponents (또는 게임의 모든 유형의 구성 요소) 간의 통신을 용이하게하기 위해 어떤 기술을 사용해야합니까?


9

첫 번째 '적절한'게임 프로젝트를 시작했으며 XNA의 게임 구성 요소가 어떻게 통신해야하는지 결정하려고 노력했습니다.

이전의 (Java) GUI 프로그래밍 이벤트에서 핸들러와 리스너는 앞으로 나아갈 것 같았습니다. 그래서 이벤트 등록을 허용하는 이벤트 버스와 이벤트를 처리하는 처리기가있는 이벤트 등록 클래스가 있습니다. 예를 들어 (의사 코드) :

class SpriteManager
    Update(){
        if(player.collidesWith(enemy)
             // create new 'PlayerCollisionEvent'
    }

class HUDManager
    onPlayerCollisionEvent(){
        // Update the HUD (reduce lives etc)
    }

그러나이 작업을 완전히 수행하는 데 필요한 코드 설정 (C #)은 확실하지 않습니다. 이벤트 (일종의 버스)를 추적하는 것은 무엇이며 어떻게 구성됩니까?

또한 Game Services에 대해 많은 언급이있는 것처럼 보입니다. 주요 Game.cs 클래스에 GameComponent를 등록 한 다음 주 'Game'객체에 대한 참조가있는 코드의 어느 곳에서나 가져올 수 있습니다. SpriteBatch 객체로 이것을 시도했지만 매우 쉬운 것처럼 보입니다. 그러나 이벤트 모델만큼 융통성이없는 것을 볼 수 없습니다.

적이 죽을 때를 예로 들어 보겠습니다. 게임 점수를 업데이트하고 싶습니다. 서비스를 사용하여 Game1에서 생성되고 서비스로 추가 된 StateManager 객체에 대한 참조를 얻은 다음 'score'를 새 값으로 설정할 수 있습니다. 나는 여러 클래스에서 다르게 처리 할 수 ​​있지만 관련 '죽음 감지'섹션에서 1 줄의 코드로 시작되는 'onEnemyDeath'이벤트를 생각할 것입니다. 각 필요한 GameComponent를 개별적으로 캐스팅 한 다음 무엇이든 호출하는 것보다 낫습니다. 방법이 필요합니다.

아니면 이러한 열등한 전략이 다른 것보다 좋은가?

나는 이것이 게임 커뮤니케이션 패러다임만큼 C # 지식이 부족하다는 것을 알고 있지만 실제로이 근본적인 것을 얻고 싶습니다.

최신 정보

서비스를 살펴보면 확신이 덜합니다. 기본적으로 전역 변수를 (내가 이해 한 것) 전달합니다.

업데이트 2

이벤트 처리 및 샘플 코드 테스트에 대한 이 기본 자습서를 살펴본 결과 이벤트는 내가 논의하고있는 논리적 인 선택 인 것 같습니다. 그러나 내가 본 샘플에서 많이 사용하지는 못합니다. 왜 안되어야하는지 분명한 이유가 있습니까?


먼저 FlatRedBall을 사용해 보는 것이 좋습니다. XNA 위에 있으며 인생을 정말 쉽게 만듭니다.
ashes999

3
엔진으로 점프하기 전에 무슨 일이 일어나고 있는지에 대한 기본 사항을 정말로 이해하고 싶습니다.
codinghands

여기서 실패하면 실제로 C #에 대한 정보가 부족하다고 생각합니다. C #은 일반적으로 이벤트를 사용하여 클래스 간의 통신을 용이하게합니다. XNA는 SpriteBatch 클래스를 제공하며 대부분의 작업은 사용자가 작성해야합니다. 엔진은 세부 사항을 살펴보기 전에 사물이 더 높은 수준에서 작동하는 방법에 대한 확실한 아이디어를 제공합니다.
ashes999

1
어느 정도 동의하지만 GameComponents 간의 대부분의 클래스 간 통신은 서비스를 사용하여 수행 할 수 있습니다. 나는 이벤트를 사용하는 데 익숙합니다. 어느 것이 가장 좋은지 확실하지 않거나 유효한 대안이 있는지 (싱글 톤, 전역 클래스로 가장하는 정적 클래스, 내가 생략 한 2 가지 방법)
codinghands

답변:


4

이전의 (Java) GUI 프로그래밍 이벤트에서 핸들러와 리스너는 앞으로 나아갈 것 같았습니다. 그래서 이벤트 등록을 허용하는 이벤트 버스와 이벤트를 처리하는 처리기가있는 이벤트 등록 클래스가 있습니다.

C #에서 이벤트 버스에 대해 많이 찾지 못하는 이유는 Java 이외의 다른 사람은 내 경험에서 그러한 것을 '버스'라고 부르지 않기 때문입니다. 보다 일반적인 용어는 메시지 큐, 이벤트 관리자, 신호 / 슬롯, 발행 / 구독 등일 수 있습니다.

작동하는 게임을 만드는 데 필요한 사람은 필요하지 않지만 편안한 시스템이라면 여기에서도 잘 작동합니다. 불행히도 아무도 그것을 사용하는 경우조차 모두 조금씩 다르게 굴리기 때문에 아무도 어떻게 만드는지 정확히 알 수 없습니다. (예를 들어, 그렇지 않습니다.) System.Collections.Generic.List<Event>다양한 이벤트가 이벤트의 서브 클래스 인 각 이벤트 유형의 등록자 목록 인 큐에 대한 단순으로 시작할 수 있습니다 . 대기열의 각 이벤트에 대해 가입자 목록을 가져오고 각 가입자에 대해 전화 handle(this_event)하십시오. 그런 다음 대기열에서 제거하십시오. 반복.

또한 Game Services에 대해 많은 언급이있는 것처럼 보입니다. 주요 Game.cs 클래스에 GameComponent를 등록 한 다음 주 'Game'객체에 대한 참조가있는 코드의 어느 곳에서나 가져올 수 있습니다. SpriteBatch 객체로 이것을 시도했지만 매우 쉬운 것처럼 보입니다. 그러나 이벤트 모델만큼 융통성이없는 것을 볼 수 없습니다.

아마 유연하지는 않지만 디버깅하기가 더 쉽습니다. 이벤트와 메시지는 호출 된 함수와 호출 된 함수를 분리하기 때문에 까다 롭습니다. 즉, 디버깅 할 때 호출 스택이 크게 도움이되지 않습니다. 중간 작업으로 인해 정상적으로 작동하는 무언가가 중단되고 정상적으로 연결되지 않으면 자동으로 실패 할 수 있습니다 , 등등. "컴포넌트를 가져 와서 필요한 것을 호출"하는 명시적인 방법은 오류를 조기에 발견하고 명확하고 명확한 코드를 가질 때 효과적입니다. 그것은 밀접하게 결합 된 코드와 많은 복잡한 의존성을 유발하는 경향이 있습니다.

나는 이것이 게임 커뮤니케이션 패러다임만큼 C # 지식이 부족하다는 것을 알고 있지만 실제로이 근본적인 것을 얻고 싶습니다.

C #은 Java와 거의 동일한 언어입니다. Java에서 수행 한 작업은 C #에서 다른 구문으로 수행 할 수 있습니다. 개념을 번역하는 데 문제가 있다면, 아마도 Java 특정 이름 만 알고 있기 때문일 것입니다.


@Kylotan에게 감사합니다. 호기심에서, 당신은 어떤 시스템을 클래스 간 통신에 사용합니까-서비스 접근 방식 또는 다른 것?
codinghands

AFAIK, 이벤트 버스는 메시징 대기열과 유사하지만 이벤트 용입니다.
ashes999

2
@codinghands, 나는 일반적으로 공식화 된 클래스 간 통신 방법을 사용하지 않습니다. 한 클래스가 다른 클래스를 호출 해야하는 경우 일반적으로 이미 두 번째 클래스를 멤버로 참조하거나 두 번째 클래스를 인수로 전달했습니다. 그러나 때로는 Unity 엔진으로 작업 할 때 '서비스'접근법과 비슷한 접근법을 사용합니다. 필요한 구성 요소가있는 이름으로 객체를 찾고 구성 요소를 찾습니다. 그런 다음 해당 컴포넌트에서 메소드를 호출하십시오.
Kylotan

@ ashes999-이 컨텍스트에서 메시지와 이벤트는 거의 동일합니다. 이벤트를 대기열, 버스 또는 무엇이든 넣는 경우 실제로 저장하는 것은 이벤트가 발생했음을 나타내는 메시지입니다. 마찬가지로 메시지를 큐에 넣는 것은 해당 메시지를 생성하는 이벤트가 발생했음을 의미합니다. 비동기 함수 호출을 보는 다른 방법.
Kylotan

죄송합니다. 아직 '답변 됨'으로 표시하지는 않았지만 언어에 관계없이 모든 게임이 구성 요소간에 통신해야한다는 점에서 더 많은 견해가있을 것이라고 생각했습니다. 주요 가능성을 다루었습니까?
codinghands

1

간단한 정적 이벤트를 사용해 보셨습니까? 예를 들어, 적의 사망 시점에 대해 점수 클래스에 알리려면 다음과 같이하십시오.

Score.cs

class Score
{
    public int PlayerScore { get; set; }

    public Score()
    {
        EnemySpaceship.Death += new EventHandler<SpaceshipDeathEventArgs>(Spaceship_Death);
    }

    private void Spaceship_Death(object sender, SpaceshipDeathEventArgs e)
    {
        PlayerScore += e.Points;
    }
}

EnemySpaceship.cs

class EnemySpaceship
{
    public static event EventHandler<SpaceshipDeathEventArgs> Death;

    public void Kill()
    {
        OnDeath();
    }

    protected virtual void OnDeath()
    {
        if (Death != null)
        {
            Death(this, new SpaceshipDeathEventArgs(50));
        }
    }
}

우주선 사망 사건 Args.cs

class SpaceshipDeathEventArgs : EventArgs
{
    public int Points { get; private set; }

    internal SpaceshipDeathEventArgs(int points)
    {
        Points = points;
    }
}


0

같은 이벤트 애그리 게이터 (aggregator)를 사용하려고 이 일


4
링크를 제공하는 대신 제안에 대해 더 자세히 설명하면이 답변이 더 좋습니다.
MichaelHouse
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.