본문 바로가기
개발일지/게임개발

[유니티 게임 개발] 동방을 걷다 프로젝트 15 - 레이무 상애 엔딩 2024 05 30(PM 08:30)

by 라이티아 2024. 5. 31.

현재 듣고있는 곡

Wind God Girl

레밀리아 씬에 넣을가 싶은 노래

바이올린 연주가 인상깊다

 

 

 

상점에 엔딩 아이템, 반지를 추가해 보려 한다

그전에 먼저 버튼들을 정리해야 할 것 같다

 

현재 모든 버튼을이 따로 스크립트를 가지고 있는데, 굉장히 혼란스러운 방식으로 만들어 놨음을 알 수 있다

 

이를 해결하기 위해서 상점 버튼 매니저를 만들어서 관리하자

 

기능은 이미 구현되어 있으니 그대로 사용한다

 

public Button power;
    public Button defense;
    public Button dodge;

   
    public GameObject less_gold;
    // Start is called before the first frame update
    void Start(){
        power.onClick.AddListener(up_power);
        defense.onClick.AddListener(up_defense);
        dodge.onClick.AddListener(up_dodge);
    }
    public void up_power()
    {
        if(NPCManager.Instance.Gold >= 10){
            NPCManager.Instance.Gold -= 10;
            Gamemanager.Instance.power += 1;
        }
        else if(NPCManager.Instance.Gold < 10){
            less_gold.SetActive(true);
        }
    }

이런 식으로 연결해서 관리한다

 

 

이제 여기에 물건을 구입할때 효과음을 추가해 준다

사용할 효과음을 추가해준 뒤

 

public void up_power()
    {
        Soundmanager.Instance.Playsound("shop_buy");
        if(NPCManager.Instance.Gold >= 10){
            NPCManager.Instance.Gold -= 10;
            Gamemanager.Instance.power += 1;
        }
        else if(NPCManager.Instance.Gold < 10){
            less_gold.SetActive(true);
        }
    }

이렇게 효과음을 추가해준다

 

이렇게 여러 버튼들이 소리를 추가해 주면

상점에 좀더 활기가 생겼다

 

이제 엔딩 아이템인 반지를 추가해보자

 

 

여기에 결혼 반지를 추가해보자

 

 

 

랜덤 아이템 버튼을 죽이고 반지 구입 버튼으로 대체 해버린다

 

이제 생각해야 하는 매커니즘

 

1. 호감도 MAX되는 순간 bool 변수 true

2. bool변수 true일때 반지 버튼 활성화

 

이런 순서로 되야 하니, 반지 버튼을 관리하도록 버튼 매니저를 수정한다

    public Button ring;
   
    public GameObject _ring;

반지 구입 버튼을 버튼, 게임 오브젝트로 2개로 나눈다

 

void Update(){
        if(NPCManager.Instance.like >= 100){
            _ring.SetActive(true);
        }
    }

MAX 호감도라면 활성화 되도록 한 뒤

public void buy_ring(){
        if(NPCManager.Instance.is_ring == false && NPCManager.Instance.Gold >= 100){
            Soundmanager.Instance.Playsound("shop_buy");
            NPCManager.Instance.is_ring = true;
            NPCManager.Instance.Gold -= 100;
        }
    }

반지를 구입하면 반지 여부가 true가 된다

 

이를 이용해서 레이무에게 반지를 선물하는 이벤트의 key가 된다

 

호감도가 100 이하일때는 나오지 않다가

MAX이상이면 true가 되서 나온다

 

이제 플레이어가 반지가 상점에서 구입할 수 있게 되었다

 

 

마지막, 레이무와 만났을때

is_ring = true

상태라면 반지를 선물하여 엔딩으로 향하게 만들면 된다

 

 

 

이제 여기에 선물하기 버튼을 추가한뒤

 

반지 여부 bool 변수와 엮어주면 된다

 

하쿠레이 신사 UI를 관리하는 스크립트에 버튼을 추가한다

    public Button ringButton;
    public GameObject _ringButton;

 

그후 setactive를 설정한다

if(NPCManager.Instance.is_ring)
            _ringButton.SetActive(false);
        else
            _ringButton.SetActive(true);

update에 넣어주면 알아서 관리해주니 편하다

 

void give_ring()
    {
        currentLine = ending_line;
        DisplayNextSentence();
    }

엔딩 버튼 기능은 임시로 만들었다

 

 

매커니즘을 수정해야 할 것 같다

Update에 버튼 활성화를 넣어두니, 항상 활성화 되는 문제가 보인다

 

if (Sentence[currentLine, 5] == "1")
            {
                dialogueButton.gameObject.SetActive(true);
                exitButton.gameObject.SetActive(true);
                helpButton.gameObject.SetActive(false);
            }

txt매니저의 줄 끝 확인에 else if를 하나 더 걸치면 될 것 같다

 

if (Sentence[currentLine, 5] == "1")
            {
                dialogueButton.gameObject.SetActive(true);
                exitButton.gameObject.SetActive(true);
                helpButton.gameObject.SetActive(false);
            }
            else if(Sentence[currentLine, 5] == "1" && NPCManager.Instance.is_ring){
                dialogueButton.gameObject.SetActive(true);
                exitButton.gameObject.SetActive(true);
                helpButton.gameObject.SetActive(false);
                ringButton.gameObject.SetActive(true);
            }
            else
            {
                dialogueButton.gameObject.SetActive(false);
                exitButton.gameObject.SetActive(false);
                helpButton.gameObject.SetActive(false);
                ringButton.gameObject.SetActive(false);
            }

조건문을 걸쳐서 구현해준다

 

문제없이 잘 작동하고 있다

 

대화는 임시로 라인을 넣어놔서 그렇다

 

이제 엔딩씬을 구현해 보자

 

에라토호YM의 순애 엔딩을 참고를 많이 하도록 하겠다

엔딩씬을 만들어 줬다

 

이제 마지막 글자에 걸리면 씬을 이동 시켜서 엔딩을 볼 수 있게 하고, 크레딧을 내려보자

 

if(Sentence[currentLine, 9] == "1"){
                is_end = true;
            }
            if(Sentence[currentLine+1,2]!="end" && !is_end){
                currentLine++;
            }

대화씬 함수에 is_end가 true일때 대화가 더 진행되지 않도록 막아버린다

 

이렇게 해버리면 엔딩의 마지막 대사인

레이무 END (하쿠레이의 신랑)

에서 막혀버리게 된다

 

이렇게 막히면 UI위에 UI를 넣는 방식으로 엔딩을 만들어 주면 된다

 

이런 긴 사진을 오른쪽으로 천천이 이동시킬 예정이다

 

Vector2 sub = rect.anchoredPosition;
        if(sub.x <= 2200){
            sub.x += 0.3f;
            rect.anchoredPosition = sub;
        }

rectpos값을 이동시키면 된다

 

if(color.a <= 1){
            color.a += 0.3f;
            image.color = color;
        }

투명도도 조절해서 좀 더 멋지게 표현해 준다

 

이제 이 위에 텍스트를 얻어주면 된다

 

 

 

현재까지는 이런 느낌이다

 

이제 위에 텍스트를 추가해주면 된다

 

 

void Start()
    {
        // Start the coroutine to handle the text display and fading
        StartCoroutine(DisplayText());
    }

    IEnumerator DisplayText()
    {
        while (line <= 9)
        {
            // Set the text based on the current line
            switch (line)
            {
                case 1:
                    Text.text = "한 낮의 하쿠레이 신사";
                    break;
                case 2:
                    Text.text = "신사의 툇마루에는 평소와 같이\n빗자루를 기대어 세워져 있고";
                    break;
                case 3:
                    Text.text = "낙원의 무녀가 뒤에서\n차를 훌쩍거리고 있다";
                    break;
                case 4:
                    Text.text = "그 무릎 위에는\n당신이 머리를 올리고\n조용히 숨소리를 내고 있다";
                    break;
                case 5:
                    Text.text = "레이무는 당신의\n얼굴을 들여다 보며\n가볍게 입맞춤을 했다";
                    break;
                case 6:
                    Text.text = "평온 속에서\n시간이 조용히 지난다";
                    break;
                case 7:
                    Text.text = "당신은 문득 눈을 떠\n 레이무와 눈을 맞춘다";
                    break;
                case 8:
                    Text.text = "그저 평온한 나날들이다";
                    break;
                case 9:
                    Text.text = "Ending No.1 (레이무 엔딩)";
                    break;
            }
            if(line != 9){
                yield return StartCoroutine(FadeTextToFullAlpha(1f, Text));
                yield return new WaitForSeconds(2f);
                yield return StartCoroutine(FadeTextToZeroAlpha(1f, Text));
                yield return new WaitForSeconds(2f);
                line++;
            }
        }
    }

    public IEnumerator FadeTextToFullAlpha(float t, TextMeshProUGUI text)
    {
        text.color = new Color(text.color.r, text.color.g, text.color.b, 0);
        while (text.color.a < 1.0f)
        {
            text.color = new Color(text.color.r, text.color.g, text.color.b, text.color.a + (Time.deltaTime / t));
            yield return null;
        }
    }

    public IEnumerator FadeTextToZeroAlpha(float t, TextMeshProUGUI text)
    {
        text.color = new Color(text.color.r, text.color.g, text.color.b, 1);
        while (text.color.a > 0.0f)
        {
            text.color = new Color(text.color.r, text.color.g, text.color.b, text.color.a - (Time.deltaTime / t));
            yield return null;
        }
    }

 

한문단씩 끝어서 보이도록 만들어 줬다

 

이제 엔딩 크레딧을 만들어 주자

 

이런 크레딧을 올라가게 만들어 줄 것 이다

public class credit : MonoBehaviour
{
    public RectTransform rect;
    Vector2 first_pos = new Vector2(0, -1950);
    public Image image;
    Color color = new Color(1, 1, 1, 0);

    void Start()
    {
        rect.anchoredPosition = first_pos;
    }

    // Update is called once per frame
    void Update()
    {
        if (first_pos.y <= 1700)
        {
            first_pos.y += 0.1f;
            rect.anchoredPosition = first_pos;
        }
        if (color.a < 1)
        {
            color.a += 0.2f * Time.deltaTime;
            image.color = color;
        }
    }
}

코드 자체는 레이무 엔딩의 비슷한 버전이니 쉽다

 

이런 느낌이다

 

 

이제 엔딩을 합쳐주자

if(line == 9)
            {
                StartCoroutine(credit());
            }
public IEnumerator credit(){
        yield return new WaitForSeconds(5f);
        ending.SetActive(true);
    }

레이무 엔딩 텍스트에 연결해 주면 된다

 

 

 

 

 

 

드디어! 엔딩이 완성되었다