포트 & 트리거
포트와 트리거는 엔티티에 속하며, Warudo 스크립팅에서 가장 중요한 요소라고 할 수 있어요. 이들은 엔티티 간에 데이터를 주고받고, 액션을 트리거하며, 에디터에서 사용자와의 상호작용을 제공해요.


데이터 인풋 포트
데이터 인풋 포트는 사용자가 에디터를 통해 제공하는 데이터를 받거나, 다른 엔티티로부터 데이터를 받을 때 사용돼요. 데이터 인풋은 다양한 타입을 가질 수 있는데, 문자열, 숫자, 불리언 같은 기본적인 타입부터 구조화된 데이터나 배열 같은 복잡한 타입도 지원해요.
데이터 인풋은 [DataInput] 속성으로 표시되며, 엔티티 서브클래스의 public 필드로 정의돼요. 당신의 첫 스크립트를 만들어보세요 예제에서 우리는 숫자 슬라이더를 정의하는 DataInput을 보았죠:
[DataInput]
[IntegerSlider(1, 100)]
public int LuckyNumber = 42;
다양한 예시가 있어요:
-
스트링 인풋:
[DataInput]
public string MyName = "Alice"; -
열거형 인풋: (에디터에서 드롭다운으로 표시)
public enum Color {
Red,
Green,
Blue
}
[DataInput]
public Color MyColor = Color.Red; -
배열 인풋: (에디터에서 수정 가능한 리스트로 표시)
[DataInput]
public float[] MyFavoriteNumbers = new float[] { 3.14f, 2.718f };
아래는 에디터에서 어떻게 보이는지의 예시예요 (이 예에서는 노드를 사용하지만, 에셋과 플러그인에서도 동일하게 적용돼요):

코드에서 지정한 기본값으로 데이터 인풋이 초기화되는 방식에 주목해 주세요.이 기본값들은 사용자가 데이터 인풋 레이블 옆에 있는 "Reset" 버튼을 클릭할 때 다시 할당돼요.
데이터 인풋은 일반적으로 직렬화 가능한 타입을 가집니다. 여기서 "직렬화 가능"이란 Warudo를 종료하고 다시 열었을 때 데이터 값이 저장되고 복원될 수 있음을 의미해요. 다음 타입들이 기본적으로 직렬화 가능해요:
- 기본 타입:
int,float,bool,string그리고 모든 열거형 타입 - Unity 타입:
Vector2,Vector3,Vector4,Color - 구조화된 데이터 타입
- 에셋 레퍼런스
- 직렬화 가능한 타입의 배열
노드의 경우, 에디터에서 수정할 수는 없지만 노드 자체에서 처리되는 비직렬화 가능한 데이터 인풋도 정의할 수 있어요. 예를 들어, 다음 코드는 제네릭 오브젝트 데이터 인풋에서 ToString() 메서드를 호출해요:
[NodeType(Id = "dc28819e-5149-4573-945e-40e81e2874c4", Title = "ToString()", Category = "CATEGORY_ARITHMETIC")]
public class ToStringNode : Node {
[DataInput]
public object A; // Not serialized
[DataOutput]
[Label("OUTPUT_STRING")]
public string Result() {
return A?.ToString();
}
}
다른 일반적인 데이터 인풋 타입은 직렬화할 수 없지만 노드 간에 전달할 수 있는 Dictionary, GameObject 그리고 Quaternion이 있어요.
속성
데이터 인풋 포트는 속성을 사용해 에디터에 추가적인 정보를 제공할 수 있어요. 예를 들어, 이전 에 봤던 [IntegerSlider] 속성은 데이터 인풋이 1에서 100까지의 범위를 가진 슬라이더로 표시되도록 지정해요. 지원되는 속성은 다음과 같아요:
[Label(string label)]: 데이터 인풋의 라벨을 지정해요.[HideLabel]: 데이터 인풋의 라벨을 숨기도록 지정해요.[Description(string description)]: 데이터 인풋의 설명을 지정해요.[HiddenIf(string methodName)]: 지정된 메서드가true를 반환하면 데이터 인풋이 숨겨지도록 지정해요. 메서드는 엔티티 클래스의public또는protected메서드여야 하며,bool을 반환해야 해요.[DataInput]
public int MyNumber = 0;
[DataInput]
[HiddenIf(nameof(IsSecretDataInputHidden))]
public string SecretDataInput = "I am hidden unless MyNumber is 42!";
public bool IsSecretDataInputHidden() => MyNumber != 42;[HiddenIf(string dataInputPortName, If @if, object value)]: 지정된 데이터 인풋 포트가@if조건을 만족하면 데이터 인풋이 숨겨지도록 지정해요. value는 상수여야 해요.[DataInput]
public int MyNumber = 0;
[DataInput]
[HiddenIf(nameof(MyNumber), If.NotEqual, 42)]
public string SecretDataInput = "I am hidden unless MyNumber is 42!";[HiddenIf(string dataInputPortName, Is @is)]: 지정된 데이터 인풋 포트가@is조건을 만족하면 데이터 인풋이 숨겨지도록 지정해요.[DataInput]
public CharacterAsset MyCharacter;
[DataInput]
[HiddenIf(nameof(MyCharacter), Is.NullOrInactive)]
public string SecretDataInput = "I am hidden unless MyCharacter is selected and active!";[DisabledIf(...)]:[HiddenIf(...)]와 유사하지만, 데이터 인풋이 숨겨지는 대신 비활성화돼요.[Hidden]: 데이터 인풋이 항상 숨겨지도록 지정해요. 코드는 사용하지만, 사용자에게 노출되지 않도록 할 때 유용해요.[Disabled]: 데이터 인풋이 항상 비활성화(편집 불가)되도록 지정해요. 예를 들어, 고정된 길이의 배열 데이터 인풋이거나, 항상 프로그래밍적으로 설정되는 데이터 인풋을 시각화할 때 유용해요.[Section(string title)]: 새로운 섹션과 함께 데이터 인풋 및 모든 후속 데이터 인풋이 표시되도록 지정해요. 다른 섹션이 지정되지 않는 한 계속 유지돼요.[SectionHiddenIf(string methodName)]:[Section]속성이 필요해요. 지정된 메서드가true를 반환하면 섹션이 숨겨지도록 지정해요. 메서드는public또는protected메서드여야 하며,bool을 반환해야 해요.@if및@is조건도 지원해요.[Markdown(bool Primary = false)]: 데이터 인풋이 Markdown 텍스트로 표시되며 편집할 수 없도록 지정해요. 데이터 인풋은string타입이어야 해요.primary가true면, 더 큰 글씨 크기와 배경색 없이 텍스트가 표시돼요. See Text Block for details.
[HiddenIf] 및 [DisabledIf] 속성은 에셋이나 노드가 편집기에서 보일 때 매 프레임 평가돼요. 따라서 이러한 메서드에서 성능 소모가 큰 연산은 피하는 것이 좋아요.
일부 속성은 특정 데이터 인풋 타입에만 적용돼요:
[IntegerSlider(int min, int max, int step = 1)]: 데이터 타입이int또는int[]이어야 해요. 지정된 범위를 가진 정수 슬라이더로 데이터 인풋을 표시하도록 지정해요.[FloatSlider(float min, float max, float step = 0.01f)]: 데이터 타입이float또는float[]이어야 해요. 지정된 범위를 가진 실수 슬라이더로 데이터 인풋을 표시하도록 지정해요.[AutoCompleteResource(string resourceType, string defaultLabel = null)]: 데이터 타입이string이어야 해요. 지정된 리소스 유형의 자동완성 리스트로 데이터 인풋을 표시하도록 지정해요. 예를 들어 "Character → Default Idle Animation" 데이터 인풋은[AutoCompleteResource("CharacterAnimation")]으로 정의돼요. 자세한 내용은[리소스 프로바이더 및 리졸버]페이지를 참조하세요.(resource-providers-and-resolvers.md) page for more information.[AutoCompleteList(string methodName, bool forceSelection = false, string defaultLabel = null)]: 데이터 타입이string이어야 해요. 지정된 메서드에 의해 생성된 드롭다운 메뉴로 데이터 인풋을 표시하도록 지정해요. 메서드는 엔티티 클래스의public또는protected메서드여야 하며,UniTask<AutoCompleteList>를 반환해야 해요. 메서드는 비동기일 수 있어요. 만약forceSelection이true면 사용자는 드롭다운 리스트에서만 값을 선택할 수 있으며, 선택하지 않으면null값이 할당돼요.using System.Linq;
[DataInput]
[AutoComplete(nameof(AutoCompleteVipName), forceSelection: true)]
public string VipName = "Alice";
protected async UniTask<AutoCompleteList> AutoCompleteVipName() {
return AutoCompleteList.Single(vipNames.Select(name => new AutoCompleteEntry {
label = name, // This is what the user sees
value = name // This is what the field stores
}).ToList());
}
private List<string> vipNames; // Entity-controlled runtime data
// Some other code should update the vipNames list팁자동완성 리스트는 컴파일 시점에 알 수 없는 옵션 목록을 제공할 때 유용해요. 예를 들어, 디렉터리에서 파일 목록을 제공하거나, 원격 서버에서 이모티콘 목록을 제공할 때 사용할 수 있어요. Warudo의 내부 노드 및 에셋에서도 매우 자주 사용돼요!
[MultilineInput]:데이터 타입이string이어야 해요. 여러 줄로 구성된 텍스트 입력 필드로 데이터 인풋을 표시하도록 지정해요.[CardSelect]: 데이터 타입이 열거형이어야 해요. 카드 선택 리스트로 데이터 인풋을 표시하도록 지정해요. (예: "Camera → Control Mode").public enum Color {
[Label("#00FF00")]
[Description("I am so hot!")]
Red,
[Label("#00FF00")]
[Description("I am so natural!")]
Green,
[Label("#0000FF")]
[Description("I am so cool!")]
Blue
}
[DataInput]
[CardSelect]
public Color MyColor = Color.Red;
열거
열거형 타입에서 [Label(string label)] 속성을 사용해 열거형 값의 에디터 라벨을 커스터마이징 할 수 있어요. 예를 들어:
public enum Color {
[Label("#FF0000")]
Red,
[Label("#00FF00")]
Green,
[Label("#0000FF")]
Blue
}
속성 섹션에서 설명한 것처럼 [Description(string description)] 과 [Icon(string icon)] 속성을 사용해 열거형 입력을 카드 목록으로 표시할 수도 있어요.
icon은 단일 SVG 요소여야 해요(예: <svg>...</svg>). 예를 들어:
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 512 512">
<path>...</path>
</svg>
에셋 레퍼런스
에셋 레퍼런스는 에셋, 노드, 그리고 플러그인이 아닌 구조화된 데이터에서만 사용할 수 있어요.
데이터 입력을 사용해 현재 씬에서 다른 에셋을 참조할 수 있어요. 예를 들어, 아래 코드는 CharacterAsset을 참조하는 데이터 입력을 정의해요:
[DataInput]
public CharacterAsset MyCharacter;
에디터에서 사용자는 드롭다운 목록에서 캐릭터 에셋을 선택할 수 있어요:

그 후 참조된 에셋의 포트와 트리거에 접근할 수 있어요:
[FlowInput]
public Continuation Enter() {
if (MyCharacter.IsNonNullAndActive()) {
MyCharacter.EnterExpression("Joy", transient: true); // Make the character smile!
}
return Exit;
}
에셋이 null이거나 비활성 상태인지 확인하려면 asset.IsNullOrInactive()를 사용하고, 활성 상태인 경우 asset.IsNonNullAndActive()를 사용할 수 있어요..
에셋을 드롭다운 목록에서 필터링하고 싶다면 어떻게 해야 할까요? [AssetFilter(string methodName)] 속성을 사용해 씬에 있는 에셋을 필터링할 메서드를 지정할 수 있어요. 메서드는 해당 에셋 타입의 파라미터를 받아 bool 값을 반환하는 public 또는 protected 메서드여야 해요. 예를 들어:
[DataInput]
[AssetFilter(nameof(FilterCharacterAsset))]
public CharacterAsset MyCharacter;
protected bool FilterCharacterAsset(CharacterAsset character) {
return character.Active; // Only show active characters
}
프로그래밍 방식으로 데이터 인풋 액세스
엔티티가 있다고 가정해볼게요. 데이터를 읽는 두 가지 방법이 있어요:
- 데이터 인풋 필드에 직접 접근하기. 예를 들어,
public int MyNumber = 42;라는 퍼블릭 데이터 인풋 필드를 가진 노드가 있다면node.MyNumber를 사용해MyNumber의 값을 직접 읽을 수 있어요. T GetDataInput<T>(string key)또는object GetDataInput(string key)메서드를 사용하기. 이 메서드는 모든 엔티티에서 사용할 수 있으며, 지정된 이름의 데이터 인풋 값을 반환해요. 예를 들어.MyNumber라는 데이터 인풋을 가진 노드가 있을 때,node.GetDataInput<int>("MyNumber")또는 스타일적으로 선호되는node.GetDataInput<int>(nameof(node.MyNumber))를 사용해MyNumber값을 읽을 수 있어요.
포트의 키는 필드 이름과 동일하며, 포트가 동적으로 추가된 경우는 제외됩니다(동적 포트 참조).
두 번째 방법은 데이터를 동적으로 접근해야 할 때 유용해요. 예를 들어, 문자열 변수에 따라 데이터를 접근해야 하는 경우에요. (마찬가지로 동적 포트참조.) 그 외에는 두 방법에 큰 차이가 없어요.
마찬가지로, 데이터 인풋에 값을 쓰기 위해서는 데이터 인풋 필드에 직접 값을 할당하거나 void SetDataInput<T>(string key, T value) 메서드를 사용할 수 있어요. 예를 들어, MyNumber라는 데이터 인풋의 값을 설정하려면 node.MyNumber = 42 또는 스타일적으로 선호되는 node.SetDataInput("MyNumber", 42, broadcast: true) 또는 node.SetDataInput(nameof(node.MyNumber), 42, broadcast: true)을 사용할 수 있어요.
SetDataInput(nameof(MyNumber), 42, broadcast: true) 대신 다음과 같이 쓸 수 있어요:
MyNumber = 42;
BroadcastDataInput(nameof(MyNumber));
하지만 이 경우에는 두 번째 방법을 사용하는 것이 깅력하게 권장되는데, 이유는 두 가지에요:
- 데이터 인풋의 변경 사항이 관찰자에게 통지된다는 점.
broadcast파라미터를true로 설정하면, 변경 사항이 에디터에 전송돼요. 그렇지 않으면BroadcastDataInput(string key)를 사용해 수동으로 에디터에 변경 사항을 전송해야 해요.
첫 번째 방법은 다음과 같은 경우에만 사용해야 해요:
- 매우 자주 데이터를 업데이트하지만, 매번 에디터에 변경 사항을 전송할 필요가 없을 때. 즉, 가끔
BroadcastDataInput(string key)를 호출해 성능을 절약할 수 있어요. - 데이터 인풋의 관찰자에게 변경 사항을 통지하고 싶지 않을 때. 이는 드문 경우에요.
데이터 아웃풋 포트
데이터 아웃풋 포트는 다른 노드에 데이터를 제공하는 데 사용돼요. 데이터 아웃풋은 노드 하위 클래스에서 [DataOutput] 속성으로 정의된 공개 메서드로 정의돼요. 이 메서드는 void가 아닌 타입을 반환해야 해요. 아래는 예시예요:
[DataOutput]
public int RandomNumber() {
return Random.Range(1, 100); // Return a random number between 1 and 100
}
데이터 아웃풋은 일부 데이터 인풋 속성을 지원해요: [Label], [HideLabel], [Description], [HiddenIf], [DisabledIf].
플로우 인풋 포트
플로우 인풋 포트는 다른 노드로부터 플로우 신호를 받아 특정 작업을 실행하는 데 사용돼요. 플로우 인풋은 노드 하위 클래스에서 [FlowInput] 속성으로 정의된 공개 메서드로 정의되며, 해당 메서드는 Continuation이라는 플로우 아웃풋을 반환해야 해요. 다음은 예시예요:
[DataInput]
public bool FlowToA = true;
[FlowInput]
public Continuation Enter() {
return FlowToA ? ExitA : ExitB; // If FlowToA is true, trigger ExitA; otherwise, trigger ExitB
}
[FlowOutput]
public Continuation ExitA;
[FlowOutput]
public Continuation ExitB;
플로우 인풋은 일부 데이터 인풋 속성을 지원해요: [Label], [HideLabel], [Description]. 메서드가 Enter()로 명명되고 [Label] 속성이 없으면, 에디터의 언어로 'Enter'라는 단어로 자동 설정돼요.