이렇게 훌륭한 강의를 이제서야 알게되었네요.ㅠㅜ 모든 영상에 좋아요 눌렀습니다. 좋은 강좌 만들어주셔서 너무 너무 감사합니다.ㅠㅜ 그리고 혹시 해당 강의와 퀘스트 시스템까지 모두 구현 성공했는데, npc와의 대화 도중이나 아니면 대화 마지막에 플레이어(주인공)도 말을 하게 하고 싶은데, 어떤 방법이 있을까요?ㅠㅜ
talkData = new Dictionary() 대화 하나에 여러 문장이 들어가있어서 string[] 배열을 사용한다고 하셨는데요 스프라이트도 portraitData = new Dictionary(); Sprite[] 배열으로 사용할수 있나요? 강의에서는 스프라이트는 배열로 안하셔서 이유가 궁금합니다.
버튼 클릭 시 파일 선택 윈도우 창이 나오고 사용자가 이미지를 선택하면 그것이 UI에 나타나게하는 로직을 공유해드립니다. using UnityEngine; using UnityEngine.UI; using System.IO; using System.Windows.Forms; public class ImageUpload : MonoBehaviour { public RawImage displayImage; public Button loadImageButton; private void Start() { loadImageButton.onClick.AddListener(OpenFileDialogAndLoadImage); } private void OpenFileDialogAndLoadImage() { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Image Files|*.png;*.jpg;*.jpeg;*.gif;*.bmp"; openFileDialog.Title = "Select an image file"; if (openFileDialog.ShowDialog() == DialogResult.OK) { string imagePath = openFileDialog.FileName; if (File.Exists(imagePath)) { byte[] imageData = File.ReadAllBytes(imagePath); Texture2D texture = new Texture2D(2, 2); texture.LoadImage(imageData); displayImage.texture = texture; } else { Debug.LogError("Image file not found: " + imagePath); } } } }
@@goldmetal 혹시 게임오버되서 씬 전환이 이뤄지게 하려면 다른 스크립트에 씬 전환 코드를 구현하고, Talk가 있는 스크립트에 쪽에 FindObjectOfType()를 해서 해봤는데 NullReferenceException이 뜨는데 혹시 다른 방법은 어떤것이 있는지 여쭤봐도 될까요??
먼저 초상화 데이터는 TalkManager의 portraitArr에 들어가 있어야 합니다. 이후에 대화마다 마지막에 콜론:을 붙이고 초상화 숫자를 써야하고 34:28 처럼 대화마다 초상화 데이터를 가지고 올 수 있도록 해야 합니다. 이렇게 되어있는지 확인하시고 게임 플레이할 때 대화가 나오고 하이어라키에서 초상화 이미지 오브젝트 선택 후에 Image 컴포넌트에 스프라이트가 잘 들어갔는지 확인해보세요.
33:44 스프라이트를 인스펙터창에서 말고 Asset에서 코드를 통해서 가져올려고 합니다. 찾아보니 addressable이 필요하다고 하는데, addressable을 건들려고 보니 현재 제 수준에서는 건들여도 이해하기 어렵더라고요. 혹시 addressable을 숙지할려면 어느 수준에 도달 후 공부를 시작해봐야할까요?
전에 구동 잘 되는 것을 확인하며 웃으며 저장을 누르고 껐는데... 스크립트는 그대로 저장이 되어 있지만, 씬의 작업과정이 저장이 안 되어있어서 npc, 게임메니저, 토크메니커 스크립트들을 다시 연결을 시도 했습니다. 그런데 대화 내용과 초상화를 연결한 부분에 오류가 있다고 콘솔창에서 떠요 ㅠㅠ 구동은 되는데 캐릭터가 지정된 타일 밖으로 튕겨져 나갑니다 ㅠㅠ IndexOutOfRangeException: Index was outside the bounds of the array. TalkManager..GenerateData() (at Assets.Scrips/TalkManager.cs.31) portraitData.Add(1000 + 0, portraitArr[0]);
@@goldmetal 으아아~~ 해결되었어요 ㅠㅠ 1. IndexOutOfRangeException: Index was outside the bounds of the array. - 말씀주신대로 토크메니저 스크립트를 또 다른데 짱박아두어서 생긴 결과더라구요 ㅠㅠ...감사해요..흑흑 2. 캐릭터가 맵 밖으로 튕기는 것 - 맵에 물리 컴포넌트 설정을 잘못한거 같아요 ㅠㅠ... 위에 것과 관련되어 문제가 있는 줄 알았어요...알고보니 별개의 문제였어요 ㅠㅠㅠ ㅠㅠ 감사해요...! 3일간 고민했었어요 흑흑 감사해요!
@@goldmetal 혹시 오브젝트를 마우스 클릭시 애니메이션이 나오도록 짜고 싶은데 GetMouseButton 함수를 이용하면 단순히 클릭하면 애니메이션 출력하게 만들수 있을까요?? 아니면 따로 변수라든지 함수를 작성해서 거기에 처리를 하고 GetMouseButton 함수에 집어넣어야 할까요 ㅠㅠ
txt파일에다가 대화를넣어서 불러오는 식으로 만들까 하는데 이렇게 하시는분들이 거의없는거같습니다. 예상대로라면 번역작업할때도 편하고 여러모로 좋을것같은데 많은분들이 이렇게 하지않는데엔 뭔가 문제가 있기때문인가요? 짧게 생각하기엔 베포할때 path문제가 좀 있을법도한데 조언 부탁드립니다.
골메님... a 라는 이름의 Dictionary에 100 이라는 ID를 등록하고 100이라는 ID에 "안녕하세요" 라는 문장을 넣었어요... 그리고 이차원배열로 return a[100][0]; 이렇게 작성하면 "안녕하세요"라는 문장이 반환되는건가요....? 아마도 되는것같은데 처음알았네요... Dictionary와 이차원배열이 연동된다는 말씀이신거죠...? 와 진짜 신기하네요.... 한가지 궁금한게 있는데 위에 리턴값에서 return a[100][0]; 를 하든 return a[100][1]; 을 하든 뒤의 배열은 상관없는거죠??? 궁금해요//..
정확히는 아닙니다. Dictionary 와 Array의 차이점을 잘 이해하셔야겠습니다. Dictionary는 Key방식이라서 100이라는 Key에다 "안녕하세요" Value를 연결하여 저장하는 것이고 배열은 100번째 칸에다가 "안녕하세요"를 저장한 셈이 됩니다. 그리고 배열은 Dictionary처럼 길이가 자유롭게 변경되지 않으니 미리 선언한 배열크기를 넘으면 에러가 발생하니 참고하시기 바랍니다.
@@진진자라지리지리-f4z Dictionary는 Key 방식, Array는 Index 방식입니다. Dictionary는 Key만 알면 value를 얻을 수 있고, Array는 칸 주소를 알아야 value를 얻을 수 있습니다. Array가 조금 불편하지만 for문으로 숫자를 돌려서 모든 칸을 순회할 수 있고, Dictionary는 그게 안됩니다.
@@goldmetal 이해는 되는데....계속 질문 죄송합니다...ㅠㅠㅠ Dictionary TakeData; TakeData = new Dictionary();해주면서 TakeData.Add(1000, new string[] { "안녕?", "반가워!" }); TakeData.Add(100, new string[] { "무슨일이지?" }); 라고 넣었어요. return TakeData[1000][0]; 한다면 "안녕?", return TakeData[1000][1]; 한다면 "반가워!", return TakeData[100][0]; 한다면 "무슨일이지?"가 반환이 되잖아요!! 그렇다는것은 이차원 배열과 dictionary 이 연결이 된다는 말인데 key값 그리고 인덱스 값 이렇게 다른데 어떻게 이게 가능한거죠?? 정말정말 죄송합니다 ㅠㅠ 진짜 존경합니다!!
골드메탈님 항상 양질의 콘텐츠를 만들어 주셔서 감사드립니다 ㅠ 질문이 있습니다 ! 플레이 모드에만 들어가면 초상화 이미지가 흐리게 나옵니다. 초상화에 사용할 픽셀 이미지를 픽셀퍼 유닛도 맞게 하고 no point에 none을 설정해주었는데도 플레이 모드에만 들어가면 흐리게 나옵니다 ㅠ 해결할 방법을 여쭙고 싶습니다 ㅠ
딕셔너리는 {key, value} 형태의 데이터를 저장하는 용도입니다. 20:45 시간대를 보시면 Add() 함수를 사용해서 {int, string[]} 형태로 데이터를 넣고 있지요. 레퍼런스 타입 (클래스 타입)은 선언 후 초기화 할때만 한번 new Dictionary()해주시면 됩니다. 이것은 Awake()에서 해주고 있는걸 확인 하실 수 있습니다.
1.talkManager에 float timer 변수를 두고 대화 중에는 Update에서 timer+= Time.deltaTime; 실행 ( if문을 통한 조건 ) 2. UI 는 슬라이더 하나를 만들고LateUpdate에서 value값을 timer / 최대시간초 이렇게 계산한 값을 넣어준다. 3. timer < 0 일 때 TalkEnd같은 함수를 호출하여 대화를 종료시킨다
골드메탈님! 질문이 있습니다 talkData.Add(1000, new string[] { "안녕*0", "이 곳에 처음 왔구나?*1" }); talkData.Add(100, new string[] { "평범한 나무 상자다."}); talkData.Add(200, new string[] { "누군가 사용했던 흔적이 있는 책상이다."}); talkData.Add(2000, new string[] { "여어*1","이 호수는 정말 아름답지?*0","사실 이 호수에는 무언가의 비밀이 숨겨져있다고 해*1"}); portraitData.Add(1000 + 0, portraitArr[0]); portraitData.Add(1000 + 1, portraitArr[1]); portraitData.Add(1000 + 2, portraitArr[2]); portraitData.Add(1000 + 3, portraitArr[3]); portraitData.Add(2000 + 0, portraitArr[4]); portraitData.Add(2000 + 1, portraitArr[5]); portraitData.Add(2000 + 2, portraitArr[6]); portraitData.Add(2000 + 3, portraitArr[7]); 이 부분이 잘 이해가 안돼요ㅠㅠ "여어*1" 여기서 1이 뭘 나타내는 건가요?
1.퀴즈문제, 선택지, 정답을 저장할 배열 변수 혹은 딕셔너리를 따로 선언 2. 각 배열 혹은 딕셔너리에 데이터를 추가 3. 대화 마지막에 퀴즈ID를 구분자 (&,* 등등 특수기호)와 함께 추가 4. 대화 함수 호출 시 퀴즈ID 데이터가 있을 때 대화 끝나고 퀴즈가 나오도록 구현 이정도로 해주시면 됩니다.
다수의 인물이 대화를 나누기 위해선 초상화를 담을 Image 오브젝트도 그만큼 배치해두어야 합니다. 그리고 하나의 대화에 참여하는 인물들의 데이터도 따로 저장해두어야 하구요. 대화가 시작할 때 이 데이터(배열이 좋겠네요)를 읽어서 Image에 초상화를 띄우면 되겠습니다.
골드메탈님 이번 강좌도 정말 잘 봤습니다 대화랑 초상화는 문제없이 잘 뜨는데 자꾸 콘솔에 NullReferenceException: Object reference not set to an instance of an object UnityEditor.Graphs.Edge.WakeUp ()(at :0) 어쩌고저쩌고 이런식으로 오류가 뜨네요. 무슨 문제일까요?
골드메탈님 안녕하세요!! 벌써 여기까지 따라왔습니다ㅠㅠ ♡ 12:00~ 까지 순조롭게 진행되다가, ObjectData 스크립트 만들며 새로운 부분을 덧붙여줬던 GameManager에서 [ error CS0246: The type or namespace name 'ObjData' could not be found(are you missing a using directive or an assembly reference?) ] 라는 오류가 떴는데 왜 이런문제가 생겼는지 아시나요...? 스크립트는 두번세번 확인했는데 대소문자 틀린 부분 없이 그대로 구현했습니다 ! 외부적인 Inspector 창 쪽에서 제가 뭔가 놓친걸까요..? 그리고 GameManager 의 Inspector 창에 Talk Panel, Talk Text, Scan Object 는 나오는데 Talk Manager 가 활성화되지 않네요... ಥ_ಥ 내일 처음부터 다시 따라가보겠습니다 ㅠㅠ! 너무너무 재밌습니다....!!!
안녕하세요 골드메탈님 항상 좋은강의 감사드립니다 ㅠ.ㅠ 이번 강의의 내용과는 맞지않은 질문입니다. 지형의 보더라인에 관하여 질문드립니다. 강의영상을 보면 플레이어가 있던 마을의 지형과 호수가 있는 지형 그리고 그 둘을 연결해주는 다리같은 역할을 하는 지형 총 3개로 보이고 그렇게 판단하였습니다. 궁금한점은 기본 강의에서 BorderLine을 생성하신 방법으로 지형을 비슷하게 다리가 있고 다른 곳으로 이동하는 지형을 만들었더니 BorderLine의 콜라이더가 사각형모양이라 텅텅빈 여분의 지형으로도 플레이어가 이동하는 경우가 발생합니다. BorderLine을 맵의 빈지형에 추가하여 그곳으로 못오게 하는 방법말고는 생각이 나지 않습니다. 이러한 방식말고 다른 방식으로 해결해야하는지 질문드립니다.
바깥 경계 외에 플레이어 이동을 막고 싶으면 바닥 타일맵을 덮는 새로운 타일맵을 만드시고 타일맵 콜라이더 추가하시면 됩니다. 그리고 막아야 되는 부분, 모양이 타일 하나보다 작거나 다른 모양이면 스프라이트 선택 후 인스펙터에서 Sprite Editor로 간 후, 창 왼쪽 위에 작은 메뉴 Physics Shape로 선택해서 콜라이더 모양을 잡아주시면 됩니다. 이 내용은 B17에서 다루었습니다. ruclips.net/video/f8ixw9IpnD8/видео.html
좋은 강의 감사합니다. 질문이 있습니다. 1. 코드 오류는 없고 마지막까지 따라한 상태입니다. 두 번째 NPC와 대화할 때 첫 번째 NPC의 첫 대사가 나오면서 대화 내용이 한줄씩 밀립니다. 혹시 알려주실 수 있으신가요? 2. 혹시 대화가 종료되자마자 다음씬으로 넘어가게 만들고 싶을 땐 어떤 함수를 쓰면 좋을지 알려주실 수 있으신가요?
@@goldmetal ㅠㅠ 덕분에 디버그 로그 찍어가며 해결했습니당.. 제가 나무 오브젝트에는 대사를 입력해주지 않아서 생긴문제였어요! 해당하는 오브젝트에 talkData.Add(400, new string[] { }); 이렇게 빈객체를 생성해주니까 오류가 안났습니당ㅎ.. 대사가 필요없는 객체는 굳이 Object 레이어로 할 필요가 없겠다 싶어서 layer를 Default로 설정하니 저렇게 객체 생성 코드 안써도 오류가 안났어요! 오늘도 배워갑니당... 총총..
메탈형님 강의 듣고 따라하던중 오류가 생겨 질문하나 남깁니다 캐릭터가 scanHit raycast 인식 범위를 벗어나도 대화키를 누르게되면 scanHit raycast 거리 밖임에도 마지막으로 인식했던 오브젝트와의 대사창이 나옵니다 나머지 기능들은 정상적으로 진행되는데 어떻게 해결하면 좋을까요??
사물의 내용을 데이터에 넣고 불러오는 부분 중에 NullReference Exception 오류가 떠서 클릭으로 그 부분에 갔는데 ObjData objData = scanObject.GetComponent(); 가 뜨던데 뭐가 문제인지 모르겠네요.. 혹시 뭐가 문제인지 아시나요? 코드도 계속 봐도 다 똑같은거 같은데 모르겠네요ㅠ
그 코드 위에 Debug.Log(scanObject); 해보세요. 아마 Null이 나올겁니다. scanObject가 왜 안담아졌는지 레이캐스팅 쪽을 보셔야겠습니다. 스캔할 대상의 레이어가 Object인지도 확인해보셔야 겠네요. ruclips.net/video/bZVa6C6vRBQ/видео.html
@@goldmetal 디버그를 썼는데 콘솔 창에 Flower, Water이 나오네요.. 여전히 null레퍼런스.. 이렇게 뜨지만... npc쪽은 레이어가 오브젝트여도 콘솔창에만 뜨고 null오류는 없지만 판넬은 안보이고 Grid안에 있는 꽃 연못들은 Layer가 Object여도 콘솔에는 뜨지만 null과 같이뜨고 판넬은 안보이네요... 오브젝트 레퍼런스가 인스턴스로 설정되지 않았다는게 도데체 왜 뜨는지... 제가 정리하느라 추가나 수정하는 부분 제외하면 진행 코드를 적은 순서대로 냅두긴 했는데 혹시 순서로 차이가 생기는 부분 있나요?
int, float, bool 같은 단일형 변수는 차지하고 있는 메모리 크기가 정해져 있기 때문에 C#컴파일러가 미리 알고 있으므로 그냥 선언합니다. 하지만 선언방법 혹은 데이터 추가로 인해 크기가 가변적인 배열, 리스트, 클래스 타입은 자유로운 메모리 공간에 변수를 두기 위해서 new 키워드 사용해주어야 합니다. (인스턴스) 이정도로만 이해하시고 더 깊이 들어가실려면 Stack 과 Heap 메모리타입에 대해 공부하셔야 합니다. 링크 첨부해드릴께요. nowonbun.tistory.com/67
초상화 부분을 다 하고 한번 실행해보려 했는데, ArgumentException: An item with the same key has already been added. Key: 1001 System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at :0) System.Collections.Generic.Dictionary`2[TKey,TValue].Add (TKey key, TValue value) (at :0) TalkManager.GenerateData () (at Assets/Scripts/TalkManager.cs:31) TalkManager.Awake () (at Assets/Scripts/TalkManager.cs:16) 재생버튼을 누르자마자 이런 오류가 뜨더군요. 구글링해서 나온 해결책도 안듣고요. 왜 이러는건지 알려주시면 감사하겠습니다.
주인공 대사가 나올때 (sprite 값이 특정값일때) public Image portrait image;(초상화 사진) 의 좌표값을 이동시키던중 game object와 다르게 Image는 transform.position이 먹히지 않았는데 일단 주인공 대사부분은 해결하긴 했지만, 한가지 의문점이 있습니다 스크립트 상에서 Canvas의 Image좌표값은 어떻게 바꿀 수 있을까요?
아.. 진짜 잘 나가다가 막판에 갑자기 대사창NPC Portrait이미지 안떠서 생고생했네요 ㅠㅠ 인스펙터창에 Obj Data의 Is NPC체크 풀린거 모르고 삽질을 ㅠㅠ 오늘은 오류없이 잘 되가나 싶어 신나가지고 막 따라하다가 플레이 누른 상태로 체크했었나봐요. ㅠㅠ 체크한 기억이 분명 있는데 풀려있는거 보니 ㅠㅠ 그럼 다음 장으로 넘어가겠습니다 ㅠㅠ
안녕하세요! 저는 talk index가 0->1->2->3이 순서대로 가지 않고, npc가 아닌 오브젝트는 0->2 순서대로 가고 npc와 대화할때는 1->3->5->2->4->6 이런 식으로 갑니다. 그래서 대화가 순차적으로 이루어지지 않아요ㅜㅜ 어떤 것 때문에 이런 상황이 발생할까요?ㅠㅠ 콘솔창에 에러 뜨는 것도 없어요ㅠㅠㅠ
portraitImg.sprite = TMS.GetPortrait(id, int.Parse(talkData.Split(':')[1])); 여기서 위의 코드를 주석처리하면 정상적으로 작동하지만 위의 코드를 넣으면 그 밑에 있는 코드들이 실행이 안되는거로 봐서는 코드에 문제가 있는 것 같은데 혹시 제가 NPC한테만 넣어둬서 isNPC라는걸 아예 안 넣어 뒀고 그래서 if(isNPC)이런것도 안 넣어 뒀는데 그것 떄문인가요?
@@goldmetal NullReferenceException: Object reference not set to an instance of an object TalkManager.GetPortrait (System.Int32 id, System.Int32 portraitIndex) (at Assets/Scripts/TalkManager.cs:34)라고 나오고 더블클릭하면 return portraitData[id + portraitIndex];의 맨 앞으로 갑니다.
@@goldmetal public Sprite GetPortrait(int id, int portraitIndex) { return portraitData[id + portraitIndex]; }로 되어 있어서 id와 portraitIndex도 선언 되어있습니다. Dictionary portraitData;에도 public을 하는 건가요?
안녕하세욥 분명 열심히 똑같이 코딩을 했는데 이런게 뜨네요. . . . . NullReferenceException: Object reference not set to an instance of an object GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/script/GameManager.cs:35) GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/script/GameManager.cs:26) playeraction.Update () (at Assets/script/playeraction.cs:72) 어떻게 해결 하나요?????????
NullReferenceException: Object reference not set to an instance of an object GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/script/GameManager.cs:26) GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/script/GameManager.cs:19) playeraction.Update () (at Assets/script/playeraction.cs:72)
Argument 2: cannot convert from 'UnityEngine.Sprite' to 'UnityEngine.Sprite[]' 라는 오류가 뜹니다. 어떻게 수정해야 할까요? 잠도 줄여가며 골메 님 영상으로 공부 중인데, 쉽게 설명해주시는데도 제겐 쉽지만은 않네요. 많은 노력이 필요할 것 같습니다. 항상 답변해주셔서 진심으로 감사드립니다!
실행하면 바로 일시정지가 되고 KeyNotFoundException: The given key was not present in the dictionary. System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0) Talkmanger.GenerateData () (at Assets/Scenes/Talkmanger.cs:26) Talkmanger.Awake () (at Assets/Scenes/Talkmanger.cs:14) 이런 오류가 뜨고 일시정지를 풀고 오브젝트한테 스페이스를 누르면 일시정지가 된 후 KeyNotFoundException: The given key was not present in the dictionary. System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0) Talkmanger.GetPortrait (System.Int32 id, System.Int32 portraitIndex) (at Assets/Scenes/Talkmanger.cs:44) GameManger.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Scenes/GameManger.cs:36) GameManger.Action (UnityEngine.GameObject scanObj) (at Assets/Scenes/GameManger.cs:19) playeraction.Update () (at Assets/Scenes/playeraction.cs:65) 이렇게 오류가 뜹니다.talkmanger에 오류가 있는것처럼 보이는데 talkmanger는 이렇게 작성을 하였고 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Talkmanger : MonoBehaviour { Dictionary talkData; //대화데이터 저장 Dictionary portraitdata; public Sprite[] portraitArr; void Awake() { talkData = new Dictionary(); portraitdata = new Dictionary(); GenerateData(); } // Update is called once per frame void GenerateData() { talkData.Add(1000, new string[] { "안녕?:0", "이 곳에 처음 왔구나?:1" }); //배열은 여러가지 문장이 들어갈 수도 있으니 //Add:함수를 사용하여 대화 데이터 입력 추가 talkData.Add(2000, new string[] { "와!:1", "이 호수는 정말 아름답지?:0", "사실 이 호수에는 무엇간의 비밀이 숨겨져있다고 해.:1"}); talkData.Add(100, new string[] { "평범한 나무상자다" }); talkData.Add(200, new string[] { "누군가 사용했던 흔적이 있는 책상이다" }); portraitdata.Add(1000 + 0, portraitdata[0]); portraitdata.Add(1000 + 1,portraitdata[1]); portraitdata.Add(1000 + 2,portraitdata[2]); portraitdata.Add(1000 + 3,portraitdata[3]); portraitdata.Add(2000 + 0, portraitdata[4]); portraitdata.Add(2000 + 1, portraitdata[5]); portraitdata.Add(2000 + 2, portraitdata[6]); portraitdata.Add(2000 + 3, portraitdata[7]); } public string GetTalk(int id, int talkIndex) { if (talkIndex == talkData[id].Length) return null; else return talkData[id][talkIndex]; //id로 대화 get talkIndex로 대화의 한 문장을 가져옴 } public Sprite GetPortrait(int id, int portraitIndex) { return portraitdata[id + portraitIndex]; } } gamemanger는 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GameManger : MonoBehaviour { public Talkmanger talkManger; public GameObject talkPanel; public Image PortraitImg; public Text talkText; public GameObject scanObject; public bool isAction; public int talkIndex; public void Action(GameObject scanObj) { scanObject = scanObj; Objdata objdata = scanObject.GetComponent(); Talk(objdata.id, objdata.isNpc);
talkPanel.SetActive(isAction); } void Talk(int id, bool isNpc) { string talkData = talkManger.GetTalk(id, talkIndex); if(talkData == null) { isAction = false; talkIndex = 0; return; //void함수에서 return은 함수종료 } if (isNpc) { talkText.text = talkData.Split(':')[0]; //split();구분자를 통하여 배열로 나눠주는 문자열 함수 PortraitImg.sprite = talkManger.GetPortrait(id, int.Parse(talkData.Split(':')[1])); //parse():문자열을 해당 타입으로 바꿔주는 함수,문자열 내용이 타입이랑 맞지 않으면 문제 발생 PortraitImg.color = new Color(1, 1, 1, 1); } else { talkText.text = talkData; PortraitImg.color = new Color(1, 1, 1, 0); } isAction = true; talkIndex++; } } 이렇게작성했습니다.어떤 부분이 문제가 있는건가요 ㅠ
29:13 여기서 저걸 썼더니 Assets\Scripts\TalkManager.cs(33,36): error CS1503: Argument 2: cannot convert from 'UnityEngine.Sprite' to 'UnityEngine.Sprite[]' 라는 오류가 뜨는데 어떻게 해결해야 되나요?
그럼 Dictionary 와 2차원 배열의 차이는 뭔가요? 또 Dictionary 라면 배열을 설정하지 않으면 오히려 한 페이지에 대해 한 정보밖에 저장하지 못하니 오히려 효율이 떨어지지 않나요? P.S 분명 어떨땐 2차원배열이 좋고 어떨땐 Dictonary가 좋겠지만 아직 잘 몰라서요.
배열은 Index기반의 컬렉션입니다. 크기가 정적으로 정해져 있고 데이터 접근을 Index로 합니다. 딕셔너리는 Key기반 컬렉션으로, 크기가 유동적이며 데이터 접근을 Key로 합니다. 관리를 어떻게 하냐에 따라 두 방식 중 하나를 고르시면 됩니다. 한 대화에 여러 문장이 있으니 말씀하신 대로 2차원배열로 하면 Index 기반으로 쉽게 접근이 가능하나, 대화 데이터가 늘어나면 배열 크기를 재설정해줘야 하는 점, 대화마다 Index가 무엇인지 기록해야 한다는 점이 있습니다. 딕셔너리는 크기가 유동적이라 크기 지정을 신경쓸 필요가 없고, 대화에 연결된 key를 숫자가 아닌 문자열로 가능해서 ("주인공첫대사" 이런식) 관리가 2차원배열보다 수월합니다. 다만 2차원 배열처럼 여러 데이터를 넣지 못하는 문제가 있지만, 대화데이터는 어짜피 문자열이므로 구분자(:, /,@ 등)만 정하면 얼마든지 잘라서 여러 문장으로 만들 수 있습니다.
저만 겪는건지 모르겠는데, 대화를 걸다보면 rayhit가 collider 맞으면 활성화되는걸로 아는데, collider에 그 ray가 살짝 겹치는 경우가 있습니다. 그런데 이경우에는 스페이스바를 처음 누르면 대화창은 열리는데, 대화창이 열린 후 스페이스 바를 눌러도 다음 활동 (대화창나가기와 움직임활성화)가 활성화 되지를 않습니다. 어떻게 해결하나요? + 비슷한경우로 위에있는 캐릭터에게 대화를 건네는 찰나의 순간에 오른쪽 방향키를 누르면 ray가 오른쪽으로 바뀌어서 다음으로 진행이 안됩니다.
portaitData.Add(1000 + 0, protraitArr[0]); 심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태 오류 CS1503 2 인수: 'UnityEngine.Sprite'에서 'UnityEngine.Sprite[]'(으)로 변환할 수 없습니다. Assembly-CSharp D:\01_유니티\골드메탈-유니티 기초[3]\Assets\C#\TalkManager.cs 26 활성 라고 오류가 뜨네요 저는 스프라이트 변수를 배열로 선언했는데 왜 이녀석은 배열이 아닌 단수로 인식하는지 궁금합니다. 토크 메니저 전체 코드는 using System.Collections; using System.Collections.Generic; using UnityEngine; public class TalkManager : MonoBehaviour { Dictionary talkData; Dictionary portaitData; public UnityEngine.Sprite[] portraitArr; private void Awake() { talkData = new Dictionary(); portaitData = new Dictionary(); GenerateData(); } void GenerateData() { talkData.Add(1000, new string[] { "안녕?:0", "이 곳에 처음 왔구나?:1" }); talkData.Add(2000, new string[] { "안녕?:0", "이 곳에 잘 왔어:1", "이 호수는 정말 아름답지?:0", "사실 이 호수에는 무언가의 비밀이 숨겨져 있다고 해.:1" }); talkData.Add(200, new string[] { "평범한 나무상자다." }); talkData.Add(300, new string[] { "누군가 사용한 흔적이 있는 책상이다." }); portaitData.Add(1000 + 0, portraitArr[0]); portaitData.Add(1000 + 1, portraitArr[1]); portaitData.Add(1000 + 2, portraitArr[2]); portaitData.Add(1000 + 3, portraitArr[3]); portaitData.Add(2000 + 0, portraitArr[4]); portaitData.Add(2000 + 1, portraitArr[5]); portaitData.Add(2000 + 2, portraitArr[6]); portaitData.Add(2000 + 3, portraitArr[7]); } public Sprite GetPortrait(int id, int portraitIndex) { return portaitData[id + portraitIndex]; } public string GetTalk(int id, int talkindex) { if(talkindex == talkData[id].Length) { return null; } else { return talkData[id][talkindex]; } } } 입니다.
NullReferenceException: Object reference not set to an instance of an object TalkManager.GetTalk (System.Int32 id, System.Int32 talkIndex) (at Assets/Script/TalkManager.cs:25) GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Script/GameManager.cs:33) GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/Script/GameManager.cs:26) PlayerAction.Update () (at Assets/Script/PlayerAction.cs:76) 안녕하세요 골드메탈님 항상 잘보고있습니다ㅎㅎ 이번 영상도 열심히 보고 따라하던 도중 인스펙터창에 Talkmanager 변수도 넣고 영상 똑같이 따라했는데 왜 안되는지 도저히 모르겠습니다 ㅜㅜ 시스템에서 알려주는대로 문제해결을 해볼려고 했는데 어떻게 고쳐야할지 모르겠어요
대화를 할려고 하면 KeyNotFoundException: The given key was not present in the dictionary. System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0) TalkManager.GetTalk (System.Int32 id, System.Int32 talkIndex) (at Assets/Scripts/TalkManager.cs:44) GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Scripts/GameManager.cs:31) GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/Scripts/GameManager.cs:21) PlayerAction.Update () (at Assets/Scripts/PlayerAction.cs:71) 콘솔창에 경고가 뜨고 해당 오류가 발생하는데 표시된 스크립트를 가도 원인을 못 찾겠어요...ㅠ
NullReferenceException: Object reference not set to an instance of an object GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/C#/GameManager.cs:57) GameManager.Act (UnityEngine.GameObject scanObj) (at Assets/C#/GameManager.cs:24) PlayerAct.Update () (at Assets/C#/PlayerAct.cs:97) 라고 떴는데 더블클릭 해보니까 void Talk(int id, bool isNpc) {
string talkData = talkManager.GetTalk(id, talkIndex); if (talkData == null) { isActing = false; talkIndex = 0; return; } if (isNpc) { talkText.text = talkData.Split('@')[0]; portraitImg.sprite = talkManager.GetPortrait(id, int.Parse(talkData.Split('@')[1])); portraitImg.color = new Color(1, 1, 1, 1); } else { talkText.text = talkData; portraitImg.color = new Color(1, 1, 1, 0); } 여기 부분에서 portraitImg.color = new Color(1, 1, 1, 0)에 문제가 있다는데 어떻게 해야할까여 또 NPC랑 대화하면 portraitImg.sprite = talkManager.GetPortrait(id, int.Parse(talkData.Split('@')[1])); 에 문제가 있다네욤..ㅠㅠ 처음에 대충 들었을땐 넘어갔는데 왜 제대로 들을 때엔 오류가 생기는 건지...
골드메탈님 항상 잘보고있습니다. 영상을 보고 그대로 따라하고 있는도중에 제 화면에서는 UI에 있는 도트크기가 플레이 공간과 다르게 보여서 살짝 불편한데 혹시 이걸 맞출 수 있는 방법이 있을까요? 16으로 해서 다 똑같이 맞추면 될줄알았는데 UI창만 유독 도트 크기가 커졋네요
일단 에러 내용은 대화 데이터를 저장하는 딕셔너리에서 없는 Key값을 가져오려 할 때 문제다는 것인데요, 대화 데이터를 가지고 오기 전 보내는 key값을 Debug.Log()로 찍어보시고 그 값이 딕셔너리에 적어둔 키가 맞는지 확인이 필요하겠습니다. TalkManaager 의 GetTalk에서 Debug.Log(id); 를 해보세요
@@goldmetal 역시나 예상했지만 엉뚱한 곳에 문제가 있었네요.. 그래도 골드메탈님 덕분에!! 찾았습니다. Dictionary에 저장해둔 대화값에서 뒤에 portrait로 지정해둔 번호가 문제였습니다 ㅠㅠ 연결한 번호는 0,1,2,3인데 뒤에 배열의 인자값번호를 대화목록에 설정해두는 바람에 없는 번호를 불러오면서 에러를 발생시켰었네요... 하 왜 저게 눈에 안띄었는지 참 멍청했습니다. 그래도 에러 찾으면서 코드 다시한번 훑어보느라 복습은 제대로 한 것 같습니다. 항상 좋은 영상 남겨주셔서 감사합니다!! 앞으로도 가끔 질문 댓글 남길것 같은데 그때도 잘부탁드립니다 ㅋㅋㅋㅋㅎㅎㅎㅎ
이번편에 배운게 재밌네요 ㅋㅋㅋㅋㅋ
혹시 게임매니저의 인스펙트 창에 토크매니저를 끌어다가 토크매니저 자리에 넣으려고 하는데 안들어가고 동그라미에 작대기 쳐진 표시가 나오면 어떻게해야 할까요...?
타입이 맞지 않는다는 이야기입니다.
변수가 TalkManager 타입이 맞는지, 끌어오려는 게임오브젝트에 TalkManager 컴포넌트를 가지고 있는지 잘 확인해주세요
이렇게 훌륭한 강의를 이제서야 알게되었네요.ㅠㅜ 모든 영상에 좋아요 눌렀습니다.
좋은 강좌 만들어주셔서 너무 너무 감사합니다.ㅠㅜ
그리고 혹시 해당 강의와 퀘스트 시스템까지 모두 구현 성공했는데,
npc와의 대화 도중이나 아니면 대화 마지막에 플레이어(주인공)도 말을 하게 하고 싶은데, 어떤 방법이 있을까요?ㅠㅜ
:0 과 :1 을 분기로 나누는 방식으로 해결했습니다!
저는 캐릭터 썸네일은 안넣을거라서 대사 마지막이 :0 이면 npc의 위치에 말풍선을 띄우고 대사 처리, :1이면 플레이어 머리 위에 말풍선을 띄우는 식으로 조건을 만들어서 해결했습니다~
좋은 강의 오늘도 감사히 잘봤습니다. 덕분에 혼자 코딩하려고 했으면 한세월 걸렸을 내용을 빠르고 쉽게 배울 수 있었네요.
골드메탈님 void Awake함수에 GenerateData();위치를 중간에서 맨아래로 바꾸니 몇시간동안 쩔쩔매던 오류가 고쳐져서 궁금해졌는데 Awake함수에서 순서가 중요한가요? Awake함수는 시작할때 한번실행되고 그뒤에는 실행되지 않으니까 상관없을 것 같았습니다 (이게 문제일줄은 생각 못했는데 신기하네요)
함수 내에서의 코드 순서는 매우 중요합니다.
변수의 초기화가 보통 먼저 이루어지고 이후에 해당 변수 데이터를 가지고 작업하는
로직이 와야 에러 없이 정상적으로 작동하기 때문입니다.
함수의 선언은 위치 상관없으나 호출만큼은 순서 신경쓰셔야 한다는 점 참고 바랍니다.
골드메탈님 혹시 이미 대화한 npc와는 다시 대화할 수 없게 하려면 어떻게 해야할까요?
이 강좌에서는 진행할 필요가 없는 퀘스트 대사에도 대사 데이터를 넣었는데
아예 "" 아무런 값을 넣지 않고 Talk에서 데이터 가져왔을 때
이 빈값을 만나면 대사가 진행되지 않게 막으면 어떨까합니다.
영상 늘 감사합니다.
질문이 있습니다.
Talk 태그를 가진 오브젝트가 플레이어와 trigger로 충돌했을때 스페이스바를 눌러서 대화창을 띄우는게 아닌 Talk 태그를 가진 오브젝트와 플레이어가 충돌하면 대화창이 바로 뜨게 하고 싶은데 어떻게 해야 할까요?
OnTriggerEnter2D에서 if 로 태그 검사 후 바로 Action 함수를 호출하시면 됩니다.
@@goldmetal 감사합니다!!
오늘도 유익햇슴다 감사!
talkData = new Dictionary() 대화 하나에 여러 문장이 들어가있어서 string[] 배열을 사용한다고 하셨는데요
스프라이트도 portraitData = new Dictionary(); Sprite[] 배열으로 사용할수 있나요?
강의에서는 스프라이트는 배열로 안하셔서 이유가 궁금합니다.
물론 사용 가능합니다. 따로 이유는 있진 않았구요
Dictionary를 사용한다면 앞 key는 인물 ID만 넣고 뒤의 Sprite[] 배열에서 대화 index를 사용하면 충분히 원하는 표정을 가지고 올 수 있겠네요
골드 메탈님 영상 항상 잘 보면서 유니티 배우고 있습니다, 이 강의로 유니티 3d에서도 똑같이 구현이 되나요? 해보다가 뭔가 다른 게 있는 것 같은데 제가 못 찾는 건지 아예 게임 시스템이 다른 건지 궁금합니다,,
일단 물리가 2D에서 3D가 되므로 Vector2를 사용하던 요소는 모두 Vector3으로 바꾸셔야 합니다. Y축 정보는 Z축으로 옮겨주시면 얼추 비슷하게 구현하실 수 있겠습니다
골드메탈님! 대화하다가 사진 파일을 넣고 싶은데 어떻게 하면 될까요???
버튼 클릭 시 파일 선택 윈도우 창이 나오고 사용자가 이미지를 선택하면 그것이 UI에 나타나게하는 로직을 공유해드립니다.
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Windows.Forms;
public class ImageUpload : MonoBehaviour
{
public RawImage displayImage;
public Button loadImageButton;
private void Start()
{
loadImageButton.onClick.AddListener(OpenFileDialogAndLoadImage);
}
private void OpenFileDialogAndLoadImage()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Image Files|*.png;*.jpg;*.jpeg;*.gif;*.bmp";
openFileDialog.Title = "Select an image file";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string imagePath = openFileDialog.FileName;
if (File.Exists(imagePath))
{
byte[] imageData = File.ReadAllBytes(imagePath);
Texture2D texture = new Texture2D(2, 2);
texture.LoadImage(imageData);
displayImage.texture = texture;
}
else
{
Debug.LogError("Image file not found: " + imagePath);
}
}
}
}
잘 보고 있습니다!! 혹시 대화를 마지막까지 완료 후에 게임오버되게 할 수가 있나요??/
Talk에서 특정id를 if문으로 걸러내어 게임오버를 실행하면 됩니다.
@@goldmetal 혹시 게임오버되서 씬 전환이 이뤄지게 하려면 다른 스크립트에 씬 전환 코드를 구현하고, Talk가 있는 스크립트에 쪽에 FindObjectOfType()를 해서 해봤는데 NullReferenceException이 뜨는데 혹시 다른 방법은 어떤것이 있는지 여쭤봐도 될까요??
@@thj6348 그건 타입이 맞지 않아서 그렇습니다. 다른 스크립트의 파일이름과 클래스 이름이 같은지부터 확인하시고 FindObjectOfType()의 T자리에 정확하게 클래스 이름 넣어주세요
감사합니당! 열심히 따라했습니당 ㅎㅁㅎ
골드메탈님 영상을 매일 보는 학생입니다.
현재 초상화 여러 표정을 game manager 에 넣고 플레이를 하면
코드에서는 문제가 없는데, 대화창만 나오고 초상화는 아예 안나오는데 어쩌면 될까요? 4시간째 제자리라서..
유니티는 2023.2.18f1 버전입니다..
먼저 초상화 데이터는 TalkManager의 portraitArr에 들어가 있어야 합니다.
이후에 대화마다 마지막에 콜론:을 붙이고 초상화 숫자를 써야하고
34:28 처럼 대화마다 초상화 데이터를 가지고 올 수 있도록 해야 합니다.
이렇게 되어있는지 확인하시고 게임 플레이할 때 대화가 나오고 하이어라키에서 초상화 이미지 오브젝트 선택 후에 Image 컴포넌트에 스프라이트가 잘 들어갔는지 확인해보세요.
좋은 강의 잘 봤습니다^ ^, 이 강의를 따라했는데 중간에 잘못해서 그런지 텍스트가 텍스트와 구분자와 같이 '안녕 :0 '이렇게 나옵니다... 어떻게 고쳐야할까요?
33:22 처럼 Split으로 나누고 [0] 번째 문자열만 text로 넣어주셔야 합니다.
도와주셔서 감사합니다
이번 강의는 너무 어려웠습니다. 처음에 이해 못했는데 다 만들고 곰곰히 이해 해보니...
우와.. 정말 아는 만큼 보인다고, 훌륭한 강의 였습니다.무료로 알려주셔서 감사합니다.
33:44 스프라이트를 인스펙터창에서 말고 Asset에서 코드를 통해서 가져올려고 합니다.
찾아보니 addressable이 필요하다고 하는데,
addressable을 건들려고 보니 현재 제 수준에서는 건들여도 이해하기 어렵더라고요.
혹시 addressable을 숙지할려면 어느 수준에 도달 후 공부를 시작해봐야할까요?
어드레서블은 에셋 관리 도구이므로 지금 당장은 필요없고
간단한 파일 불러오기라면 Resources를 사용하시면 됩니다.
learnandcreate.tistory.com/753
@@goldmetal Resource같은 경우 게임 실행시 메모리에 다 올라간다고 해서 메모리 관리에 취약하다고 해서요.
미리 addressable을 숙지할려고해서 문의드렸던 거였어요.
감사합니다. 정말 잘 따라하고 있어요.ㅎㅎ
전에 구동 잘 되는 것을 확인하며 웃으며 저장을 누르고 껐는데...
스크립트는 그대로 저장이 되어 있지만, 씬의 작업과정이 저장이 안 되어있어서 npc, 게임메니저, 토크메니커 스크립트들을 다시 연결을 시도 했습니다.
그런데 대화 내용과 초상화를 연결한 부분에 오류가 있다고 콘솔창에서 떠요 ㅠㅠ
구동은 되는데 캐릭터가 지정된 타일 밖으로 튕겨져 나갑니다 ㅠㅠ
IndexOutOfRangeException: Index was outside the bounds of the array.
TalkManager..GenerateData() (at Assets.Scrips/TalkManager.cs.31)
portraitData.Add(1000 + 0, portraitArr[0]);
장면에 TalkManager 스크립트가 두 개 올라갔는지 확인이 필요하겠습니다
@@goldmetal 으아아~~ 해결되었어요 ㅠㅠ
1. IndexOutOfRangeException: Index was outside the bounds of the array.
- 말씀주신대로 토크메니저 스크립트를 또 다른데 짱박아두어서 생긴 결과더라구요 ㅠㅠ...감사해요..흑흑
2. 캐릭터가 맵 밖으로 튕기는 것
- 맵에 물리 컴포넌트 설정을 잘못한거 같아요 ㅠㅠ... 위에 것과 관련되어 문제가 있는 줄 알았어요...알고보니 별개의 문제였어요 ㅠㅠㅠ
ㅠㅠ 감사해요...! 3일간 고민했었어요 흑흑 감사해요!
11:26 Talkpanel이나 talkManager 같은 경우, 컴포넌트를 가져오는 코드를 쓰지 않고, 혹은 해당 스크립트가 들어있는 오브젝트를 찾는 코드를 쓰지 않고 어떻게 작동하는지 알 수 있을까?
아아 나중에 손으로끌어다가 연결하는군요.
어렵다...그냥 보고 따라하는데도 어지러운데 스스로 코드짤때는 더 힘들겠네,,
좋은 영상 항상 감사합니다 열심히 할게요
초상화 기능을 사용하면 앞으로 그냥 대화는 불가능한가요?
아니면 그냥 isNpc를 해제하고 대화를 이어나가야 할까요
초상화 ID가 9번이면 초상화 스프라이트는 적용하지 않는 분기점을 추가하면 어떨까 합니다.
저번주에 문의 드렸던 사람입니다! 오브젝트 클릭시 대화창이 넘겨지는것 외에도 대화판넬을 클릭하면 넘어가도록 추가적으로 만들고 싶은데 이때는 판넬을 id로 줘서 그냥 추가하면 되는걸까요?
상대방 데이터인 scanObject는 플레이어가 가지고 있으므로 대화판넬에도 플레이어만 접근 가능하면 됩니다.
@@goldmetal 혹시 오브젝트를 마우스 클릭시 애니메이션이 나오도록 짜고 싶은데
GetMouseButton 함수를 이용하면 단순히 클릭하면 애니메이션 출력하게 만들수 있을까요??
아니면 따로 변수라든지 함수를 작성해서 거기에 처리를 하고 GetMouseButton 함수에 집어넣어야 할까요 ㅠㅠ
@@ppibppyob 마우스 위치에 레이캐스트를 쏘아 오브젝트를 확인하고 원하는 로직을 작성하시면 됩니다.
the-pond.tistory.com/12
txt파일에다가 대화를넣어서 불러오는 식으로 만들까 하는데 이렇게 하시는분들이 거의없는거같습니다.
예상대로라면 번역작업할때도 편하고 여러모로 좋을것같은데 많은분들이 이렇게 하지않는데엔 뭔가 문제가 있기때문인가요?
짧게 생각하기엔 베포할때 path문제가 좀 있을법도한데 조언 부탁드립니다.
텍스트 파일 중에 데이터 구조를 넣을 수 있는 JSON 혹은 XML 형식 파일을 사용하는 경우가 많습니다.
구글에서 유니티 Json 검샏하시면 많은 방법이 나올거에요!
혹은 빠르게 구현을 위한 스크립트블 로브젝트도 사용하실 수 있습니다
골메님... a 라는 이름의 Dictionary에 100 이라는 ID를 등록하고 100이라는 ID에 "안녕하세요" 라는 문장을 넣었어요... 그리고 이차원배열로 return a[100][0]; 이렇게 작성하면 "안녕하세요"라는 문장이 반환되는건가요....? 아마도 되는것같은데 처음알았네요... Dictionary와 이차원배열이 연동된다는 말씀이신거죠...? 와 진짜 신기하네요.... 한가지 궁금한게 있는데 위에 리턴값에서 return a[100][0]; 를 하든 return a[100][1]; 을 하든 뒤의 배열은 상관없는거죠??? 궁금해요//..
정확히는 아닙니다. Dictionary 와 Array의 차이점을 잘 이해하셔야겠습니다.
Dictionary는 Key방식이라서 100이라는 Key에다 "안녕하세요" Value를 연결하여 저장하는 것이고
배열은 100번째 칸에다가 "안녕하세요"를 저장한 셈이 됩니다.
그리고 배열은 Dictionary처럼 길이가 자유롭게 변경되지 않으니 미리 선언한 배열크기를 넘으면
에러가 발생하니 참고하시기 바랍니다.
@@goldmetal 그렇다면 Dictionary와 Array의 형식은 Key와 Value값으로 서로 다르지만 연동은 되는거죠??
@@진진자라지리지리-f4z Dictionary는 Key 방식, Array는 Index 방식입니다. Dictionary는 Key만 알면 value를 얻을 수 있고, Array는 칸 주소를 알아야 value를 얻을 수 있습니다. Array가 조금 불편하지만 for문으로 숫자를 돌려서 모든 칸을 순회할 수 있고, Dictionary는 그게 안됩니다.
@@goldmetal 이해는 되는데....계속 질문 죄송합니다...ㅠㅠㅠ
Dictionary TakeData;
TakeData = new Dictionary();해주면서
TakeData.Add(1000, new string[] { "안녕?", "반가워!" });
TakeData.Add(100, new string[] { "무슨일이지?" }); 라고 넣었어요.
return TakeData[1000][0]; 한다면 "안녕?",
return TakeData[1000][1]; 한다면 "반가워!",
return TakeData[100][0]; 한다면 "무슨일이지?"가 반환이 되잖아요!!
그렇다는것은 이차원 배열과 dictionary 이 연결이 된다는 말인데 key값 그리고 인덱스 값 이렇게 다른데 어떻게 이게 가능한거죠??
정말정말 죄송합니다 ㅠㅠ 진짜 존경합니다!!
@@진진자라지리지리-f4z TakeData[1000][0];
영상 잘 봤습니다!! 덕분에 많은 도움이 되었습니다. 개인적으로 궁금한게 있어서 질문 남깁니다! 만약 캐릭터에 따라서 출력하는 대사를 다르게 할 경우에는 어떻게 해야 할까요??
오브젝트의 npcId를 다르게 하고 그에 따른 TalkId로 대화 데이터를 담아두시면 됩니다.
14:08에서 TalkManager 스크립트가 안 들어가지는데 이것은 어떻게 해결하나요?
아 해결됐어요. TalkManager 스크립트를 GameManager에 넣은 후 다시 TalkManager 스크립트를 GameManager의 TalkManager 속에 다시 집어넣으면 들어가지네요.
2023 최신버전으로 진행하니 초상화부분에서 버그와 오류가 일어납니다. 1000+1, 0....7 이부분꺼가 진행이 안되는데 다른 코딩으로 대체해야하면 어떻게 해야하는지 알수 있을까요?
기초적인 부분은 차이가 없습니다.
어떤 오류인지 알려주시면 확인해드리겠습니다.
@@goldmetal 다시 처음부터하니까 되네요 어디선가 문제가있었나봅니다
성공했다.........................정말 감사합니다
골드메탈님 항상 양질의 콘텐츠를 만들어 주셔서 감사드립니다 ㅠ
질문이 있습니다 !
플레이 모드에만 들어가면 초상화 이미지가 흐리게 나옵니다. 초상화에 사용할 픽셀 이미지를 픽셀퍼 유닛도 맞게 하고 no point에 none을 설정해주었는데도 플레이 모드에만 들어가면 흐리게 나옵니다 ㅠ 해결할 방법을 여쭙고 싶습니다 ㅠ
설정하신 후에는 꼭 아래의 Apply 버튼을 눌러주셔야 합니다.
@@goldmetal 아하 감사합니다!
골드메탈님 혹시 선택지도 딕셔너리 써서 만들 수 있나요? 만들려고 하는 데 방향을 못잡겠어요..
1.선택지 저장용 딕셔너리 (int, string) 선언
2.int 키값은 대화 id로 저장
3.string은 선택지, 특문자로 구분지어 저장
4.불러올때 선택지 문자열을 split()함수로 배열로 나누어 접근
5.배열로 나눠진 각 문자열을 UI에 표시
@@goldmetal 정말 감사합니다 함 해보겠습니다!
골드메탈님 이번 영상에서도 질문이 있습니다!
질문 내용은 NPC에게 다가가서 스페이스바 키를 누를경우 플레이어가 멈추는 현상이 발생하고 대화창도 뜨지 않습니다. 왜그런 걸까요?
스페이스바 눌렀을 때 유니티 아래에 에러메세지가 나타나는지 확인해보세요
골드메탈님 Dictionary 함수를 사용할때 talkData는 Dictionary이런식으로 아예 안에 배열을 넣어버렸는데 초상화데이터를 넣을때는 왜 Dictionary이런식으로 안하구 밖에 따로 만드신건가요??? 설명부탁드립니다. ㅠㅠ 저렇게는 안되는건가요
딕셔너리는 {key, value} 형태의 데이터를 저장하는 용도입니다.
20:45 시간대를 보시면 Add() 함수를 사용해서 {int, string[]} 형태로 데이터를 넣고 있지요.
레퍼런스 타입 (클래스 타입)은 선언 후 초기화 할때만 한번 new Dictionary()해주시면 됩니다. 이것은 Awake()에서 해주고 있는걸 확인 하실 수 있습니다.
@@goldmetal 감사합니다!
대사칠때 효과음은 어디서 구할수있을까요?
띠디디딕 이런거요
유니티 에셋스토어에서 Sound 무료로 설정해서 UI관련 에셋쪽 찾아보시면 될 것 같네요
안녕하세요!! 늦은밤 질문드려죄송합니다
Npc위에 타이머 설정하여 시간이 되면 가게 밖으로 나가도록 이동하는 코드를 구현하고 싶은데 어느 방향으로 짜야할지 감이 잘 안잡힙니다..어떻게하는지도움받고싶습니다…
그럼 좋은하루되세요감사합니다!!
1.talkManager에 float timer 변수를 두고 대화 중에는 Update에서 timer+= Time.deltaTime; 실행 ( if문을 통한 조건 )
2. UI 는 슬라이더 하나를 만들고LateUpdate에서 value값을 timer / 최대시간초 이렇게 계산한 값을 넣어준다.
3. timer < 0 일 때 TalkEnd같은 함수를 호출하여 대화를 종료시킨다
영상과는 별개로 따로 토크매니저 만들어서 진행하면되는걸까요..???
@@뇽-k8b 아 여기서는 게임매니저에서 진행하셔도 됩니다.
내년 gigdc준비하는데 큰힘이 되고있어요 감사합니다!
좋은 결과 있길 바랍니다. 😊
골드메탈님! 질문이 있습니다
talkData.Add(1000, new string[] { "안녕*0", "이 곳에 처음 왔구나?*1" });
talkData.Add(100, new string[] { "평범한 나무 상자다."});
talkData.Add(200, new string[] { "누군가 사용했던 흔적이 있는 책상이다."});
talkData.Add(2000, new string[] { "여어*1","이 호수는 정말 아름답지?*0","사실 이 호수에는 무언가의 비밀이 숨겨져있다고 해*1"});
portraitData.Add(1000 + 0, portraitArr[0]);
portraitData.Add(1000 + 1, portraitArr[1]);
portraitData.Add(1000 + 2, portraitArr[2]);
portraitData.Add(1000 + 3, portraitArr[3]);
portraitData.Add(2000 + 0, portraitArr[4]);
portraitData.Add(2000 + 1, portraitArr[5]);
portraitData.Add(2000 + 2, portraitArr[6]);
portraitData.Add(2000 + 3, portraitArr[7]);
이 부분이 잘 이해가 안돼요ㅠㅠ
"여어*1" 여기서 1이 뭘 나타내는 건가요?
초상화 이미지의 ID라고 보시면 될 것 같습니다. 대화에 맞게 표정을 지정해주는 것이지요. 차후에 문자열에서 *를 중심으로 잘라서 사용할 겁니다.
골드메탈님
대화중에 퀴즈를 넣고 싶은데
어떻게 구현하면 좋을까요?
1.퀴즈문제, 선택지, 정답을 저장할 배열 변수 혹은 딕셔너리를 따로 선언
2. 각 배열 혹은 딕셔너리에 데이터를 추가
3. 대화 마지막에 퀴즈ID를 구분자 (&,* 등등 특수기호)와 함께 추가
4. 대화 함수 호출 시 퀴즈ID 데이터가 있을 때 대화 끝나고 퀴즈가 나오도록 구현
이정도로 해주시면 됩니다.
감사합니다!
골드메탈님 영상 잘 보고 있습니다
'ObjData' 형식 또는 네임스페이스 이름을 찾을수 없습니다. using 지시문 또는 어셈블리 참조가 있는지 확인하세요 라고 오류가 뜨는데 어떻게 해결할수 있나요?
이건 유니티 에디터와 비주얼 스튜디오가 연결이 잘 안되서 그런 것일 수 있습니다.
유니티 디버그 D01 영상을 참고해주세요.
ruclips.net/video/-j5LKpFj4NQ/видео.html
2d 게임형식을 3d에서 접목하고있더니 확실히 제가 코딩이 부족해서 그런가 잘 안되네요 ㅠㅠ
계속 GameManager 쪽에서 null 값이 나와서 2d에선 scanObject 를 사용하시는데 혹시 3d에서 그대로 쓰면 작동이 원래 안되는건가요?
레이캐스트 사용할 때 Physics2D 가 아닌 Physics 를 사용하셔야 합니다.
@@goldmetal GameManager 쪽에서 자꾸 널값이 나왔습니다
@@baka302 에러메세지 더블클릭하시고 그 줄에서 사용된 변수가 왜 Null인지 역추적해보세요
@@goldmetal gameManager.isAction(scanObject); 에서 게임매니저부분이 널값이 나온다고 떴습니다
@@baka302 그건 인스펙터 창에서 게임매니저를 넣지 않아서 그렇습니다. 인스펙터 창 확인해보세요
골드메탈님 혹시 초상화를 여러개 출력하고싶으면 어떻게하면 될까요??
다수의 인물이 대화를 나누기 위해선
초상화를 담을 Image 오브젝트도 그만큼 배치해두어야 합니다.
그리고 하나의 대화에 참여하는 인물들의 데이터도 따로 저장해두어야 하구요.
대화가 시작할 때 이 데이터(배열이 좋겠네요)를 읽어서 Image에 초상화를 띄우면 되겠습니다.
@@goldmetal 답변 감사합니다!
골드메탈님 따라하던 중 오류가 터져서 계속 고치려고 시도 했었는데, 결국 처음에 오류 났던 코드가 다시 실행 되네요.. 이렇듯 가끔 유니티 자체에서 스크립트 못 읽을 때가 있나요?
간혹 내부 오류로 그런 경우가 발생할 수도 있긴 합니다.
그래서 전혀 모르는 에러가 났을 땐 일단 저장 후 재시작해보는 것도 좋습니다.
게임메니저에 public으로 선언한 talkMnager에 드래그 해서 넣는 14:12 초쯤 처럼 안 들어가고 마우스 커서가 거부모양으로 바뀌는데 이유를 잘모르겠습니다
에셋창의 스크립트 파일을 드래그해서 넣는 것이 아니라
하이어라키의 TalkManager가 들어있는 오브젝트를 드래그해서 넣으셔야 합니다.
골드메탈님 이번 강좌도 정말 잘 봤습니다
대화랑 초상화는 문제없이 잘 뜨는데 자꾸 콘솔에
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.Graphs.Edge.WakeUp ()(at :0)
어쩌고저쩌고
이런식으로 오류가 뜨네요. 무슨 문제일까요?
애니메이터 내부 문제입니다.
애니메이터 창은 닫아주시고 모두 저장 후에 유니티를 껏다가 재시작해보세요.
@@goldmetal 감사합니다!!
골드메탈님 안녕하세요!! 벌써 여기까지 따라왔습니다ㅠㅠ ♡
12:00~ 까지 순조롭게 진행되다가, ObjectData 스크립트 만들며 새로운 부분을 덧붙여줬던 GameManager에서 [ error CS0246: The type or namespace name 'ObjData' could not be found(are you missing a using directive or an assembly reference?) ] 라는 오류가 떴는데 왜 이런문제가 생겼는지 아시나요...? 스크립트는 두번세번 확인했는데 대소문자 틀린 부분 없이 그대로 구현했습니다 ! 외부적인 Inspector 창 쪽에서 제가 뭔가 놓친걸까요..?
그리고 GameManager 의 Inspector 창에 Talk Panel, Talk Text, Scan Object 는 나오는데 Talk Manager 가 활성화되지 않네요... ಥ_ಥ 내일 처음부터 다시 따라가보겠습니다 ㅠㅠ!
너무너무 재밌습니다....!!!
유니티와 비주얼 스튜디오가 연결되지 않아서 스크립트를 찾을 수 없을 수도 있겠네요.
유니티 디버그 D01 영상 참고해주세요.
ruclips.net/video/-j5LKpFj4NQ/видео.html
안녕하세요 골드메탈님 항상 좋은강의 감사드립니다 ㅠ.ㅠ
이번 강의의 내용과는 맞지않은 질문입니다.
지형의 보더라인에 관하여 질문드립니다.
강의영상을 보면 플레이어가 있던 마을의 지형과 호수가 있는 지형 그리고 그 둘을 연결해주는 다리같은 역할을
하는 지형 총 3개로 보이고 그렇게 판단하였습니다.
궁금한점은 기본 강의에서 BorderLine을 생성하신 방법으로
지형을 비슷하게 다리가 있고 다른 곳으로 이동하는 지형을 만들었더니
BorderLine의 콜라이더가 사각형모양이라 텅텅빈 여분의 지형으로도 플레이어가 이동하는 경우가 발생합니다.
BorderLine을 맵의 빈지형에 추가하여 그곳으로 못오게 하는 방법말고는 생각이 나지 않습니다.
이러한 방식말고 다른 방식으로 해결해야하는지 질문드립니다.
바깥 경계 외에 플레이어 이동을 막고 싶으면 바닥 타일맵을 덮는 새로운 타일맵을 만드시고 타일맵 콜라이더 추가하시면 됩니다. 그리고 막아야 되는 부분, 모양이 타일 하나보다 작거나 다른 모양이면 스프라이트 선택 후 인스펙터에서 Sprite Editor로 간 후, 창 왼쪽 위에 작은 메뉴 Physics Shape로 선택해서 콜라이더 모양을 잡아주시면 됩니다.
이 내용은 B17에서 다루었습니다.
ruclips.net/video/f8ixw9IpnD8/видео.html
@@goldmetal 아하 너무어렵게 생각하고있었네요 좋은 답변 감사드립니다!
좋은 강의 감사합니다.
질문이 있습니다.
1. 코드 오류는 없고 마지막까지 따라한 상태입니다. 두 번째 NPC와 대화할 때 첫 번째 NPC의 첫 대사가 나오면서 대화 내용이 한줄씩 밀립니다. 혹시 알려주실 수 있으신가요?
2. 혹시 대화가 종료되자마자 다음씬으로 넘어가게 만들고 싶을 땐 어떤 함수를 쓰면 좋을지 알려주실 수 있으신가요?
1. 두번째 NPC의 NpcId 설정이 되었는지 인스펙터 확인해보세요
2. SceneManager.LoadScene() 사용하시면 됩니다.
@@goldmetal 알려주셔서 감사합니다 NPC인지 아닌지 확인하는 체크 박스를 말씀하시는 건가요?
@@ChuEru id변수 말씀입니다. 두 NPC의 id가 같으면 안되니까요
@@goldmetal 앗 다 다릅니다!! 다 다름에도 불구하고 오류가 나서 무척 고민하던 중이었습니다. 염치없지만 카페에 글을 올려놨는데 한 번 봐주실 수 있으신가요? 꼭 답 안해주셔도 됩니다.
cafe.naver.com/unityhub/120438
대화창에 초상화 2명 이상이 필요할 땐 어떻게 해야되나요?
그리고 초상화가 움직이는 애니메이션은 어떻게 넣어야 될까요?
한 대화에 들어가는 인물 수를 저장하는 변수도 추가해야겠지요.
미리 초상화 오브젝트를 4개 만들어두고 대화가 시작 될 때 이 숫자를 읽어서
오브젝트를 장면 안으로 옮기는 것이지요.
실제 모바일 게임에 사용되는 움직이는 초상화는 라이브2D가 사용된겁니다.
안녕하세요 오늘도 강의 잘 듣고있습니다.
딕셔너리형 공부해야겠어요ㅜㅜ
오늘은 질문이 있습니다!
구동시엔 잘 돌아가는데 대화시스템 구현부분에서 다음과 같은 에러가 뜹니다.
NullReferenceException: Object reference not set to an instance of an object
GameManager2.Action (UnityEngine.GameObject scanObj) (at Assets/scripts/GameManager2.cs:18)
PlayerAction.Update () (at Assets/scripts/PlayerAction.cs:74)
GameManager의 18~19줄은
objData oData = scanObject.GetComponent(); //해당하는 컴포넌트의 요소를 저장
Talk(oData.id, oData.isNpc);
이고
PlayerAction의73~ 74번째 줄은
if (Input.GetButtonDown("Jump") && scanObject != null)
manager.Action(scanObject);
입니다.
제 생각엔 scanObject부분이 비어있어서 나는것 같은데 PlayerAction에서 scanObject부분은 제가 스페이스바를 눌러야만 isAction이 작동하니까 에러가 나지 않아야 하는데 자꾸 저런 에러문구가 나와요.. 제가 오류문구를 이해한게 맞나요??
원래이런건지 아니면 제가 뭔가 잘못한 건지 궁금합니다. 하나하나 스캔은 잘 되거든요!
제가 오류문구를 잘 이해했는지 저 오류문구를 무시해도 되는지 궁금합니다.
if (Input.GetButtonDown("Jump") && scanObject != null) {
Debug.Log("Action : " + scanObject .name);
manager.Action(scanObject);
}
이렇게하고 한번 실행해보세요.
@@goldmetal ㅠㅠ 덕분에 디버그 로그 찍어가며 해결했습니당..
제가 나무 오브젝트에는 대사를 입력해주지 않아서 생긴문제였어요!
해당하는 오브젝트에 talkData.Add(400, new string[] { });
이렇게 빈객체를 생성해주니까 오류가 안났습니당ㅎ..
대사가 필요없는 객체는 굳이 Object 레이어로 할 필요가 없겠다 싶어서 layer를 Default로 설정하니 저렇게 객체 생성 코드 안써도 오류가 안났어요!
오늘도 배워갑니당... 총총..
정말 감사합니다~ ㅠㅠ 진짜 이 강의 없었으면 프로젝트 만드는거 한참 걸렸을겁니다~ ㅠㅠ
메탈형님 강의 듣고 따라하던중 오류가 생겨 질문하나 남깁니다
캐릭터가 scanHit raycast 인식 범위를 벗어나도 대화키를 누르게되면 scanHit raycast 거리 밖임에도 마지막으로 인식했던 오브젝트와의 대사창이 나옵니다
나머지 기능들은 정상적으로 진행되는데 어떻게 해결하면 좋을까요??
17:24 Action 함수 첫번째 줄에 Debug.Log(scanObj.name); 추가하고 시도해보세요.
바깥으로 벗어난는데도 이름이 나타난다면 Ray쪽에 문제가 있는 것 같네요.
메탈형 해결했습니다 감사합니다
골드 메탈님 잘보고 있습니다. 다름이 아니라 이런 대화 시스템은 전에 만드신 2D 플랫포머 게임에도 적용이 가능한가요?
네 장르 상관없이 다 됩니다.
사물의 내용을 데이터에 넣고 불러오는 부분 중에
NullReference Exception 오류가 떠서 클릭으로 그 부분에 갔는데
ObjData objData = scanObject.GetComponent(); 가 뜨던데 뭐가 문제인지 모르겠네요.. 혹시 뭐가 문제인지 아시나요? 코드도 계속 봐도 다 똑같은거 같은데 모르겠네요ㅠ
그 코드 위에 Debug.Log(scanObject); 해보세요.
아마 Null이 나올겁니다.
scanObject가 왜 안담아졌는지 레이캐스팅 쪽을 보셔야겠습니다.
스캔할 대상의 레이어가 Object인지도 확인해보셔야 겠네요.
ruclips.net/video/bZVa6C6vRBQ/видео.html
@@goldmetal 디버그를 썼는데 콘솔 창에 Flower, Water이 나오네요.. 여전히 null레퍼런스.. 이렇게 뜨지만...
npc쪽은 레이어가 오브젝트여도 콘솔창에만 뜨고 null오류는 없지만 판넬은 안보이고
Grid안에 있는 꽃 연못들은 Layer가 Object여도 콘솔에는 뜨지만 null과 같이뜨고 판넬은 안보이네요...
오브젝트 레퍼런스가 인스턴스로 설정되지 않았다는게 도데체 왜 뜨는지...
제가 정리하느라 추가나 수정하는 부분 제외하면 진행 코드를 적은 순서대로 냅두긴 했는데 혹시 순서로 차이가 생기는 부분 있나요?
@@이영차-z6o 물론 순서로 인해 문제가 발생할 수 있죠. 선언, 할당, 호출 순서가 꼬이면 문제가 생길 수 있습니다. 일단 ObjData objData = scanObject.GetComponent
@@goldmetal 하.. if문으로 감싸도 그대로 오류가 뜨네요...
@@이영차-z6o scanObject 안에 Object 스크립트가 포함되어있지 않을 수도 있겠네요. 그리고 스크립트 이름이 Object이면 상당히 위험합니다. 이름을 바꿔주세요.
처음에 talkData = new 로 초기화 시켜주는 이유가 뭔가요? 독학으로 띄엄띄엄 해서 그런지 감이 안잡히네요
int, float, bool 같은 단일형 변수는 차지하고 있는 메모리 크기가 정해져 있기 때문에 C#컴파일러가 미리 알고 있으므로 그냥 선언합니다.
하지만 선언방법 혹은 데이터 추가로 인해 크기가 가변적인 배열, 리스트, 클래스 타입은 자유로운 메모리 공간에 변수를 두기 위해서 new 키워드 사용해주어야 합니다. (인스턴스) 이정도로만 이해하시고 더 깊이 들어가실려면 Stack 과 Heap 메모리타입에 대해 공부하셔야 합니다. 링크 첨부해드릴께요. nowonbun.tistory.com/67
@@goldmetal 상세한 답글 감사합니다 ~ 덕분에 이해되었습니다 (_ _)
[질문] 초상화를 바뀌는 이미지가 아닌 한 이미지로 통일한다면 26:18 까지만 따라해도 잘 작동하는 건가요??
+유익한 영상 잘 봤습니다 감사합니다 :)
네 그렇습니다.
2만 축하드립니다 split 함수 제가 문자를 :로 지정 해두었으면
예를들어 a:b:c
C를 쓰고싶으면 index가 [2]이되는건가요?
네 정확하십니다.
초상화 부분을 다 하고 한번 실행해보려 했는데,
ArgumentException: An item with the same key has already been added. Key: 1001
System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at :0)
System.Collections.Generic.Dictionary`2[TKey,TValue].Add (TKey key, TValue value) (at :0)
TalkManager.GenerateData () (at Assets/Scripts/TalkManager.cs:31)
TalkManager.Awake () (at Assets/Scripts/TalkManager.cs:16)
재생버튼을 누르자마자 이런 오류가 뜨더군요.
구글링해서 나온 해결책도 안듣고요.
왜 이러는건지 알려주시면 감사하겠습니다.
TalkData 에 동일한 Id로 데이터를 넣으려고 하고 있어 에러가 생기는 겁니다.
1000 + 1 번 Add 두번 하는지 확인해보세요
14분에 있는 TalkPanel에 아무것도 없는데 Canvas를 집어 넣는게 맞나요?
해결했습니다. Canvas가 아니라 바로 밑에있는 대화 UI를 집어 넣으면 되는거였네요
항상 참고하고 있습니다 영상 만들어 주셔서 감사합니다!!
주인공 대사가 나올때 (sprite 값이 특정값일때) public Image portrait image;(초상화 사진) 의 좌표값을 이동시키던중 game object와 다르게 Image는 transform.position이 먹히지 않았는데
일단 주인공 대사부분은 해결하긴 했지만, 한가지 의문점이 있습니다
스크립트 상에서 Canvas의 Image좌표값은 어떻게 바꿀 수 있을까요?
Canvas 내에서는 RectTransform을 사용합니다.
아.. 진짜 잘 나가다가 막판에 갑자기 대사창NPC Portrait이미지 안떠서 생고생했네요 ㅠㅠ
인스펙터창에 Obj Data의 Is NPC체크 풀린거 모르고 삽질을 ㅠㅠ
오늘은 오류없이 잘 되가나 싶어 신나가지고 막 따라하다가 플레이 누른 상태로 체크했었나봐요. ㅠㅠ 체크한 기억이 분명 있는데 풀려있는거 보니 ㅠㅠ
그럼 다음 장으로 넘어가겠습니다 ㅠㅠ
감사합니다..,감사합니다,,, 덕분에 고쳤어요
언제나 너무 도움이 되고 유익한강의들이예요!! 재미있네요 ㅎㅎ
감사합니다 골메님!!! 골메님 최고!
딕셔너리 개꿀도구네요 ㄷㄷㄷㄷ
안녕하세요! 저는 talk index가 0->1->2->3이 순서대로 가지 않고, npc가 아닌 오브젝트는 0->2 순서대로 가고 npc와 대화할때는 1->3->5->2->4->6 이런 식으로 갑니다. 그래서 대화가 순차적으로 이루어지지 않아요ㅜㅜ 어떤 것 때문에 이런 상황이 발생할까요?ㅠㅠ 콘솔창에 에러 뜨는 것도 없어요ㅠㅠㅠ
Debug.Log(talkIndex); 로 흐름 확인해보시는게 좋겠습니다.
아마 0,1,2,3 잘 흘러갈텐데 그렇다면 처음 talkData 딕셔너리 에 넣을 때 순서를 잘못넣으신걸 고려해보셔야 합니다.
@@goldmetal 빠른 답변 감사드립니다. 말씀하신대로 디버그로 확인해보니 순서 흐름은 맞게 흘러갑니다.. 제가 봤을땐 딕셔너러 순서도 이상이 없어보이는데 왜 그럴까요...?ㅜㅜ
앗! 해결했습니다. 제가 scanobject를 두번 써버린 실수를 했네요. 도움 주셔서 정말 감사합니다!!ㅠㅠ
좋은 영상 잘 보고 있습니다 혹시 한번 누르면 여러문장이 차례로 나오는 것이 아니라 한문장이 나오고 대화가 끝나고 다시 눌러야지 다음 문장이 나오게 하려면 어떻게 해야할까요?
해당 내용은 B25에서 다루었습니다.
ruclips.net/video/emGwkkM6bnc/видео.html
정말 좋은 영상입니다. 많은 노하우를 얻어가네요 :) 감사합니다
이 대화 시스템을 csv 파일을 이용해서 불러오고 연결해주려면 어떻게 해야 될까요..??
잘 정리된 글이 있어 공유해드립니다.
foxtrotin.tistory.com/121
@@goldmetal 혹시 골드메탈님께서 강의해주신 방법으로 talkManager와 QuestManager를 이용한 그대로 csv파일과 연결해서 사용하려면 dictionary 다중키를 이용해서 npcId와 QuestId를 키로 받아 접근해야 할까요?
@@FlyingNotebook-e9p 네, 저장 타입이 string 이 아닌 대화 데이터 클래스로하면 됩니다.
portraitImg.sprite = TMS.GetPortrait(id, int.Parse(talkData.Split(':')[1]));
여기서 위의 코드를 주석처리하면 정상적으로 작동하지만 위의 코드를 넣으면 그 밑에 있는 코드들이 실행이 안되는거로 봐서는 코드에 문제가 있는 것 같은데 혹시 제가 NPC한테만 넣어둬서 isNPC라는걸 아예 안 넣어 뒀고 그래서 if(isNPC)이런것도 안 넣어 뒀는데 그것 떄문인가요?
해당 코드를 넣고 실행했을 때 에러메세지가 나오는지 콘솔창을 확인하세요.
안되는 이유를 메세지 확인하지 않고 지레짐작으로 하면 해결하기가 어렵습니다.
에러 메세지를 더블 클릭하면 에러난 위치로 안내해주니까 그 줄을 확인하시고 고쳐주시면 됩니다.
@@goldmetal NullReferenceException: Object reference not set to an instance of an object
TalkManager.GetPortrait (System.Int32 id, System.Int32 portraitIndex) (at Assets/Scripts/TalkManager.cs:34)라고 나오고
더블클릭하면 return portraitData[id + portraitIndex];의 맨 앞으로 갑니다.
@@user-ek9dp4fu1s TalkManager 32번째 줄에 사용된 변수가 비어있다는 겁니다. public으로 선언한 변수라면 인스펙터 창에서 비어있는지 확인해보세요
@@goldmetal public Sprite GetPortrait(int id, int portraitIndex)
{
return portraitData[id + portraitIndex];
}로 되어 있어서 id와 portraitIndex도 선언 되어있습니다.
Dictionary portraitData;에도 public을 하는 건가요?
@@user-ek9dp4fu1s return바로 위에 Debug.Log(portraitData[id + index]); 추가해서 스프라이트가 있는지 콘솔로 확인해보세요
안녕하세욥 분명 열심히 똑같이 코딩을 했는데 이런게 뜨네요. . . . .
NullReferenceException: Object reference not set to an instance of an object
GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/script/GameManager.cs:35)
GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/script/GameManager.cs:26)
playeraction.Update () (at Assets/script/playeraction.cs:72)
어떻게 해결 하나요?????????
GameManager.cs:35 게임매니저 35번째 줄에 호출되는 변수 중 Null 값이 있다고 하네요.
한번 확인해보세요.
NullReferenceException: Object reference not set to an instance of an object
GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/script/GameManager.cs:26)
GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/script/GameManager.cs:19)
playeraction.Update () (at Assets/script/playeraction.cs:72)
음.............
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public TalkManager talkManager;
public GameObject talkPanel;
public Text talkText;
public bool isAction;
public GameObject scanObject;
public int talkIndex;
public void Action(GameObject scanObj)
{
scanObject = scanObj;
ObjData objData = scanObject.GetComponent();
Talk(objData.id, objData.isNpc);
talkPanel.SetActive(isAction);
}
void Talk(int id, bool isNpc)
{
string talkData = talkManager.GetTalk(id, talkIndex);
if (talkData == null)
{
isAction = false;
return;
}
if (isNpc) {
talkText.text = talkData;
}
else {
talkText.text = talkData;
}
isAction = true;
talkIndex++;
}
}
@@이찬영-v6s 인스펙터 창에 talkManager 변수 비어있는지 확인해보세요
잘 배워갑니다 좋은 영상 감사합니다 🥰
좋은 강의 감사드립니다 코로나 때문에 시작한 유니티가 이렇게 재밌을줄 몰랐네요ㅋㅋ
생방송도 꼭 놀러가겠습니다
Argument 2: cannot convert from 'UnityEngine.Sprite' to 'UnityEngine.Sprite[]'
라는 오류가 뜹니다. 어떻게 수정해야 할까요?
잠도 줄여가며 골메 님 영상으로 공부 중인데, 쉽게 설명해주시는데도 제겐 쉽지만은 않네요. 많은 노력이 필요할 것 같습니다. 항상 답변해주셔서 진심으로 감사드립니다!
타입이 맞지 않는 문제입니다.
스프라이트 배열 타입을 스프라이트에 대입하고 있어서 발생하는 문제이니
에머 메세지를 더블 클릭해서 안내해주는 위치의 스프라이트 배열 변수를 확인해보세요.
@@goldmetal 감사합니다! 고쳤습니다!! 잠을 좀.. 푹 자고 해야겠네요. 밤 새면서 개발하시는 분들은 대단한 정신력이란 걸 알았습니다 : 0 .. 매번 감사해요~
이게 유니티 3d 로 구현할때도 써먹을 수 있는 방법일까요? 궁금합니다.
네 가능합니다.
실행하면 바로 일시정지가 되고 KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0)
Talkmanger.GenerateData () (at Assets/Scenes/Talkmanger.cs:26)
Talkmanger.Awake () (at Assets/Scenes/Talkmanger.cs:14)
이런 오류가 뜨고 일시정지를 풀고 오브젝트한테 스페이스를 누르면 일시정지가 된 후 KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0)
Talkmanger.GetPortrait (System.Int32 id, System.Int32 portraitIndex) (at Assets/Scenes/Talkmanger.cs:44)
GameManger.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Scenes/GameManger.cs:36)
GameManger.Action (UnityEngine.GameObject scanObj) (at Assets/Scenes/GameManger.cs:19)
playeraction.Update () (at Assets/Scenes/playeraction.cs:65)
이렇게 오류가 뜹니다.talkmanger에 오류가 있는것처럼 보이는데 talkmanger는 이렇게 작성을 하였고
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Talkmanger : MonoBehaviour
{
Dictionary talkData; //대화데이터 저장
Dictionary portraitdata;
public Sprite[] portraitArr;
void Awake()
{
talkData = new Dictionary();
portraitdata = new Dictionary();
GenerateData();
}
// Update is called once per frame
void GenerateData()
{
talkData.Add(1000, new string[] { "안녕?:0", "이 곳에 처음 왔구나?:1" }); //배열은 여러가지 문장이 들어갈 수도 있으니
//Add:함수를 사용하여 대화 데이터 입력 추가
talkData.Add(2000, new string[] { "와!:1", "이 호수는 정말 아름답지?:0", "사실 이 호수에는 무엇간의 비밀이 숨겨져있다고 해.:1"});
talkData.Add(100, new string[] { "평범한 나무상자다" });
talkData.Add(200, new string[] { "누군가 사용했던 흔적이 있는 책상이다" });
portraitdata.Add(1000 + 0, portraitdata[0]);
portraitdata.Add(1000 + 1,portraitdata[1]);
portraitdata.Add(1000 + 2,portraitdata[2]);
portraitdata.Add(1000 + 3,portraitdata[3]);
portraitdata.Add(2000 + 0, portraitdata[4]);
portraitdata.Add(2000 + 1, portraitdata[5]);
portraitdata.Add(2000 + 2, portraitdata[6]);
portraitdata.Add(2000 + 3, portraitdata[7]);
}
public string GetTalk(int id, int talkIndex)
{
if (talkIndex == talkData[id].Length)
return null;
else
return talkData[id][talkIndex]; //id로 대화 get talkIndex로 대화의 한 문장을 가져옴
}
public Sprite GetPortrait(int id, int portraitIndex)
{
return portraitdata[id + portraitIndex];
}
}
gamemanger는
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameManger : MonoBehaviour
{
public Talkmanger talkManger;
public GameObject talkPanel;
public Image PortraitImg;
public Text talkText;
public GameObject scanObject;
public bool isAction;
public int talkIndex;
public void Action(GameObject scanObj)
{
scanObject = scanObj;
Objdata objdata = scanObject.GetComponent();
Talk(objdata.id, objdata.isNpc);
talkPanel.SetActive(isAction);
}
void Talk(int id, bool isNpc)
{
string talkData = talkManger.GetTalk(id, talkIndex);
if(talkData == null)
{
isAction = false;
talkIndex = 0;
return; //void함수에서 return은 함수종료
}
if (isNpc)
{
talkText.text = talkData.Split(':')[0]; //split();구분자를 통하여 배열로 나눠주는 문자열 함수
PortraitImg.sprite = talkManger.GetPortrait(id, int.Parse(talkData.Split(':')[1]));
//parse():문자열을 해당 타입으로 바꿔주는 함수,문자열 내용이 타입이랑 맞지 않으면 문제 발생
PortraitImg.color = new Color(1, 1, 1, 1);
}
else
{
talkText.text = talkData;
PortraitImg.color = new Color(1, 1, 1, 0);
}
isAction = true;
talkIndex++;
}
}
이렇게작성했습니다.어떤 부분이 문제가 있는건가요 ㅠ
아 해결했습니다.스프라이트 이미지 바꿀때 portraitArr[]로 해야하는데 자동완성때문에 portraitdata[]로 했네요 ㅠㅠ
영상 잘보고갑니다~! 스크립트 짜는 부분이 아직 이해가 다 안되서..차근차근 다시 첨부터 영상보고 직접 하고 반복하면서 제껄로 만들어야 겠네요! 진짜 큰 도움이 됩니다!~
골드메탈님 혹시 isaction이 바꿔도 ui가 안사라지는데 어떻게 해야 하나요?
실제로 비활성화 하는 로직은 Action의 talkPanel.SetActive(isAction); 이니까
이 로직 위에 Debug.Log(isAction);을 둬서 어떻게 흘러가는지 콘솔창으로 확인해보세요
@@goldmetal 아 다른 이미지를 gamemanager에 넣었네요...
항상 좋은 강의 올려주셔서 정말 감사합니다.
11분 대화 시스템 코드 다적고 게임 오브젝트 Game manager 스크립트에 Telk Manager 빈칸에 텔크 매니저가 안넣어지는데 어떻게 해야할까요
NullReferenceException: Object reference not . . . 이러면서 GameObject 34,27
PlayerMove 73
콜솔보면 저런 오류가 뜨고 분명 뭔가 놓치고 안적은거 같아서 몇번 영상 다시보고 혹시 저처럼 오류난사람있나 댓글도 찾아보는데 도저히 모르겠어요ㅠㅠ
스크립트를 선택하지 마시고 Scene에 올라와있는 GameMananger를 선택하시고 변수에 TalkManager 오브젝트를 넣으셔야 합니다.
@@goldmetal 답변 감사합니다 문제를 해결했습니다. 이제 열심히 해보겠습니다!👍
29:13 여기서 저걸 썼더니 Assets\Scripts\TalkManager.cs(33,36): error CS1503: Argument 2: cannot convert from 'UnityEngine.Sprite' to 'UnityEngine.Sprite[]' 라는 오류가 뜨는데 어떻게 해결해야 되나요?
portraitArr 만 넣으시면 안되고 번지수까지 들어간 portraitArr[1] 이런식으로 넣어주셔야 합니다.
@@goldmetal 이미 그렇게 넣은 상태인데요...
@@yuriru 그럼 선언하실 때 데이터타입을 Sprite[]로 잘못 선언하셨는지 확인해보세요.
@@goldmetal 감사합니다!
구분자 사용할 때 문자 리러럴에 문자가 너무 많다고 나오는데 무엇이 문제일까요...
아 해결됐습니다. ' : '을 ':'로 바꾸니 에러가 안뜨네요;; ㅎ
지난번꺼랑 이어서 엄청 유용하네요! 감사합니다ㅠ
그럼 Dictionary 와 2차원 배열의 차이는 뭔가요?
또 Dictionary 라면 배열을 설정하지 않으면 오히려 한 페이지에 대해 한 정보밖에 저장하지 못하니 오히려 효율이 떨어지지 않나요?
P.S 분명 어떨땐 2차원배열이 좋고 어떨땐 Dictonary가 좋겠지만 아직 잘 몰라서요.
배열은 Index기반의 컬렉션입니다.
크기가 정적으로 정해져 있고 데이터 접근을 Index로 합니다.
딕셔너리는 Key기반 컬렉션으로,
크기가 유동적이며 데이터 접근을 Key로 합니다.
관리를 어떻게 하냐에 따라 두 방식 중 하나를 고르시면 됩니다.
한 대화에 여러 문장이 있으니 말씀하신 대로 2차원배열로 하면
Index 기반으로 쉽게 접근이 가능하나, 대화 데이터가 늘어나면 배열 크기를 재설정해줘야 하는 점, 대화마다 Index가 무엇인지 기록해야 한다는 점이 있습니다.
딕셔너리는 크기가 유동적이라 크기 지정을 신경쓸 필요가 없고, 대화에 연결된 key를 숫자가 아닌 문자열로 가능해서 ("주인공첫대사" 이런식) 관리가 2차원배열보다 수월합니다. 다만 2차원 배열처럼 여러 데이터를 넣지 못하는 문제가 있지만, 대화데이터는 어짜피 문자열이므로 구분자(:, /,@ 등)만 정하면 얼마든지 잘라서 여러 문장으로 만들 수 있습니다.
초상화의 다른 표정을 불러온후 portraitImg.color = new Color(1, 1, 1, 1); 의 영향을 받지않습니다.... 무슨문제일까요....?
Color(1,1,1,1)은 원본색상 하얀색을 뜻하는 것입니다. 이미 보이고 있다면 효과가 없는 것 처럼 보일거에요
@@goldmetal 1,1,1,0 값도 영향을 안받아서 다른 방법으로 해결했습니다. 답변 감사합니다!
저만 겪는건지 모르겠는데, 대화를 걸다보면 rayhit가 collider 맞으면 활성화되는걸로 아는데, collider에 그 ray가 살짝 겹치는 경우가 있습니다. 그런데 이경우에는 스페이스바를 처음 누르면 대화창은 열리는데, 대화창이 열린 후 스페이스 바를 눌러도 다음 활동 (대화창나가기와 움직임활성화)가 활성화 되지를 않습니다. 어떻게 해결하나요?
+ 비슷한경우로 위에있는 캐릭터에게 대화를 건네는 찰나의 순간에 오른쪽 방향키를 누르면 ray가 오른쪽으로 바뀌어서 다음으로 진행이 안됩니다.
17:42 이런 것 처럼 Talk 했을 시 대화 내용이 없다면 isAction = false 가 되어야 합니다.
GameManager 20번째 줄에 Debug.Log(isAction); 을 놓고 정상적으로 로그가 나오는지 확인해보세요
@@goldmetal 감사합니다 항상 잘보고있어요!
portaitData.Add(1000 + 0, protraitArr[0]);
심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류 CS1503 2 인수: 'UnityEngine.Sprite'에서 'UnityEngine.Sprite[]'(으)로 변환할 수 없습니다. Assembly-CSharp D:\01_유니티\골드메탈-유니티 기초[3]\Assets\C#\TalkManager.cs 26 활성
라고 오류가 뜨네요 저는 스프라이트 변수를 배열로 선언했는데 왜 이녀석은 배열이 아닌 단수로 인식하는지 궁금합니다.
토크 메니저 전체 코드는
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TalkManager : MonoBehaviour
{
Dictionary talkData;
Dictionary portaitData;
public UnityEngine.Sprite[] portraitArr;
private void Awake()
{
talkData = new Dictionary();
portaitData = new Dictionary();
GenerateData();
}
void GenerateData()
{
talkData.Add(1000, new string[] { "안녕?:0", "이 곳에 처음 왔구나?:1" });
talkData.Add(2000, new string[] { "안녕?:0", "이 곳에 잘 왔어:1", "이 호수는 정말 아름답지?:0", "사실 이 호수에는 무언가의 비밀이 숨겨져 있다고 해.:1" });
talkData.Add(200, new string[] { "평범한 나무상자다." });
talkData.Add(300, new string[] { "누군가 사용한 흔적이 있는 책상이다." });
portaitData.Add(1000 + 0, portraitArr[0]);
portaitData.Add(1000 + 1, portraitArr[1]);
portaitData.Add(1000 + 2, portraitArr[2]);
portaitData.Add(1000 + 3, portraitArr[3]);
portaitData.Add(2000 + 0, portraitArr[4]);
portaitData.Add(2000 + 1, portraitArr[5]);
portaitData.Add(2000 + 2, portraitArr[6]);
portaitData.Add(2000 + 3, portraitArr[7]);
}
public Sprite GetPortrait(int id, int portraitIndex)
{
return portaitData[id + portraitIndex];
}
public string GetTalk(int id, int talkindex)
{
if(talkindex == talkData[id].Length)
{
return null;
}
else
{
return talkData[id][talkindex];
}
}
}
입니다.
Dictionary portaitData;
여기서는 Sprite 배열이 아니라 단일이어야 합니다.
Dictionary portaitData;
@@goldmetal 감사합니당!
NullReferenceException: Object reference not set to an instance of an object
TalkManager.GetTalk (System.Int32 id, System.Int32 talkIndex) (at Assets/Script/TalkManager.cs:25)
GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Script/GameManager.cs:33)
GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/Script/GameManager.cs:26)
PlayerAction.Update () (at Assets/Script/PlayerAction.cs:76)
안녕하세요 골드메탈님 항상 잘보고있습니다ㅎㅎ
이번 영상도 열심히 보고 따라하던 도중
인스펙터창에 Talkmanager 변수도 넣고 영상 똑같이 따라했는데
왜 안되는지 도저히 모르겠습니다 ㅜㅜ 시스템에서 알려주는대로 문제해결을 해볼려고 했는데 어떻게 고쳐야할지 모르겠어요
TalkManager 25번줄에 사용중인 변수가 Null, 비어있다는 이야기입니다.
public 변수라면 인스펙터 창을 살펴보세요.
@@goldmetal public string GetTalk(int id, int talkIndex)
{
return talkData[id][talkIndex];
}
return줄이 25번째 줄인데 인스펙터창에서 무엇을 봐야할까요?
@@김아영-n4l talkData 초기화 하셨는지, 함수 호출할 때 매개변수 id 혹은 talkIndex를 Null로 넘겼는지 확인해보셔야 합니다.
public void Action(GameObject scanObj)
{
isAction = true;
scanObject = scanObj;
ObjectData objData = scanObject.GetComponent();
왜 scanObj 정보를 scanObject에 거쳐서 objData에 넣는건가요?
scanObj를 다이렉트로 objData에 넣지 않는 이유라도 있을까요?
ObjectData objData = scanObj.GetComponent();
이처럼 넣어도 동작에는 이상이 없네요
scanObject 변수는 차후에 재사용됩니다. 만약 이게 아니면 말씀하신대로 바로 컴포넌트 가져오셔도 됩니다.
좋아요~~~꾹꾹~~ 특이하게 sprit할때는 쌍따옴표가아니고 홋따옴표로 구분하네요 ㅎㅎㅎ 여러가지 방법으로 처리하는 방식을 알려주시는거같아 도움이 많이 됩니다~~~~~너무 감사드려요~
talkIndex가 1씩 느는게 아니라 2씩 늘고 대화가 다 끝나도 0이 안됩니다. 어떻게 해야 하나요?
한번 누를 때마다 Talk 함수를 두번씩 호출하는건지 Debug.Log("대화"); 를 Talk함수에 넣고 실험해보세요
@@goldmetal 그렇게 해봤는데 1번씩만 호출 됩니다.
20:39 42번줄의 talkIndex++; 말고 다른 ++도 있는지 확인해보세요.
@@goldmetal 없는것 같습니다.
string talkData = talkManager.GetTalk(ID, talkIndex);
if (talkData == null)
{
isACTION = false;
Debug.Log("1");
return;
}
if (npc)
{
talkText.text = talkData;
Debug.Log(usetime);
}
else
{
talkText.text = talkData;
Debug.Log(usetime);
}
isACTION = true;
talkIndex++;
이렇게 되어 있어요
@@jadelee0703 게임 플레이 후 인스펙터 창에서 실제로 talkIndex값이 0에서 2로 뛰는 걸 확인하신건가요? 함수 호출이 두번 일어난게 아니라면 이 정보로는 원인 예측하기가 힘듭니다.
다른 npc를 추가하려고 오브젝트 추가하고 오브젝트에 objdata넣고 Tlakmanager에서 talkData로 대사 넣고 했는데 오브젝트 스캔이 안 되네요.
뭐가 문제일까요?
새로 추가된 NPC의 태그 확인해보세요
@@goldmetal 감사합니다 선생님 layer를 object로 바꾸니까 해결됐습니다
썸네일에 플레이어 머리가 몸통인줄 알고 뭔 헐크인가 이랬음ㅋㅋㅋ
안녕하세요 골드 메탈님 오늘도 영상 잘 보고 있습니다.
구글신에게 그냥 이미지 바꾸는법 검색했을때는 나오지 않던 딕셔너리 너무 놀라웠는데요!!
예를들어 똑같은 스프라이트 5개를 쓰는 오브젝트 5개가 상황에따라 각각 다른 모양이 나와야할때
a.add( 1 + 0 , spt[0]);
a.add( 1 + 1 , spt[1]);
a.add( 1 + 2 , spt[2]);
a.add( 1 + 3 , spt[3]);
a.add( 1 + 4 , spt[4]);
a.add( 2 + 0 , spt[0]);
a.add( 2 + 1 , spt[1]);
a.add( 2 + 2 , spt[2]);
a.add( 2 + 3 , spt[3]);
a.add( 2 + 4 , spt[4]);
a.add( 3 + 0 , spt[0]);
a.add( 3 + 1 , spt[1]);
a.add( 3 + 2 , spt[2]);
a.add( 3 + 3 , spt[3]);
a.add( 3 + 4 , spt[4]);
이렇게 사용하면 너무 비효율적일것같아서요
좀더 효율적으로 사용할방법이있을까요?
이 이상은 XML ,JSON으로 초상화 정보 '초상화이름' - '초상화Index' 를 파일로 저장하고 유니티 내에서 불러온 다음 for문으로 딕셔너리에 저장해서 사용해야 합니다.
JSON의 사용 법은 아래 링크로 전달해드릴께요.
wergia.tistory.com/164
Set native size가 원본크기로 맞추는건가요
네 그렇답니다
대화를 할려고 하면 KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0)
TalkManager.GetTalk (System.Int32 id, System.Int32 talkIndex) (at Assets/Scripts/TalkManager.cs:44)
GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Scripts/GameManager.cs:31)
GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/Scripts/GameManager.cs:21)
PlayerAction.Update () (at Assets/Scripts/PlayerAction.cs:71) 콘솔창에 경고가 뜨고 해당 오류가 발생하는데 표시된 스크립트를 가도 원인을 못 찾겠어요...ㅠ
GetTalk 에 사용한 id 값이 TalkData에 없어서 그렇습니다.
GetTalk 에 Debug.Log()를 추가하고 로그 확인해서
처음 TalkData 넣는 데이터 확인해보세요.
@@goldmetal 네! 확인해보겠습니다~!
와우 빠른편집
NullReferenceException: Object reference not set to an instance of an object
GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/C#/GameManager.cs:57)
GameManager.Act (UnityEngine.GameObject scanObj) (at Assets/C#/GameManager.cs:24)
PlayerAct.Update () (at Assets/C#/PlayerAct.cs:97)
라고 떴는데 더블클릭 해보니까
void Talk(int id, bool isNpc)
{
string talkData = talkManager.GetTalk(id, talkIndex);
if (talkData == null)
{
isActing = false;
talkIndex = 0;
return;
}
if (isNpc)
{
talkText.text = talkData.Split('@')[0];
portraitImg.sprite = talkManager.GetPortrait(id, int.Parse(talkData.Split('@')[1]));
portraitImg.color = new Color(1, 1, 1, 1);
}
else
{
talkText.text = talkData;
portraitImg.color = new Color(1, 1, 1, 0);
}
여기 부분에서 portraitImg.color = new Color(1, 1, 1, 0)에 문제가 있다는데 어떻게 해야할까여
또 NPC랑 대화하면
portraitImg.sprite = talkManager.GetPortrait(id, int.Parse(talkData.Split('@')[1]));
에 문제가 있다네욤..ㅠㅠ 처음에 대충 들었을땐 넘어갔는데 왜 제대로 들을 때엔 오류가 생기는 건지...
알고보니 제가 게임 매니저 인스펙터 창에 포트레이트 이미지를 안 넣었었네요!
ㅎㅎ
골드메탈님 강의는 저처럼 복습 할 정도로 명강의라 생각합니다!!
골드메탈님 항상 잘보고있습니다. 영상을 보고 그대로 따라하고 있는도중에 제 화면에서는 UI에 있는 도트크기가 플레이 공간과 다르게 보여서 살짝 불편한데 혹시 이걸 맞출 수 있는 방법이 있을까요? 16으로 해서 다 똑같이 맞추면 될줄알았는데 UI창만 유독 도트 크기가 커졋네요
스텐다드를 누르면 통일이 되긴하는데 다른걸누르면 통일이 안되네요
UI는 Canvas Scaler 컴포넌트가 있어서 인 게임과 크기가 다를 수 있습니다. 제일 쉬운건 Pixel Per Unit을 다르게 주는 방법이지 않을까 싶네요.
@@goldmetal 답변감사합니다!
몇시간 인터넷에서 답을 찾다가.. 안되서 질문남깁니다..
에러내용 : --------------------------------------------------------------------------------------------------------------------------
KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at :0)
TalkManager.GetPortrait (System.Int32 id, System.Int32 portraitIndex) (at Assets/Scripts/TalkManager.cs:46)
DIalogManager.Talk (System.Int32 id, System.Boolean bo_isNPC) (at Assets/Scripts/DIalogManager.cs:47)
DIalogManager.Action (UnityEngine.GameObject scanObject) (at Assets/Scripts/DIalogManager.cs:23)
PlayerAction.Update () (at Assets/Scripts/PlayerAction.cs:73)
--------------------------------------------------------------------------------------------------------------------------
현재 해당 오류인데..
이게 NPC A에게 대화할때는 초상화이미지랑 대화내용 잘 유추해서 가져오는데
NPC B에게 대화를 할때만 해당 에러가 발생하면서 멈추네요.
앞뒤로 Debug.Log 찍어봤는데
딱 ObjectData objData = scanObject.GetComponent(); 이코드에서 에러가 발생합니다.
여기서 NPC B의 초상화 이미지도 제대로 추가해두었고 Object ID의 값은 제대로 입력이 되어있으며, isNPC도 잘 체크되어있습니다.
NPC A를 복사해서 생성했던 것이기에 모든게 동일하며, 비교했을때도 특이사항 확인하지 못했습니다.
너무답답해서 댓글남기는데 혹시 어떤문제인지 알고계시거나
아니면 어떤걸 더 확인해보면 되는지 답변부탁드립니다.
참고로 유니티프로그램은 수십번 종료했다 재실행시켜봤습니다...
항상 잘 시청하고 있습니다. 감사합니다.
일단 에러 내용은 대화 데이터를 저장하는 딕셔너리에서
없는 Key값을 가져오려 할 때 문제다는 것인데요,
대화 데이터를 가지고 오기 전 보내는 key값을 Debug.Log()로 찍어보시고
그 값이 딕셔너리에 적어둔 키가 맞는지 확인이 필요하겠습니다.
TalkManaager 의 GetTalk에서 Debug.Log(id); 를 해보세요
@@goldmetal 역시나 예상했지만 엉뚱한 곳에 문제가 있었네요.. 그래도 골드메탈님 덕분에!! 찾았습니다. Dictionary에 저장해둔 대화값에서 뒤에 portrait로 지정해둔 번호가 문제였습니다 ㅠㅠ 연결한 번호는 0,1,2,3인데 뒤에 배열의 인자값번호를 대화목록에 설정해두는 바람에 없는 번호를 불러오면서 에러를 발생시켰었네요... 하 왜 저게 눈에 안띄었는지 참 멍청했습니다. 그래도 에러 찾으면서 코드 다시한번 훑어보느라 복습은 제대로 한 것 같습니다. 항상 좋은 영상 남겨주셔서 감사합니다!! 앞으로도 가끔 질문 댓글 남길것 같은데 그때도 잘부탁드립니다 ㅋㅋㅋㅋㅎㅎㅎㅎ
잘 보고 따라했습니다! 구현은 성공했지만 이번 대화 시스템은 꽤나 난이도가 있어 여러번 돌려봐야겠어요. 나중에 게임 만들 때도 사용하기 좋을 것 같아요! d(^^)b
언제나 좋은 강의 감사합니다.
제가 강의를 보면서 따라하고 있는데 여자 NPC는 정상적으로 UI가 작동하는데 남자 NPC와 대화를 시도하면 오류가 뜹니다. 혹시 어떻게 해결해야 할까요. 게임,토크 매니저 인스펙터가 안비어있는거 확인했고 isnpc도 체크 하였습니다. 오류 내용은 아래와 같습니다
FormatException: Input string was not in a correct format.
System.Number.StringToNumber (System.String str, System.Globalization.NumberStyles options, System.Number+NumberBuffer& number, System.Globalization.NumberFormatInfo info, System.Boolean parseDecimal) (at :0)
System.Number.ParseInt32 (System.String s, System.Globalization.NumberStyles style, System.Globalization.NumberFormatInfo info) (at :0)
System.Int32.Parse (System.String s) (at :0)
GameManager.Talk (System.Int32 id, System.Boolean isNpc) (at Assets/Script/GameManager.cs:43)
GameManager.Action (UnityEngine.GameObject scanObj) (at Assets/Script/GameManager.cs:21)
Player.Update () (at Assets/Script/Player.cs:65)
감사합니다. 좋아요 꾸욱
문자열을 숫자형태로 변형하는데 실패했다는 이야기입니다.
게임매니저 스크립트 43번재 줄에서 문자열 값을 한번 Debug.Log()로
확인해보시는게 좋겠습니다.