유니티 기초

코루틴

다모아 2023. 8. 8. 12:51

https://docs.unity3d.com/kr/2021.3/Manual/Coroutines.html

 

코루틴 - Unity 매뉴얼

코루틴을 사용하면 작업을 다수의 프레임에 분산할 수 있습니다. Unity에서 코루틴은 실행을 일시 정지하고 제어를 Unity에 반환하지만 중단한 부분에서 다음 프레임을 계속할 수 있는 메서드입니

docs.unity3d.com

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test
{
    public class HeroController : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {

        }

        // Update is called once per frame
        void Update()
        {

        }

        public void Move(Vector3 targetPosition)
        {
            this.transform.position = targetPosition;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Test;

public class Test_PlayerControlSceneMain : MonoBehaviour
{
    [SerializeField]
    private HeroController heroController;
    [SerializeField]
    private Image image;

    private float maxDistance = 100f;
    
    // Start is called before the first frame update
    void Start()
    {
        //this.Fade();
        this.StartCoroutine(this.CoFade());
        //이렇게 하지말고 위처럼 사용
        //this.CoFade();
    }

    // Update is called once per frame
    void Update()
    {
        //화면을 클릭하면 클릭한 위치로 Hero가 이동
        if(Input.GetMouseButtonDown(0))
        {
            //Ray를 만든다
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 2f);

            RaycastHit hit;
            if(Physics.Raycast(ray, out hit, maxDistance))
            {
                //충돌정보가 hit변수에 담김
                Debug.LogFormat("hit.point: {0}", hit.point);

                //this.heroGo.transform.position = hit.point;

                //Hero게임오브젝트를 이동
                this.heroController.Move(hit.point);
            }
        }
    }

    void Fade()
    {
        
        for (float f = 1f; f >= 0; f -= 0.1f)
        {
            Color c = this.image.color;
            Debug.Log(f);
            c.a = f;
            this.image.color = c;
        }
    }

    IEnumerator CoFade()
    {
        for (float f = 1f; f >= 0; f -= 0.01f)
        {
            Color c = this.image.color;
            Debug.Log(f);
            c.a = f;
            this.image.color = c;
            //다음프레임 시작
            yield return null;
        }
        
    }
}


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test
{
    public class HeroController : MonoBehaviour
    {
        private Vector3 targetPosition;
        private Coroutine moveRoutine;

        private float moveSpeed = 2f;
        // Start is called before the first frame update
        void Start()
        {

        }

        public void Move(Vector3 targetPosition)
        {
            //이동할 목표지점을 저장
            this.targetPosition = targetPosition;
            //이동시작
            if(this.moveRoutine != null)
            {
                //이미 코루틴이 실행중이다 -> 중지
                this.StopCoroutine(this.moveRoutine);
            }
            this.moveRoutine = StartCoroutine(CoMove());
        }
        private IEnumerator CoMove()
        {
            while (true)
            {
                //로직
                //방향을 바라봄
                this.transform.LookAt(this.targetPosition);
                //이동
                this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
                //목표지점과 나와의 거리를 잼
                float distance = Vector3.Distance(this.transform.position, this.targetPosition);
                Debug.Log(distance);
                //distance가 0이 될 수는 없다 가까워질 때 도착한 것으로 판단하자
                if (distance <= 0.1f)
                {
                    //도착
                    break;
                }
                yield return null; //다음 프레임 시작
            }
            Debug.Log("<color=yellow>도착!</color>");
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Test;

public class Test_PlayerControlSceneMain : MonoBehaviour
{
    [SerializeField]
    private HeroController heroController;
    [SerializeField]
    private Image image;

    private float maxDistance = 100f;
    
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        //화면을 클릭하면 클릭한 위치로 Hero가 이동
        if(Input.GetMouseButtonDown(0))
        {
            //Ray를 만든다
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 2f);

            RaycastHit hit;
            if(Physics.Raycast(ray, out hit, maxDistance))
            {
                //충돌정보가 hit변수에 담김
                Debug.LogFormat("hit.point: {0}", hit.point);

                //this.heroGo.transform.position = hit.point;

                //Hero게임오브젝트를 이동
                this.heroController.Move(hit.point);
            }
        }
    }
}