티스토리 뷰
[Unity] NPC와 대화하기 (1) 에서 이어집니다.
⭐️ 목표 ⭐️
- NPC와 대화 중에는 플레이어의 이동을 막는다.
- 다른 Object와 소통하는 다양한 방법을 알아본다. (SendMessage , UnityEvent )
플레이어의 이동을 막기 위해
moveSpeed를 0으로 설정해주겠습니다.
[1]
첫번째 방법은 NPCAreaController에 ThirdPersonController를 주입받아서 moveSpeed를 0으로 직접 설정해주는 방법입니다.
에디터에서 controller 필드에 플레이어를 설정해주면 됩니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using StarterAssets;
public class NPCAreaController : MonoBehaviour
{
public GameObject dialogPanel;
public GameObject joysticksCanvas;
public ThirdPersonController controller;
// 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")
{
controller.MoveSpeed = 0;
joysticksCanvas.SetActive(false);
dialogPanel.SetActive(true);
};
}
}
[2]
두번째 방법은 SendMessage 를 이용하는 방법입니다.
특정 게임오브젝트한테 message를 날리면
그 게임오브젝트에 붙어있는 스크립트가 message를 받아서 처리할 수 있습니다.
이렇게 NPCAreaController에서 Player한테 StopMoving이라는 메세지를 날리고
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using StarterAssets;
public class NPCAreaController : MonoBehaviour
{
public GameObject dialogPanel;
public GameObject joysticksCanvas;
// 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")
{
other.gameObject.SendMessage("StopMoving");
joysticksCanvas.SetActive(false);
dialogPanel.SetActive(true);
};
}
}
ThirdPersonController에서는 해당 메세지를 받아서 자신의 필드인 MoveSpeed 를 0으로 직접 세팅할 수 있습니다.
public class ThirdPersonController : MonoBehaviour
{
public float MoveSpeed = 2.0f;
...
public void StopMoving()
{
Debug.Log("StopMoving!");
MoveSpeed = 0;
}
}
[3]
세번째 방법은 UnityEvent 를 이용하는 방법입니다.
유니티이벤트에 여러 콜백을 등록해둘 수 있고 Invoke 를 콜하면 등록한 콜백들이 불리게 됩니다.
이 글의 설명을 참고하시면 좋습니다.
UnityEngine.Events 를 임포트해주고
onPlayerEntered 라는 UnityEvent를 만듭니다.
그리고 Player가 NPCArea 영역에 들어오면 해당 이벤트를 Invoke 합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
public class NPCAreaController : MonoBehaviour
{
public GameObject dialogPanel;
public GameObject joysticksCanvas;
public UnityEvent onPlayerEntered;
// 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")
{
onPlayerEntered.Invoke();
joysticksCanvas.SetActive(false);
dialogPanel.SetActive(true);
};
}
}
이렇게 스크립트를 작성해주고 유니티 에디터로 돌아와보면
추가한 유니티이벤트 필드가 나옵니다.
+ 를 누르고 Player를 끌어와준 후, Fuction에서
StopMoving을 선택해줍니다.
그럼 OnPlayerEntered에 대한 콜백을 등록한 것이고,
이 이벤트가 불리면 StopMoving 함수가 불리게 될 것입니다.
참고로 + 를 눌러서 다른 Object의 함수도 여러개 등록할 수도 있답니다!
저는 유알못이지만.. 유니티 하시는 분들은 이 방법을 가장 선호하시는 것 같아요!
(제가 봐도 이게 가장 깔끔하고 유지보수성이 좋은 것 같아요)
그래서 저도 NPC Controller 를 아래와 같이 바꾸고
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class NPCAreaController : MonoBehaviour
{
public UnityEvent onPlayerEntered;
// 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")
{
onPlayerEntered.Invoke();
};
}
}
직접 오브젝트를 참조해서 부르던 setActive 들을 모두 콜백으로 등록하도록 바꿔줬어요!
[ 기록 ]
원하는 스펙
1. NPC와 대화 중
- DialogPanel 보이게
- 모바일 조이스틱 안보이게
- 플레이어 움직일 수 없게
2. NPC와 대화가 끝나면
- DialogPanel 안보이게
- 모바일 조이스틱 보이게
- 플레이어 움직이게
DialogController를 아래처럼 작성해줬고
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
public class DialogController : MonoBehaviour
{
public Text dialogText;
public UnityEvent onDialogFinished;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void StartDialog()
{
dialogText.text = "";
string sampleText = "안녕하세요 지니지니테스트 님,\n무엇을 도와드릴까요?";
StartCoroutine(Typing(sampleText));
}
public void FinishDialog()
{
gameObject.SetActive(false);
StopAllCoroutines();
onDialogFinished.Invoke();
}
IEnumerator Typing(string text)
{
foreach (char letter in text.ToCharArray())
{
dialogText.text += letter;
yield return new WaitForSeconds(0.1f);
}
// TODO
yield return new WaitForSeconds(0.5f);
FinishDialog();
}
}
NPCController는 아래와 같고
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class NPCAreaController : MonoBehaviour
{
public UnityEvent onPlayerEntered;
// 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")
{
onPlayerEntered.Invoke();
};
}
}
ThirdPersonController에 이 함수를 추가해줬어요 (위에서 설명한 StopMoving은 지워줌)
public void SetMoveSpeed(float speed)
{
Debug.Log("setMoveSpeed");
MoveSpeed = speed;
}
콜백 등록은 이렇게 해줬습니다.
[ 모바일 이슈 대응 ]
모바일 조이스틱을 setActive(false) 했다가 다시 setActive(true) 로 바꾸면
마지막 드래그된 포지션으로 조이스틱이 가있고 플레이어 계속 움직이게 됩니다.
그래서 StarterAssets의 UIVirtualJoystick 스크립트에
Reset 함수를 추가해줬습니다.
조이스틱 UI의 포지션을 zero 로 해줘서 조이스틱 UI가 센터로 오게 해주고
OutputEvent도 zero로 날려줘서 플레이어를 멈춰주는 코드입니다.
public void Reset()
{
UpdateHandleRectPosition(Vector2.zero);
joystickOutputEvent.Invoke(Vector2.zero);
}
그리고 NPCAreaController 스크립트의 OnPlayerEntered 이벤트에
Reset을 콜백으로 등록해줍니다.
저는 Drag 해서 움직이는 툴인 Move이랑 Look 두개 다 등록해줬습니다.
그럼 이제 잘 동작합니다. (NPC와 대화가 끝나고 조이스틱이 디폴트 상태로 되어있고 플레이어가 멈춰있다면 성공임)
이거 말고 다른 방법이 있을 것 같아서 StarterAsset을 한참 살펴봤지만, 잘 모르겠네요 🥲
'🎨 > Unity' 카테고리의 다른 글
[Unity] Coroutines 코루틴 (0) | 2022.02.20 |
---|---|
[Unity] UnityWebRequest / JsonUtility (0) | 2022.02.18 |
[Unity] Xcode Simulator로 빌드하기 (0) | 2022.02.17 |
[Unity] NPC와 대화하기 (1) (0) | 2022.02.17 |
[Unity] NPC와 충돌감지하기 (0) | 2022.02.17 |
- Total
- Today
- Yesterday
- DRF APIException
- 플러터 얼럿
- Django Heroku Scheduler
- Django Firebase Cloud Messaging
- drf custom error
- flutter build mode
- 장고 Custom Management Command
- Sketch 누끼
- Django FCM
- Flutter getter setter
- Flutter 로딩
- flutter 앱 출시
- Dart Factory
- Watch App for iOS App vs Watch App
- flutter deep link
- ipad multitasking
- Python Type Hint
- PencilKit
- cocoapod
- 플러터 싱글톤
- ribs
- Flutter Clipboard
- 구글 Geocoding API
- github actions
- 장고 URL querystring
- Flutter Spacer
- METAL
- Flutter Text Gradient
- flutter dynamic link
- SerializerMethodField
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |