스레딩없는 스크립팅 및 영화


12

게임 엔진에서 스크립팅을 구현하는 방법에 어려움을 겪고 있습니다. 몇 가지 요구 사항 만 있습니다. 직관적이어야하며 사용자 지정 언어, 파서 및 인터프리터를 작성하고 싶지 않으며 스레딩을 사용하고 싶지 않습니다. (더 간단한 솔루션이 있다고 확신합니다. 여러 게임 로직 스레드가 필요하지 않습니다.) 다음은 Python (일명 의사 코드)의 스크립트 예제입니다.

def dramatic_scene(actors):
    alice = actors["alice"]
    bob = actors["bob"]

    alice.walk_to(bob)
    if bob.can_see(alice):
        bob.say("Hello again!")
    else:
        alice.say("Excuse me, Bob?")

장대 한 스토리 텔링은 구현 문제를 야기합니다. walk_to게임 시간이 걸리기 때문에 전체 방법을 한 번에 평가할 수는 없습니다 . 그것이 곧바로 돌아 오면 Alice는 Bob에게 걸어 가기 시작하고 (같은 프레임에서) 인사합니다. 그러나 walk_toBob에 도달했을 때 반환되는 차단 호출 인 경우 Alice가 걸을 수있는 동일한 실행 스레드를 차단하기 때문에 내 게임이 중단됩니다.

나는 각 함수가 액션을 대기열에 alice.walk_to(bob)넣는 것을 고려 했다. 큐에 객체를 밀어 넣을 것이다. 앨리스는 어디에 있든 Bob에게 도달 한 후에 튀어 나올 것이다. 좀 더 미묘하게 깨졌습니다. if지점이 즉시 평가되므로 Bob이 등을 돌리더라도 Alice가 인사 할 수 있습니다.

스레드를 만들지 않고 다른 엔진 / 사람이 스크립팅을 어떻게 처리합니까? jQuery 애니메이션 체인과 같은 게임이 아닌 영역에서 아이디어를 찾기 시작했습니다. 이런 종류의 문제에는 좋은 패턴이 있어야합니다.


1
질문에 +1, 특히 "Python (일명 의사 코드)":)
Ricket

파이썬은 초강력을 갖는 것과 같습니다.
ojrac

답변:


3

Panda와 같은 방법은 콜백입니다. 차단하는 대신

def dramatic_scene(actors):
    alice = actors["alice"]
    bob = actors["bob"]

    def cb():
        if bob.can_see(alice):
            bob.say("Hello again!")
        else:
            alice.say("Excuse me, Bob?")
    alice.walk_to(bob, cb)

완전한 콜백이 있으면 이러한 종류의 이벤트를 원하는만큼 연결할 수 있습니다.

편집 : JavaScript 스타일 이므로이 스타일에 대한 구문이 더 좋습니다.

function dramatic_scene(actors) {
    var alice = actors.alice;
    var bob = actors.bob;
    alice.walk_to(bob, function() {
        if(bob.can_see(alice)) {
            bob.say('Hello again!');
        } else {
            alice.say('Excuse me, Bob?');
        }
     });
}

그것은 +1을 위해 충분히 작동합니다. 나는 단지 콘텐츠 디자인에 잘못되었다고 생각합니다. 스크립트가 단순하고 명확하게 보이도록 추가 작업을 기꺼이합니다.
ojrac

1
@ojrac : 사실이 방법이 더 좋습니다. 여기 같은 스크립트에서 여러 배우에게 동시에 걷기 시작하도록 지시 할 수 있기 때문입니다.
바트 반 Heukelom

좋은 지적이야
ojrac September

그러나 가독성을 높이기 위해 콜백 정의는 walk_to () 호출 안에 중첩되거나 나중에 호출되는 코드가 소스에서 나중에 볼 수 있도록 호출됩니다 (둘 다 언어가 지원되는 경우).
바트 반 Heukelom

예, 파이썬은 불행히도 이런 종류의 구문에는 좋지 않습니다. JavaScript에서는 훨씬 멋지게 보입니다 (위의 코드 형식을 사용할 수 없음).
coderanger

13

여기서 검색하고자하는 용어는 " 코 루틴 "(일반적으로 언어 키워드 또는 함수 이름은 yield)입니다.

코 루틴은 서브 루틴을 일반화하여 특정 위치에서 실행을 일시 중단 및 재개하기위한 여러 진입 점을 허용하는 프로그램 구성 요소입니다.

구현은 우선 귀하의 언어에 달려 있습니다. 게임의 경우 구현이 최대한 가벼워 지길 원합니다 (실 또는 섬유보다 가벼움). Wikipedia 페이지 (링크)에는 다양한 언어 별 구현에 대한 링크가 있습니다.

루아가 코 루틴을 기본적으로 지원한다고 들었습니다. GameMonkey도 마찬가지입니다.

언리얼 스크립트는 이것을 "상태"와 "잠재적 인 함수"라고 부르는 것으로 구현합니다.

C #을 사용하는 경우 Nick Gravelyn 의이 블로그 게시물 을 볼 수 있습니다.

또한 "애니메이션 체인"아이디어는 동일하지는 않지만 동일한 문제에 대한 실행 가능한 솔루션입니다. Nick Gravelyn도 이것에 대한 C # 구현을 가지고 있습니다.


Nice catch, Tetrad;)
Andrew Russell

이것은 정말 좋지만, 거기에 100 % 나에게 확실하지 않습니다. 코 루틴을 사용하면 호출 메소드를 생성 할 수있는 것처럼 보이지만 Lua 스크립트에서 C # 코드까지 스택을 작성하는 동안 while (walk_to ()! = done) {yield}.
ojrac

@ojrac : Lua에 대해 모르겠지만 Nick Gravelyn의 C # 메서드를 사용하는 경우 스크립트 관리자가 확인할 조건을 보유하는 대리자 (또는 하나를 포함하는 개체)를 반환 할 수 있습니다 (Nick의 코드는 시간을 반환합니다) 암시 적으로 조건부입니다). 잠재 함수 자체가 대리자를 반환하도록 할 수도 있으므로 yield return walk_to();스크립트에 다음을 작성할 수 있습니다.
앤드류 러셀

C #의 수확량은 훌륭하지만 간단하고 쉽게 작성하기 어려운 스크립팅을 위해 솔루션을 최적화하고 있습니다. 수익률보다 콜백을 설명하는 데 더 쉬운 시간이 있으므로 다른 답변을 수락하겠습니다. 내가 할 수 있으면 +2 할 것이다.
ojrac September

1
일반적으로 yield 호출을 설명 할 필요는 없습니다. 예를 들어 "walk_to"함수로 래핑 할 수 있습니다.
Kylotan

3

스레드되지 않는 것이 똑똑합니다.

대부분의 게임 엔진은 각 단계마다 메모리를 구동하는 일련의 모듈 식 단계로 작동합니다. 예를 들어 '걸어서 걷기'의 경우 일반적으로 걷는 캐릭터가 적을 죽이지 말아야 할 상태, 애니메이션 X를 실행해야하는 애니메이션 스테이지, 물리 스테이지 (또는 물리 스테이지) 인 AI 스테이지가 있습니다. 실제 위치 등이 업데이트되는 시뮬레이션 단계)

위의 예에서 'alice'는 이러한 여러 단계에있는 조각으로 구성된 액터이므로 차단 actor.walk_to 호출 (또는 프레임 당 한 번에 next ()를 호출하는 코 루틴)에 적절한 컨텍스트가 없을 것입니다. 많은 결정을 내릴 수 있습니다.

대신 'start_walk_to'함수는 다음과 같은 작업을 수행합니다.

def start_cutscene_walk_to(actor,target):
    actor.ai.setbrain(cutscene_brain)
    actor.physics.nocoll = 1
    actor.anims.force_anim('walk')
    # etc.

그런 다음 메인 루프는 인공 지능, 물리 진드기, 애니메이션 진드기 및 컷신 틱을 실행하고 컷 신은 엔진의 각 하위 시스템에 대한 상태를 업데이트합니다. 컷신 시스템은 각각의 컷 신이 무엇을하고 있는지를 정확하게 추적해야하며, 커스트 신과 같은 선형적이고 결정적인 무언가를위한 코 루틴 구동 시스템이 의미가있을 수 있습니다.

이 모듈화의 이유는 일을 멋지고 단순하게 유지하고 일부 시스템 (물리 및 AI 등)의 경우 모든 상태를 동시에 알고 일을 올바르게 해결하고 게임을 일관된 상태로 유지해야하기 때문입니다 .

도움이 되었기를 바랍니다!


나는 당신이 원하는 것을 좋아하지만 실제로 actor.walk_to ([다른 액터, 고정 위치 또는 위치를 반환하는 함수])의 가치에 대해 강하게 느낍니다. 저의 목표는 간단하고 이해하기 쉬운 도구를 제공하고 게임의 콘텐츠 제작 부분에서 모든 복잡성을 처리하는 것입니다. 또한 제가 정말로 원하는 것은 각 스크립트를 유한 상태 머신으로 취급하는 방법이라는 것을 깨달았습니다.
ojrac

도와 줄 수있어 기쁘다! 나는 내 대답이 약간 주제가 아닌 것처럼 느꼈습니다. :) 목표를 달성하기위한 actor.walk_to 함수의 가치에 분명히 동의합니다. 구현에 대해 듣고 싶습니다.
Aaron Brady

jQuery 스타일의 콜백과 체인 함수를 함께 사용하는 것처럼 보입니다. 허용 된 답변보기;)
ojrac
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.