# 커스텀 동작 작성(C#)

사용하는 것 외에도 [내장 동작](https://docs.febucci.com/text-animator-unity/typewriter/wait-actions-when-typing)을(를) 스크립트(C#)로 직접 작성할 수 있습니다.

{% hint style="info" %}
반드시 읽어보세요 [고급 개념](/text-animator-unity/3.x-ko/writing-custom-classes/advanced-concepts.md) 페이지도.
{% endhint %}

***

## 커스텀 동작을 만드는 다양한 방법 <a href="#actions-base-class" id="actions-base-class"></a>

Text Animator 3.0부터는 프로젝트 요구에 따라 더 많은 유연성을 제공하는 다양한 방식으로 동작을 만들 수 있습니다.

### 컴포넌트로서 동작 생성하기

{% hint style="success" %}
컴포넌트로 생성된 동작은 씬 객체를 더 쉽게 참조할 수 있게 해줍니다
{% endhint %}

```csharp
[System.Serializable]
class ExampleActionComponent : TypewriterActionScriptable
{
    [SerializeField] float timeToWait;
    
    // 주요 로직은 여기, 
    
    // ...무상태로
    protected override IActionState CreateCustomState(ActionMarker marker, object typewriter)
        => new ExampleState(timeToWait);
        
    // ...또는 코루틴으로
    protected override IEnumerator PerformAction(TypingInfo typingInfo)
    {
        // yield return ...
    }
}
```

### 스크립터블 오브젝트로서 동작 생성하기

{% hint style="success" %}
스크립터블오브젝트로서의 동작은 씬이 로드되어 있지 않아도 재사용 및 참조할 수 있습니다
{% endhint %}

```csharp
[System.Serializable]
[CreateAssetMenu(menuName = "Create Example Action")]
class ExampleActionScriptable : TypewriterActionScriptable
{
    [SerializeField] float timeToWait;
    
    // 주요 로직은 여기...
    
    // ...무상태로
    protected override IActionState CreateCustomState(ActionMarker marker, object typewriter)
        => new ExampleState(timeToWait);
        
    // ...또는 코루틴으로
    protected override IEnumerator PerformAction(TypingInfo typingInfo)
    {
        // yield return ...
    }
}
```

{% hint style="warning" %}
추신: 프로젝트 뷰에서 동작 ScriptableObject를 생성하고, 이를 동작 데이터베이스에 추가하는 것을 잊지 마세요.
{% endhint %}

***

## 동작 로직을 구현하는 다양한 방법 <a href="#actions-base-class" id="actions-base-class"></a>

동작의 핵심 로직을 어떻게 작성할지 결정할 수 있습니다.&#x20;

* 코루틴(IEnumerator) 내부에서, 또는
* 별도의 "틱" 메서드(동작을 계속 실행해야 하는지 또는 완료되었는지 반환하는)로.

시작하려면 올바른 네임스페이스를 임포트하세요:

<pre class="language-csharp"><code class="lang-csharp"><strong>using Febucci.TextAnimatorForUnity.Actions;
</strong><strong>using Febucci.TextAnimatorCore.Typing;
</strong>using UnityEngine;
</code></pre>

### 코루틴 만들기 <a href="#actions-base-class" id="actions-base-class"></a>

코루틴을 작성하는 것은 꽤 간단합니다!&#x20;

예를 들어, TypewriterAction 클래스(컴포넌트든 스크립터블이든) 내부에서 PerformAction 메서드를 오버라이드하면 됩니다:

```csharp
[SerializeField] AudioSource source;

protected override IEnumerator PerformAction(TypingInfo typingInfo)
{
    if (source != null && source.clip != null)
    {
        source.Play();
        yield return new WaitForSeconds(source.clip.length);
    }
}
```

### 무상태(stateless) 동작 만들기 <a href="#actions-base-class" id="actions-base-class"></a>

반면 무상태 동작을 만들려면 **IActionState** 를 상속하는 커스텀 구조체를 만들고(이 경우: 타입라이터가 진행되기 전에 몇 초 동안 대기하는 동작을 수행함) 다음과 같이 작성해야 합니다:

```csharp
struct ExampleState : IActionState // <--- 반드시 이것을 상속해야 함
{
    float timePassed;
    readonly float timeToWait;
    public ExampleState(float timeToWait)
    {
        timePassed = 0;
        this.timeToWait = timeToWait;
    }
    
    public ActionStatus Progress(float deltaTime, ref TypingInfo typingInfo)
    {
        // 경과 시간을 증가시킵니다
        timePassed += deltaTime;
        
        // 시간에 따라 계속할지 멈출지 결정합니다
        return timePassed >= timeToWait
            ? ActionStatus.Finished
            : ActionStatus.Running;
    }
    
    public void Cancel()
    {
        // 수정할 때 이걸 사용하세요 
    }
}
```

그런 다음 Action 클래스 내부에서 CreateCustomState 메서드를 오버라이드하여 이 구조체를 인스턴스화할 수 있습니다(여기서 본 것처럼 [#actions-base-class](#actions-base-class "mention")).

```csharp
protected override IActionState CreateCustomState(ActionMarker marker, object typewriter)
        => new ExampleState(timeToWait);
```

### 속성 <a href="#attributes" id="attributes"></a>

* 그 `마커` 매개변수는 태그에 대한 유용한 정보를 포함합니다. 예를 들어 ID나 함께 전달되는 매개변수가 있는지 여부(예: `<playSound=02>`).
* 그 `typewriter` 는 현재 동작을 수행하고 있는 Typewriter 컴포넌트 또는 AnimatedLabel을 참조합니다
* 그 `typingInfo` 에는 현재 타이핑 속도(수정할 수 있음)와 타입라이터 내부에서 경과한 시간과 같은 정보가 포함되어 있습니다.

***

{% hint style="success" %}
끝! 이 간단한 절차로 원하는 모든 커스텀 동작을 추가할 수 있습니다.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.febucci.com/text-animator-unity/3.x-ko/writing-custom-classes/c-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
