보스씬 넘어가기 연습 - 특정 위치가면 씬전환+fade out
2023. 8. 12.

아이템을 장착한 뒤에 보스씬으로 넘어가는 장면을 구현하기 위해 다음과 같은 코드를 추가하였다.

Main수정

-처음에 if문 내에 그냥 함수로 호출을 하니까 동작하지 않아 update문으로 빼보았다. 그랬더니 동작은 하는데 null값때문에 문제가 발생해 코루틴 함수로 작성하여 불러왔다.(nextScene은 포탈이 생긴 후 값을 저장하기 때문에 if문 밖으로 빼면 값이 없기 때문이다. )

포탈과 일정 거리가 되면 씬 전환

-fade out을 넣어줌

-canvas설정. Image추가 후 dim으로 이름을 바꾼다. 화면 설정 변경

-코드 수정

using System;
using System.Collections;
using System.Collections.Generic;
using Test3;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

namespace Test3
{
    public class Test_CreatePortalSceneMain : MonoBehaviour
    {
        [SerializeField]
        private MonsterGenerator monsterGenerator;
        private MonsterController monsterController;
        private ItemGenerator itemGenerator;
        private ItemController itemController;
        private HeroController heroController;
        private List<MonsterController> monsterList = new List<MonsterController>();
        private List<ItemController> itemList = new List<ItemController>();
        private float maxDistance = 100f;
        [SerializeField]
        private GameObject portalPrefab;
        [SerializeField]
        private GameObject heroPrefab;
        private float distance;
        private Transform nextScene;
        private Coroutine routine;
        private System.Action onFadeOutComplete;
        [SerializeField]
        private Image dim;
        // Start is called before the first frame update
        void Start()
        {
            this.monsterGenerator = GameObject.FindObjectOfType<MonsterGenerator>();
            this.monsterController = GameObject.FindObjectOfType<MonsterController>();
            this.itemGenerator = GameObject.FindObjectOfType<ItemGenerator>();
            this.itemController = GameObject.FindObjectOfType<ItemController>();
            this.heroController = GameObject.FindObjectOfType<HeroController>();
            
            MonsterController turtleController = this.monsterGenerator.Generate(GameEnums.eMonsterType.Tutle, new Vector3(-3, 0, 0));
            turtleController.onDie = (rewardItemType) =>
            {
                Debug.Log("거북이 죽음");
                var pos = turtleController.gameObject.transform.position;
                Destroy(turtleController.gameObject);
                this.CreateItem(rewardItemType, pos);
            };


            MonsterController slimeController = this.monsterGenerator.Generate(GameEnums.eMonsterType.Slime, new Vector3(0, 0, 3));
            slimeController.onDie = (rewardItemType) =>
            {
                Debug.Log("슬라임 죽음");
                Vector3 pos = slimeController.gameObject.transform.position;
                Destroy(slimeController.gameObject);
                this.CreateItem(rewardItemType, pos);
            };
            //만들어진 개체들을 그룹화 관리 
            //배열, 컬렉션 
            //동적 배열 
            this.monsterList.Add(turtleController);
            this.monsterList.Add(slimeController);
            Debug.LogFormat("this.monsterList.Count: {0}", this.monsterList.Count);
            //리스트의 요소를 출력 
            foreach (MonsterController monster in this.monsterList)
            {
                Debug.LogFormat("monster: {0}", monster);
            }



        }
        private bool hasPortal = false;

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

            //Ray로 클릭해서 몬스터 제거
            if (Input.GetMouseButtonDown(0))//마우스 좌클릭시
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                Debug.DrawRay(ray.origin, ray.direction * maxDistance, Color.red, 3f);//ray 그리기
                RaycastHit hit;// Raycast에서 out 키워드 사용을 위한 변수 선언        
                if (Physics.Raycast(ray, out hit, maxDistance)) //Ray 충돌검사
                {

                    Debug.LogFormat("col : {0}", hit.collider);
                    //충돌감지해서 몬스터 제거
                    monsterController = hit.collider.gameObject.GetComponent<MonsterController>();
                    if (monsterController != null)//몬스터 클릭시
                    {
                        this.monsterList.Remove(monsterController);
                        Debug.Log("HitMonster");
                        monsterController.HitDamage();

                        if (monsterList.Count <= 0)
                        {
                            if (this.hasPortal == false)
                            {
                                this.hasPortal = true;
                                this.CreatePortalAndHero();//Portal, Hero 생성
                                 this.nextScene = this.portalPrefab.transform;
                                if (this.routine != null)
                                {
                                    this.StopCoroutine(this.routine);//이미 코루틴이면 실행 중지
                                }
                               
                                //이벤트 추가
                                this.onFadeOutComplete = () =>//fadeout 끝나면
                                {
                                    SceneManager.LoadScene("Test_BossScene");
                                    Debug.Log("Play Next Scene");
                                };
                                this.routine = StartCoroutine(this.CoNextScene());
                            }

                        }
                    }
                   

                }
               
            }
            
                

            

        }

        
        [SerializeField]
        private GameObject swordPrefab;
        private void CreatePortalAndHero()
        {
            //몬스터가 다 제거되면 포탈생성         
            Instantiate(this.portalPrefab);
            this.portalPrefab.transform.position = new Vector3(6, 0, 10);
            //영웅 생성
            var heroGo = Instantiate(this.heroPrefab);
            this.heroController = heroGo.GetComponent<HeroController>();
            this.heroController.onTriggerItem = () => {

                Debug.Log("아이템 장착");

                //아이템 생성 
                //기존거 제거 
                this.heroController.UnEquipWeapon();
                var itemGo = Instantiate(this.swordPrefab, this.heroController.SwordTransform());
                this.heroController.Equip(itemGo);

            };
            this.heroPrefab.transform.position = new Vector3(this.transform.position.x + 1, 0, 0);

            this.hasPortal = true;
        }

        private void CreateItem(GameEnums.eItemType itemType, Vector3 position)
        {
            Debug.LogFormat("<color=yellow>CreateItem: {0}</color>", itemType);
            this.itemGenerator.GenerateItem(itemType, position);
        }

        private IEnumerator CoNextScene()
        {
            Color color = this.dim.color;
            while (true)
            {
                //Debug.LogFormat("portal position: {0}", nextScene.position);
                //  Debug.LogFormat("hero position: {0}", this.heroController.gameObject.transform.position);
                this.distance = Vector3.Distance(this.heroController.gameObject.transform.position, nextScene.position);
                Debug.LogFormat("Portal distance: {0}", distance);
                if (distance != 0 && distance < 5f)
                {
                    Debug.Log(distance);                 
                    {
                        color.a += 0.01f;
                        this.dim.color = color;
                        Debug.Log(this.dim.color.a);
                        if (this.dim.color.a >= 1)
                        {
                            break;
                        }                        
                    }                 
                }
                yield return null;
            } 
            Debug.LogFormat("fadeout complete!");
            this.onFadeOutComplete();   //대리자 호출 
           
        }
        
    }

}
myoskin