[Unity] 안 무서워!코린틴 해설

26022 단어 tech

개시하다


유니티에는 코르크소라고 불리는 기능이 있다.
매우 편리해서 잘 사용하면 상당히 간결하게 프로그램을 쓸 수 있다.
그러나 이'콜틴'에 대해서는 초학자가 존경하고 멀리하는 경우가 많다.
내가 유닛을 처음 기억했을 때도'유닛을 쓰는 프로그램은 힘들지만, 잘 모르는 걸 기억하고 싶지 않아 뇌를 펑크나게 한다'는 생각 때문에 피했다.
지금 생각해보면 너무 아쉬운 일인 것 같아요.
"잘 몰라서 코르크를 쓰지 않고 Update()로 강제로 쓴다"는 식으로 프로그램을 번거롭게 만들 수 있다.
코르크는 어떤 장소에서 사용하는지 명심하는 기초 위에서 적당히 사용하세요.

Update()와 연골소의 차이를 빠르게 이해하다


비교 표

Update()추수선소
1 어셈블리에서 사용할 수 있는 수량
오직 하나
아무리
처리 호출 방법
매번Update() 함수의 머리부터 실행
지난번에 중단된 곳에서 실행하다
Input 액세스
문제없다
문제없다
Riidbody 액세스
좋지 않다
좋지 않다
실행 시기
대체로 같다
대체로 같다
시작 시간
어셈블리가 Enable인 경우 각 프레임에 대해 계속 수행
호출StartCoroutine의 정시
끝날 타이밍
구성 요소 비활성화/폐기 후 중지
호출 StopCoroutine/구성 요소가 버려진 후 정지

각각의 용도


Update()

  • 프레임당 실행 필요
  • 추수선소

  • '일시 대기'같은 처리를 하고 싶을 때
  • 각기 다른 점을 설명하다


    각양각색의 기법

    Update()와 연골소는 쓰는 방법이 다르다.

    Update () 의 쓰기

    MonoBehaviour 계승된 클래스에서 Update() 이 함수만 정의합니다.
    그리고 Unity는 이 함수를 프레임마다 마음대로 호출할 것입니다.
    using UnityEngine;
    
    // MonoBehaviourを継承する必要あり
    public class SampleUpdate : MonoBehaviour
    {
        // void Update() という関数を定義すれば勝手にUnityが実行してくれる
        private void Update()
        {
            // ここに毎フレームやりたい処理を書く
        }
    }
    

    코르크


    서법


    코린틴의 작법은 좀 복잡하다.

  • 반환IEnumerator의 함수를 씁니다(함수 이름은 임의로 추가할 수 있습니다).이것은 연골소의 본체다.
  • 코르크 주체의 내용을 한 번 써야 한다yield return/yield break
  • 코르크를 시작할 때 사용StartCoroutine() 코르크 주체 호출
  • using System.Collections; // これ必要
    using UnityEngine;
    
    public class SampleCoroutine : MonoBehaviour
    {
        private void Start()
        {
            // StartCoroutine()の引数に、コルーチン関数を呼び出した結果を渡すと
            // コルーチンが起動する
            StartCoroutine(NantokaCoroutine());
        }
    
        // IEnumerator型の関数を定義すればコルーチンになる
        // 関数名は好きに付けて良い
        private IEnumerator NantokaCoroutine()
        {
            Debug.Log("Hello!");
    
            // コルーチンにおいては
            // yield return という特殊なreturnが使える
            yield return null;
    
            Debug.Log("World!");
    
            // yield break でコルーチンを終了する
            // (関数末尾に到達すれば勝手に止まるので、この場合は省略してもOK)
            yield break;
        }
    }
    

    여러 매개변수 추가 또는 시작


    또 코르크는 Update()와 달리 여러 개를 동시에 수행할 수도 있고 매개 변수에 맡길 수도 있다.
    실행을 시작하는 시간을 자유롭게 설정할 수 있기 때문에 필요한 시간에 필요한 양의 코르크를 가동할 수 있다.
    using System.Collections; // これ必要
    using UnityEngine;
    
    public class SampleCoroutine : MonoBehaviour
    {
        private void Start()
        {
            // 1秒後にHello!と表示
            StartCoroutine(WaitForSecondsCoroutine(1.0f, "Hello!"));
            
            // 2秒後にBye!と表示
            StartCoroutine(WaitForSecondsCoroutine(2.0f, "Bye!"));
        }
    
        private void OnCollisionEnter(Collision other)
        {
            // なにかに衝突したら0.5秒後に「Ouch!」と表示
            StartCoroutine(WaitForSecondsCoroutine(0.5f, "Ouch!"));
        }
    
        // 一定時間後にメッセージを表示するコルーチン
        private IEnumerator WaitForSecondsCoroutine(float seconds, string message)
        {
            // 指定秒数待つ
            yield return new WaitForSeconds(seconds);
    
            // メッセージ出力
            Debug.Log(message);
        }
    }
    

    추수선소의 정지


    또 코르크는 중도에 멈출 수 있다.
    결과를 저장하고 StartCoroutine() 멈추십시오.
    StopCoroutine()에서 정지된 코르크는 폐기된다.
    using System.Collections; // これ必要
    using UnityEngine;
    
    public class SampleCoroutine : MonoBehaviour
    {
        // 今実行中のコルーチン
        private Coroutine _currentCoroutine;
    
        // 1秒ごとに1mずつ動くコルーチン
        private IEnumerator MoveCoroutine()
        {
            while (true)
            {
                transform.position += Vector3.forward;
                yield return new WaitForSeconds(1);
            }
        }
    
        // 移動開始
        public void StartMove()
        {
            if (_currentCoroutine == null)
            {
                // 実行中のコルーチンが無いなら新しく起動
                _currentCoroutine = StartCoroutine(MoveCoroutine());
            }
        }
    
        // 移動停止
        public void StopCoroutine()
        {
            if (_currentCoroutine != null)
            {
                // 実行中のコルーチンを停止(破棄)
                StopCoroutine(_currentCoroutine);
                _currentCoroutine = null;
            }
        }
    
        /*
        
        ↓これ相当の処理は自動的に走るので書かなくてもOK
        (コンポーネント破棄時に勝手にコルーチンは止まる)
         
        private void OnDestroy()
        {
            // すべてのコルーチンを停止する
            StopAllCoroutines();
        }
        */
    }
    

    각자의 행위


    Update()는 항상 함수로부터 실행됩니다.


    우선 StopCoroutine(), 항상 함수 정의의 시작 (처음부터) 에서 실행됩니다.

    따라서'조건이 충족되면 다른 처리로 전환','일정 시간이 지나면 다른 처리'같은 것을 쓰려면 Update()만 쓰면 매우 번거로운 코드가 된다.

    추수선소는 멈출 수 있어요.


    연골소는 함수에서 중간에 멈추고 다음 프레임에서 계속 실행할 수 있습니다.

    요점은 "Update()"명령입니다.
    이것을 쓰면 '일시적 정지 처리' 를 조작할 수 있습니다.
    그리고 이것yield return이 되돌아오는 값에 따라'처리를 얼마나 정지해야 하는지'를 제어할 수 있습니다.
    반환값
    효과
    보태다yield return한 프레임만 기다리다
    다음 프레임부터 계속yield return null지정된 초 대기
    다음 작업은 지정된 초가 지난 프레임에서 시작합니다.yield return new WaitForSeconds(秒数)다음 대기 중 yield return new WaitForFixedUpdateFixedUpdate와 같은 시간에 다음 작업을 수행합니다.
    기타 코르크
    다른 코린 바틴이 끝날 때까지
    코르크에서 사용할 수 있는 다른 대상도 있지만, 우선 이것으로 설명을 끝냅니다.
    중요한 것은 코르크를 사용하면 처리를 잠시 멈출 수 있다는 것이다.

    실장예: 공격 버튼을 눌러 공격한 후 1초 동안 공격할 수 없는 예


    다음과 같은 처리가 있다고 가정해 보세요.
  • 공격 가능 상태이면 버튼을 누르는 순간 공격
  • 한 번 공격 후 1초 이상 기다리지 않으면 다음 공격을 할 수 없음
  • 간단한 흐름도로 이걸 쓰면 아래처럼 돼요.

    이 처리용FixedUpdate()과 연골소 두 개로 어느 것이 더 간단한지 비교해 봅시다.
    쓰다Update()는 "기억된 상태"라고 할 수 없으므로 "현재 상태"를 필드 변수로 정의해야 합니다.
    이 정도의 처리는 괜찮지만 하고 싶은 일이 더 복잡해지면Update() 처리하는 내용이 커지고 이 필드 변수의 수량도 점점 많아진다.
    따라서 쓰기Update()만 하면 복잡한 처리가 곧 한계에 이르렀다.
    using UnityEngine;
    
    public class WaitOnUpdate : MonoBehaviour
    {
        // 待ち時間
        private float _waitTime;
    
        // 待ち時間がゼロ以下なら攻撃可能
        private bool CanAttack()
        {
            return _waitTime <= 0;
        }
    
        private void Update()
        {
            // 待ち時間の計算
            if (_waitTime > 0) _waitTime -= Time.deltaTime;
    
            // Aボタンで攻撃する
            if (CanAttack() && Input.GetKeyDown(KeyCode.A))
            {
                Attack();
            }
        }
    
        // 攻撃処理
        private void Attack()
        {
            Debug.Log("Attack!");
    
            // 1秒間攻撃無効化
            _waitTime = 1.0f;
        }
    }
    

    연필로 쓰다


    같은 처리를 코르크소로 쓰면 이렇게 되는 느낌.
    using System.Collections;
    using UnityEngine;
    
    public sealed class WaitOnCoroutine : MonoBehaviour
    {
        private void Start()
        {
            StartCoroutine(InputCoroutine());
        }
    
        private IEnumerator InputCoroutine()
        {
            while (true)
            {
                if (Input.GetKeyDown(KeyCode.A))
                {
                    // 攻撃キーが押されたら攻撃したあと、1秒待つ
                    Attack();
                    yield return new WaitForSeconds(1);
                }
                else
                {
                    // 攻撃キーが押されてないなら1F待つ
                    yield return null;
                }
            }
        }
    
        // 攻撃処理
        private void Attack()
        {
            Debug.Log("Attack!");
        }
    }
    
    Update()와 무한순환의 조합이 좋아'한 번 처리를 한 후 잠시 기다렸다가 반복한다'는 처리가 이루어져 변수가 없다.
    그리고 아까의 흐름도와 비교해 주세요.
    나는 네가 흐름도의 내용이 기본적으로 코드에 고스란히 반영되었음을 알고 싶다.

    (1초 대기 1F 대기 코드에 직접 반영)
    이렇게 하면 연골소는'잠깐만'의 처리를 코드에 직접 반영할 수 있다.

    총결산

  • Update() 프레임당 실행
  • 코르크는 이전 프레임의 후속 실행 함수
  • 에서
  • 코르크를 사용하면 간단하게'잠시만'처리할 수 있다
  • 아마도 어떤 사람들은 콜친의 기법이 좀 복잡해서 손을 대기가 어렵다고 생각할 것이다.
    그러나 콜친yield return은 강제로 쓴 코드만 쓰는 것보다 압도적일 가능성이 있다.
    코르크를 사용해 본 적이 없는 사람은 이 기회를 틈타 꼭 시도해 보세요.

    (보충)


    외부 프로그램 라이브러리와 다소 복잡한 기능에 대해서는 "코르크를 능숙하게 사용할 수 있을 때까지 기다린다"고 추천했다.
    관리시간Update()이 좋다고 들었어요.
    "Update() 그걸로 하면 코르크를 안 써도 될 것 같아요."
    가끔 이런 소리가 들리지만 코르크 사용법을 모르는 상태에서는 이런 방법으로도 능숙하게 사용할 수 없다.
    추수선소UniRx,async/await를 비교해 보면 추수선소가 가장 간단하다.
    코르크는 복잡한 일을 할 수 없지만 행동이 간단하기 때문에 초보자도 사용할 수 있다.
    너무 무리하지 말고 먼저'연골소'부터 사용하고, 연골소의 기능이 부족하다고 느끼면 이들 도서관에 가서 사는 것을 권장한다.

    좋은 웹페이지 즐겨찾기