-
으어어어어어어 어제 못적었네요 ㅠㅠ
어제 개인과제 풀이가 나왔는데 제가 하는 방법이랑 다르게 하셔서 좀 더 힘들었던 것 같습니다. 그래도 도움이 많이 되었어요!
처음 시작은 코드카타입니다.
행렬의 덧셈
int[,] answer = new int[arr1.GetLength(0),arr1.GetLength(1)]; for(int i =0 ; i<arr1.GetLength(0); i++){ for(int j=0;j<arr1.GetLength(1);j++){ answer[i,j]=arr1[i,j]+arr2[i,j]; } }
2차원 행렬을 서로 더하는 함수입니다.
그냥 Length를 하는 경우에는 모든 요소에 대한 길이를 가져옵니다.
행과 열 따로 길이를 가져오기 위해서는 GetLength를 사용해줘야합니다.
int[ , ] = { { } } 에서
GetLength(0) : { } 안에 있는 { }의 갯수
GetLength(1) : { { } } 안에 있는 값들 갯수
필수 요구사항
1. 캐릭터 만들기 : [완]
2. 캐릭터 이동 : [완]
3. 방 만들기 : [완]
4. 카메라 따라가기
void Update() { transform.position = new Vector3(player.transform.position.x,player.transform.position.y, transform.position.z); }
Main Camera에 Component.Add(Camera Controller.cs) 해주었습니다.
카메라의 position을 player.position에 맞게 하기 위해서 update에 넣어주었습니다. z의 경우에는 카메라 position을 그대로 넣어줘서 화면에 모든 게임요소들이 제대로 나올 수 있도록 해줬습니다.
5. 캐릭터 애니메이션 추가
Animation을 만들어서 movement에서 입력받을 때마다 IsWalking = true로 해서 애니메이션이 실행되도록 해줬습니다.
Transitions에서 solo를 true해줬는데 이유는 상하좌우를 움직일 때 있는 약간의 텀에 바로 idle로 이동해서 walk가 제대로 실행되지 않는 경우가 발생하여 선택해주었습니다.
private static readonly int IsWalking = Animator.StringToHash("IsWalking"); private void Move(Vector2 obj) { animator.SetBool(IsWalking); }
StringToHash를 해준 이유는 String을 처리하는 과정이 오래걸리기 때문에 처리하는 과정 시간을 줄이기 위해서 Hash로 변환해줍니다.
Move는 OnMoveEvent를 구독하고 있고, 따라서 움직임이 있다면 Move에 값이 들어오면서 IsWalking = true가 됩니다.
6. 이름 입력 시스템
첫 화면에서 이름을 입력받아서 캐릭터 위에 이름을 띄워줍니다.
새로운 Scene을 만들어줘서 캐릭터 이름을 받아줍니다.
scene을 Load해서 다른 scene으로 넘어갈 때에는 원래 scene에 있던 모든 데이터들이 삭제됩니다.
따라서 입력 받을 때 특별하게 저장해서 전달해줘야합니다.
캐릭터 이름을 받기 위해서는 'Input Field'를 사용해줬습니다.
Input Field는 종류가 두 가지가 있는데 Input Field - Text Mesh pro를 사용할 경우 변수타입은 TMP_InputField을 해줘야지 입력받을 수 있다. Text Mesh Pro를 사용하지 않으려면 Legacy에 있는 Input Field를 사용해줘야한다.
private string name = inputName.text;
이름을 입력을 받으면 저장해야합니다. 위에 적었던 것처럼 scene이 바뀌면 저장된 값들도 사라지기 때문에 사라지지 않도록 만들어줍니다.
PlayerPrefs.SetString("Name", name);
PlayerPrefs는 Key 값에 저장할 값을 저장해서 가지고 있습니다. PlayerPrefs는 scen이 바뀌어도 저장된 값이 사라지지 않기 때문에 string, int의 경우 저장이 가능합니다.
playerNameText.text = PlayerPrefs.GetString("Name");
PlayerPrefs에 저장한 값은 Get과 Key를 이용해서 불러올 수 있습니다.
7. 캐릭터 선택 시스템
처음 화면에서 캐릭터를 선택해서 메인화면으로 가져오게 됩니다.
public enum CharacterType { Penguin, Wizzard } [Serializable] public class Character { public CharacterType characterType; public Sprite CharacterSprite; public RuntimeAnimatorController controller; }
선택할 수 있는 캐릭터의 종류를 CharaterType으로 설정하고 캐릭터의 이미지와 애니메이션을 받아옵니다.
class의 경우 public을 해줘도 inspector에 나오지 않기 때문에 serializable을 해줘야합니다. enum은 필요없습니다.
Character를 List로 만들어서 캐릭터 종류마다 이미지와 애니메이션을 받아줍니다.
그러면 선택한 캐릭터가 무엇인지 어떻게 알 수 있는지가 의문입니다.
public void ChangeImage(int index) { this.index = index; selectPlayer.GetComponent<Image>().sprite = characterList[index].CharacterSprite; selectBoard.SetActive(false); }
캐릭터를 누르면 캐릭터 선택창이 사라져야하기 때문에 button component를 추가해줍니다.
이때 button을 누르면 실행되어야하는 함수에 매개변수를 설정해줍니다.
이 매개변수는 inspector에서 설정이 가능하며, 설정된 값을 매개변수로 가져와서 함수에 적용시킬 수 있습니다.
선택된 캐릭터를 MainScene으로 가져가야합니다. PlayerPrefs를 사용하기 위해서는 string 또는 int만 가능하기 때문에 입력된 매개변수 int를 저장시켜줍니다. 이럴 경우에는 MainScene에서도 첫 scene에서 사용된 characterList를 똑같이 설정해줘야합니다.
public List<Character> characterList = new List<Character>(); private void Start() { private int selectCharacter = PlayerPrefs.GetInt("Index"); ChangedCharacter(selectCharacter); } public void ChangedCharacter(int index) { MainCharacter.GetComponent<SpriteRenderer>().sprite = characterList[index].CharacterSprite; MainCharacter.GetComponent<Animator>().runtimeAnimatorController = characterList[index].controller; }
선택한 캐릭터의 index 값을 저장해서 MainScene으로 가져와서 이미지와 애니메이션컨트롤러를 바꿔주면 됩니다.
선택 요구사항
1. 시간 표시
DateTime.Now.ToString("HH:mm");
현재 시간을 24시간으로 설정하고 분은 1자리 수일 경우 앞에 0을 붙이도록 설정했습니다.
2. 인게임 이름 바꾸기
이름 입력 시스템과 똑같이 만들어주면 됩니다. 단, scene이 바뀌지 않기 때문에 PlayerPrefs로 저장할 필요가 없습니다.
public void OnClickChangeName() { GameManager.I.playerNameText.text = GameManager.I.ChangeName.text; GameManager.I.ChangeNameBoard.SetActive(false); }
이름 바꾸는 것 외에도 다양한 버튼을 사용할 것이기 때문에 버튼에 사용할 함수들만 모여두는 class를 만들어줬습니다.
☆GameManager을 다른 클래스에서 사용하기 위해서는 static으로 선언해서 싱글턴으로 만들어줘야합니다.☆
3. 참석 인원 UI : 만들지 않았습니다. 캐릭터 이름을 보여주고 바뀔 때마다 바뀌게 보여주는 것은 쉬울 것 같은데 NPC 쪽이 문제라서.. 시간 상 만들지 못했습니다 ㅠ
4. 인게임 캐릭터 선택
마찬가지로 캐릭터 선택 시스템과 똑같이 만들어주면 됩니다. 당연히 같은 scene이므로 PlayerPrefs로 저장할 필요가 없습니다.
public void OnClickChangeCharacter(int index) { GameManager.I.ChangedCharacter(index); GameManager.I.ChangeCharacterBoard.SetActive(false); }
5. NPC 대화
거리가 멀면 대화할 수 없고 어느 정도 거리에서 대화할 수 있는 버튼이 나오게 만들어줍니다.
public float DistanceToCharacter(GameObject gameObject) { return Vector3.Distance(gameObject.transform.position, MainCharacter.position); }
gameObject는 NPC를 의미합니다.
NPC와 Player간의 거리를 구해줍니다.
private void Update() { if(n_controller.DistanceToCharacter(tutor) < 3f && !OnMessage) { CallBell.SetActive(true); } else { CallBell.SetActive(false); } }
거리에 따라서 대화 버튼이 나올 수 있어야하기 때문에 Update에 넣어줍니다. 이때, Update에 넣게 되면 거리가 가까워 버튼이 나와서 버튼을 누른다고 해도 버튼이 사라지지 않습니다.(대화창이 나오는 상태에서)
그렇기 때문에 !OnMessage로 대화창이 나오고 있지 않다면 대화를 할 수 있는 버튼이 나올 수 있게하고 대화를 하고 있다면 버튼이 나오지 않도록 설정해줬습니다.
버튼을 누르면 대화창이 나오면서 NPC 말이 나오고 거기서 또 버튼을 누르면 메세지창이 사라지도록 했습니다. 이렇게되면 OnMessage가 false이므로 그 자리에서 대화창이 사라지면 다시 대화할 수 있는 버튼이 나올 수 있습니다.
으어어어어어 이번 것은 왤케 시간에 쫓겼는지 모르겠습니다..
사실 시간도 그리 많지는 않긴했는데 ㅠㅠ 아무래도 캐릭터 바꾸는 부분에서 좀 오래 걸렸던 것 같습니다.
내일부터는 팀과제 시작이네요.. 허허허허허허허허헣
팀과제는 얼마나 어려울까.. 걱정입니다..