서브컬처 게이머

세상의 모든 아름다운 것들을 위하여


나니노벨 Custom Commands

개요

※이 글은 유니티 다이얼로그 시스템 에셋 ‘Naninovel(나니노벨)’의 한국어 번역 페이지입니다.

※모든 내용의 저작권 및 내용의 책임과 권한은 Naninovel에 있습니다.

※원문 페이지: (링크)

※마지막 수정일: 2024/11/30


명령어는 씬에서 일어나는 일을 제어하는 단일 작업을 의미합니다.

예를 들어, 배경을 변경하거나 캐릭터를 이동시키거나 다른 Naninovel 스크립트를 불러오는 데 사용할 수 있습니다.

Naninovel 스크립트에 정의한 매개변수화된 명령어 시퀀스는 게임의 흐름을 효과적으로 제어합니다. API reference에서 이미 정의된(빌트인) 명령어 목록을 확인하실 수 있습니다.

코드에서 모든 내장 스크립트 명령어 구현은 Naninovel.Commands 이름공간 하위에서 정의됩니다.


커스텀 명령어 추가하기

커스텀 스크립트 명령어를 추가하려면 Command에서 파생된 새 C# 클래스를 만들고 Execute로 추상 메서드를 구현합니다.

생성된 클래스는 엔진에 의해 자동으로 선택되며 클래스 이름이나 별칭(할당된 경우)을 사용하여 naninovel 스크립트에서 명령을 호출할 수 있습니다. naninovel 명령에 별칭을 할당하려면 CommandAlias ​​특성을 클래스에 적용합니다.

다음은 Naninovel 스크립트에서 @HelloWorld 또는 @hello라는 명령어를 입력했을 때 콘솔창에 ‘Hello World!’ 텍스트를 출력하는 커스텀 명령어의 예시입니다. name 파라미터를 이용하여 (예: @hello name:Felix) ‘Hello world!’ 대신에 ‘Hello Felix!’라는 이름으로 출력시키는 것도 가능합니다.

using Naninovel;
using Naninovel.Commands;
using UnityEngine;

[CommandAlias("hello")]
public class HelloWorld : Command
{
    public StringParameter Name;

    public override UniTask Execute (AsyncToken asyncToken = default)
    {
        if (Assigned(Name)) Debug.Log($"Hello, {Name}!");
        else Debug.Log("Hello World!");
        return UniTask.CompletedTask;
    }
}

Execute 메서드

Execute는 비동기 메서드로써 명령어가 명령어 로직이 위치하고 있는 스크립트 플레이어에 의해 재생될 때 호출됩니다.

engine services를 이용하여 (나니노벨) 엔진에 내장된 시스템에 접근 가능합니다.

Naninovel 스크립트에서 Execute 시에는 Wait 매개변수가 True일 때 이 메서드가 Task를 완료 처리할 때까지 잠시 멈추게 됩니다.

비동기토큰

Execute 메서드에 의해 전달되는 선택적 AsyncToken 구문을 확인하세요. 비동기 작업을 수행할 때 각 비동기 작업 후에 취소 및 완료 요청에 대한 토큰을 확인하고 그에 따라 대응하십시오.

  • AsyncToken.Canceled는 (나니노벨) 엔진이 종료되었거나 리셋되었음을 의미합니다. 두 경우 모두 엔진 API를 사용하는 것이 더 이상 안정적이지 않으며 상태 변화로 인해 정의되지 않은 동작이 발생하게 될 것입니다. 취소되었을 시 명령어 구현은 즉시AsyncOperationCanceledException을 발생시키고 현재 수행된 활동을 모두 삭제하게 됩니다.
  • AsyncToken.Completed는 명령어가 모든 활동을 가능한 한 빨리 완료해야 함을 의미합니다. 예를 들어 애니메이션을 실행 중인 경우 해당 작업의 예상 완료 기간에 관계없이 즉시 완료시킵니다. 보통 플레이어가 계속하기 입력을 활성화시키거나 게임 저장 작업이 시작되었을 때 일어납니다.
public override async UniTask Execute (AsyncToken asyncToken = default)
{
    await PerformSomething();
    // 위 메서드 동작 중 엔진이 디스트로이되었을 수 있습니다.
    // 위 경우, 아래 명령어는 상태 확인 후 예외처리를 동작시킵니다.
    asyncToken.ThrowIfCanceled();
    // 체크 이후 엔진 API를 동작시킵니다.
    var someUI = Engine.GetService<IUIManager>().GetUI<SomeUI>();
    // 완료 요청을 받은 경우 UI를 즉시 페이드합니다.
    var fadeDuration = asyncToken.Completed ? 0 : 5;
    await someUI.ChangeVisibility(false, fadeDuration, asyncToken);
    // 위의 방법은 토큰을 수락했으며, 이러한 방법은 내부적으로 
    // 취소 처리하므로 취소 후 확인할 필요가 없습니다.
}

파라미터 타입

Naninovel 스크립트에 명령어 파라미터를 노출시키려면 지원되는 유형 중 하나를 사용하여 명령어 클래스에 공개 필드(public field)를 추가하십시오.

필드 타입값 타입스크립트 예시
StringParameterStringLoremIpsum, "Lorem ipsum"
LocalizableTextParameterLocalizableText"Lorem ipsum|#id|"
IntegerParameterInt3210, 0, -1
DecimalParameterSingle0.525, -55.1
BooleanParameterBooleantrue, false
NamedStringParameterNamedStringScript001.LabelName, .LabelName
NamedIntegerParameterNamedIntegerYuko.5
NamedDecimalParameterNamedFloatKohaku.-10.25
NamedBooleanParameterNamedBooleanMisaki.false
StringListParameterList<String>Lorem,ipsum,"doler sit amet"
IntegerListParameterList<Int32>10,-1,0
DecimalListParameterList<Single>0.2,10.5,-88.99
BooleanListParameterList<Boolean>true,false,true
NamedStringListParameterList<NamedString>Felix.Happy,Jenna.Confidence
NamedIntegerListParameterList<NamedInteger>Yuko.5,Misaki.-8
NamedDecimalListParameterList<NamedFloat>Nanikun.88.99,Yuko.-5.1
NamedBooleanListParameterList<NamedBoolean>Misaki.false,Kohaku.true

파라미터 약어

선택적으로 [ParameterAlias] 특성을 필드에 적용하여 naninovel 스크립트에서 파라미터를 참조할 때 필드 이름 대신 파라미터에 별칭 이름을 할당해 사용할 수 있습니다.

파라미터를 이름 없이 설정하려면 NamelessParameterAlias ​​상수(빈 문자열)를 별칭으로 설정하세요. 명령어당 하나의 이름 없는 파라미터만 허용됩니다.

[ParameterAlias(NamelessParameterAlias)]
public StringParameter MyNamelesParameter;
[ParameterAlias("myParam")]
public StringParameter MyParameter;
@cmd "value of the nameless param" myParam:"value of 'MyParameter' param"

파라미터가 필수인 명령어

파라미터가 필수인 명령어를 만들려면(naninovel 스크립트에 지정되지 않은 경우 오류가 기록되도록 함) 해당 필드에 [RequiredParameter] 특성을 적용하세요. 속성이 적용되지 않으면 파라미터가 옵션 사항으로 간주됩니다.

[RequiredParameter]
public StringParameter MyRequiredParameter;

파라미터가 옵션인 명령어

파라미터가 필요하지 않은 경우 시나리오 스크립트에 값이 할당되거나 할당되지 않을 수 있습니다. HasValue 프로퍼티를 사용하여 이것이 사실인지 테스트할 수 있습니다.

또한, Assigned() 정적 메서드를 사용해 제공된 파라미터가 null값이 아니고 값이 할당된 경우에 대해 true 값을 반환하는 파라미터 인스턴스를 만들 수 있습니다.

public StringParameter MyOptionalParameter;
...
if (MyOptionalParameter.HasValue) { }
if (Assigned(MyOptionalParameter)) { }

로컬라이즈 가능한 명령어

명령어에 로컬라이즈 가능한 파라미터(일반적으로 사용자에게 직접 표시되는 텍스트)가 있는 경우 Command.ILocalized 인터페이스를 구현하여 생성된 스크립트 로컬라이즈 문서에 명령어를 추가하고 LocalizedTextParameter 파라미터 타입을 사용합니다.

public class PrintText : Command, Command.ILocalizable
{
    public LocalizableTextParameter Text;
}

사전 로드 가능한 명령어

명령어를 실행하기 위해서는 일부 리소스를 사전 로드해야 하는 경우가 있을 수 있습니다. Command.IPreloadable 인터페이스를 구현하여 게임을 로드할 때 필요한 리소스를 미리 로드하세요. 자세한 내용은 메모리 관리 가이드를 참조하세요.

public class PlayAudioClip : Command, Command.IPreloadable
{
    public StringParameter ClipPath;

    public async UniTask PreloadResources ()
    {
        if (!Assigned(ClipPath) || ClipPath.DynamicValue) return;
        await ... (load the audio clip here)
    }

    public void ReleasePreloadedResources ()
    {
        if (!Assigned(ClipPath) || ClipPath.DynamicValue) return;
        ... (unload the clip here)
    }
}

ClipPath.DynamicValue 확인에 유의하세요. 명령어가 실행될 때만 이름이 알려진 경우(예: 파라미터가 스크립트 표현식을 포함하는 경우) 리소스를 미리 로드할 수 없습니다. 이 경우 리소스는 Execute 메서드 내에 로드되어야 합니다.

명령어 예시

Naninovel/Runtime/Commands 패키지 폴더에서 모든 빌트인 명령어 구현이 포함된 스크립트를 찾을 수 있습니다.

커스텀 명령어를 구현할 때 이를 참고로 삼아 자유롭게 사용하십시오.

예시

인벤토리 시스템의 항목을 추가/제거하기 위해 커스텀 명령어를 추가하는 또 다른 예는 GitHub의 인벤토리 예제 프로젝트에서 찾을 수 있습니다.

특히 명령어 구현은 Runtime/Commands 디렉터리에 저장됩니다.


빌트인 명령어 재정의하기

어떤 경우에는 빌트인 Naninovel 명령어를 재정의하는 것이 유용할 수 있습니다.

예를 들어, 커스텀 명령어를 추가하지 않고 @print 명령이 작동하는 방식을 변경하여 변경 사항이 일반 텍스트 줄에도 영향을 미치도록 할 수 있습니다(일반 줄의 텍스트는 내부적으로 print 명령어로 파싱됩니다).

빌트인 명령어를 재정의하려면 커스텀 명령어를 추가하고 빌트인 명령어와 동일한 별칭을 적용하세요. 변경 사항을 적용하려면 명령을 재정의한 후 naninovel 스크립트를 다시 가져옵니다(저장된 폴더를 마우스 오른쪽 버튼으로 클릭한 다음 ‘다시 가져오기’ 클릭). 그러면 naninovel 스크립트를 재생시킬 때 빌트인 명령 대신 커스텀 명령어가 자동으로 사용됩니다.

다음은 빌트인 @print 명령을 재정의하여 출력된 텍스트가 플레이어에게 보여지기 전에 콘솔에 로그가 남게 되는 예입니다.

[CommandAlias("print")]
public class MyCustomPrintCommand : PrintText
{
    public override UniTask Execute (AsyncToken asyncToken = default)
    {
        Debug.Log(Text);
        return base.Execute(asyncToken);
    }
}

예시

포럼에서 빌트인 명령어를 재정의하는 더 유용한 예를 찾아보세요. 재정의된 사용자 정의 명령을 사용하면 일반 텍스트 줄 내에서 바로 표시 속도를 변경할 수 있습니다.

특히 명령어 구현은 Runtime/Commands 디렉터리에 저장됩니다.

Yuko: [s 0.1] 텍스트를 평소의 1/10 속도로 출력합니다. [s 2] 텍스트를 2배 빠르게 출력합니다.

연관글 목록

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다