티스토리 뷰
[Unity] NPC와 충돌감지하기 에서 이어집니다.
⭐️ 목표 ⭐️
1. NPC와 플레이어가 만나면 대화창 (DialogPanel) 이 활성화 되도록한다.
2. 텍스트를 한글자씩 타이핑하는 효과를 낸다 with 코루틴
[1] NPC와 플레이어가 만나면 DialogPanel 이 활성화 되도록
대충 이미지와 텍스트를 자식으로 넣어둔 Panel을 만들었고
Panel 의 태그를 DialogPanel 이라고 해놨습니다.
그리고 Panel을 비활성화 해뒀습니다.
그리고 NPCAreaController 에서
충돌을 감지한 대상이 Player라면 DialogPanel을 활성화시키는 코드를 작성해줬습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NPCAreaController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
GameObject panel = GameObject.FindWithTag("DialogPanel");
if (panel == null)
{
return;
}
panel.SetActive(true);
};
}
}
저는 FindWithTag 를 사용해주었는데요!
Find 처럼 게임오브젝트의 이름으로 찾는 메소드도 있습니다.
근데 FindWithTag 랑 Find 모두 활성화된 오브젝트만 찾을 수 있다고 합니다!
비활성화된 오브젝트를 찾고 싶은 경우, 활성화된 부모를 찾아서 자식을 찾는 형식으로 접근해야한다고 하네요 (참고: 비활성화 된 GameObject찾기)
그래서 스크립트의 onTriggerEnter 메소드를 아래와 같이 수정해줘야합니다.
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
GameObject panel = GameObject.FindWithTag("Canvas").transform.Find("DialogPanel").gameObject;
if (panel == null)
{
return;
}
panel.SetActive(true);
};
}
근데 Swift의 옵셔널 체이닝이랑 다르게
C#은 GameObject.FindWithTag("Canvas") 에서 실패하면 panel이 null로 할당되는게 아니라 NullReferenceException이 납니다. 그렇다고 게임이 종료되지는 않고 콘솔에만 찍히더라구요!
null 체크를 어디까지 해야되는 지 모르겠는데,,, 크래쉬는 안나니까 우선 이 정도만 하려고 합니다.
(사실 transform.Find("Panel") 부분도 null 체크 해줘야될 것 같아요)
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
GameObject canvas = GameObject.FindWithTag("Canvas");
if (canvas == null)
{
return;
}
Transform transform = canvas.transform; // The Transform Attached to this GameObject
GameObject panel = transform.Find("Panel").gameObject;
if (panel == null)
{
return;
}
panel.SetActive(true);
};
}
아무튼 NPC Area에 들어가면 Panel 이 활성화 잘 됩니다.
조이스틱이 거슬려서 내리고 싶다! 고 하면 현재 구조가 이렇게 되어있으니
JoySticsk를 비활성화 시키는 코드를 함께 추가해주면 됩니다.
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
GameObject canvas = GameObject.FindWithTag("Canvas");
if (canvas == null)
{
return;
}
Transform transform = canvas.transform; // The Transform Attached to this GameObject
GameObject joysticksCanvas = transform.Find("UI_Canvas_StarterAssetsInputs_Joysticks").gameObject;
GameObject panel = transform.Find("Panel").gameObject;
if (joysticksCanvas == null || panel == null)
{
return;
}
joysticksCanvas.SetActive(false);
panel.SetActive(true);
};
}
[2] 타이핑 되는 텍스트로 만들기
저는 이 유튜브 영상을 참고해줬습니다.
# DialogController 만들기
DialogController를 만들고 Panel에 붙여줍니다.
그리고 Text를 에디터에서 주입받울 수 있게 해주려고 dialogText를 추가했어요
Text 타입을 사용하려면 UnityEngine.UI를 임포트 해야합니다.
위에서 처럼 Find로 자식을 찾을 수 도 있지만, 이 방법이 더 간단하고 깔끔해서 이렇게 해볼게요!
그리고 유니티 에디터로 돌아가보면
이렇게 Text 를 주입받을 수 있는 필드가 생긴 것을 볼 수 있습니다.
DialogText를 필드에 넣어줍니다.
DialogText는 이거에요!
그리고 게임플레이하고 콘솔을 보면 우리가 만든 스크립트가 필드에 넣어준 텍스트에 잘 접근하고 있는 것을 확인할 수 있습니다.
# 코루틴 살펴보기
그리고 코드를 작성하려면 코루틴에 대해서 알아야합니다.
간단히 정리하자면..!
- 시간이 지남에 따라 점진적으로 업데이트 되어야하는 애니메이션, 이벤트를 작업해야할 때,
update 함수 (매 프레임 마다 호출됨) 보다 코루틴(coroutine)을 사용하는 것이 더 편하다.
- 코루틴은 실행을 일시 중지하고 Unity에 제어 권한을 반환한 후 다음 프레임에서 중단했던 위치에서 계속할 수 있는 함수다.
- 코루틴은 IEnumerator 반환 타입과 body 어딘가에 yield 반환문이 포함된 함수다.
- yield return null 라인은 실행이 일시 중지되고 다음 프레임에서 다시 시작되는 지점이다.
- 기본적으로 코루틴은 프레임이 생성된 후 다시 시작되지만 WaitForSeconds를 사용하여 시간 지연을 도입할 수 있다.
- 코루틴을 사용하려면 StartCoroutine 함수를 사용해야한다.
- StopCoroutine과 StopAllCoroutines를 사용하여 코루틴을 중지할 수 있다.
- SetActive(false)로 인해 연결된 게임 오브젝트가 비활성화될 때에도 코루틴이 중지된다.
# 코루틴 테스트해보기
DialogController를 아래와 같이 작성하고 게임플레이를 해볼까요?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DialogController : MonoBehaviour
{
public Text dialogText;
// Start is called before the first frame update
void Start()
{
StartCoroutine(Typing(dialogText.text));
}
// Update is called once per frame
void Update()
{
}
IEnumerator Typing(string text)
{
foreach (char letter in text.ToCharArray())
{
print(letter);
yield return new WaitForSeconds(1f);
}
}
}
그럼 1초마다 한글 자씩 프린트가 잘되는 것을 볼 수 있습니다.
# 타이핑 스크립트 작성하기
이제 드디어 타이핑하는 코드를 작성해봅시다.
Start에서 현재 dialogText를 empty로 만들어주고
하드코딩한 샘플텍스트를 0.1초 간격으로 나오게 하는 코드 입니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DialogController : MonoBehaviour
{
public Text dialogText;
// Start is called before the first frame update
void Start()
{
dialogText.text = "";
string sampleText = "안녕하세요 지니지니테스트님,\n반갑습니다 룰루라라";
StartCoroutine(Typing(sampleText));
}
// Update is called once per frame
void Update()
{
}
IEnumerator Typing(string text)
{
foreach (char letter in text.ToCharArray())
{
dialogText.text += letter;
yield return new WaitForSeconds(0.1f);
}
}
}
'🎨 > Unity' 카테고리의 다른 글
[Unity] NPC와 대화하기 (2) (0) | 2022.02.18 |
---|---|
[Unity] Xcode Simulator로 빌드하기 (0) | 2022.02.17 |
[Unity] NPC와 충돌감지하기 (0) | 2022.02.17 |
[Unity] Canvas 와 UI 오브젝트 (0) | 2022.02.17 |
[Unity] Skybox (0) | 2022.02.10 |
- Total
- Today
- Yesterday
- PencilKit
- Flutter Text Gradient
- 장고 Custom Management Command
- 플러터 싱글톤
- cocoapod
- flutter build mode
- ipad multitasking
- Django Firebase Cloud Messaging
- Sketch 누끼
- Dart Factory
- 장고 URL querystring
- github actions
- DRF APIException
- Python Type Hint
- 플러터 얼럿
- Django FCM
- 구글 Geocoding API
- METAL
- flutter 앱 출시
- SerializerMethodField
- Django Heroku Scheduler
- Flutter 로딩
- drf custom error
- flutter dynamic link
- Watch App for iOS App vs Watch App
- Flutter Spacer
- flutter deep link
- Flutter getter setter
- Flutter Clipboard
- ribs
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |