Unity 입문 - 3 (개인 과제)

이준호·2023년 11월 28일
0

📌 Unity 게임 개발 입문



📌 캐릭터 애니메이션 추가

Animator에서 float값으로 0.1을 기준으로 0.1보다 크거나 작으면 Run 애니메이션이 동작하고 멈추게 하였다.

    private void FixedUpdate()
    {
        // 이동 로직 실행
        ApllyMovement(_movementDirection);

        // Player Animation is Run Check
        playerAnim.SetFloat("Move", _movementDirection.magnitude);
    }

저번 글에서 했던거의 연장선이다.

ApllyMovement(_movementDirection); 는 안에 _movementDirection가 이벤트에 등록되어 있어 키 입력이 들어올 경우만 값이 들어가고 입력이 멈추면 0이 들어가기 때문에 _movementDirection을 .magnitude하여 float값으로 변환하여 애니메이션에 이용했다.






📌 이름 입력 시스템

Input Field를 사용하였다.

위 처럼 Input Field를 사용하여 입력값을 받는다.

public class PlayerInformation : MonoBehaviour
{
    [SerializeField] private InputField playerinputName;
    [SerializeField] private SceneMovement sceneMove;

    private string playerName = null;

    private void Awake()
    {
        playerName = playerinputName.GetComponent<InputField>().text;
    }

    // 플레이어 이름 저장
    public void PlayerInputNameSave()
    {
        // Player Name 2 ~ 10 글자 사이 제한
        if (playerinputName.text.Length > 1 && playerinputName.text.Length < 11)
        {
            // 조건 충족시 이름 저장
            playerName = playerinputName.text;
            // 게임 매니저에 이름 저장
            GameManager.instance.SettingPlayerName(playerName);
            // 씬 이동
            sceneMove.GoMainScene();
        }
    }

}


위에서 입력을 받으면 GameManager에 저장하여 이름 값을 중앙에서 관리하도록 하였다.

public class GameManager : MonoBehaviour
{
    #region Instance
    public static GameManager instance = null;

    private void Awake()
    {
        // instance가 null이라면
        if (instance == null)
        {
            // 자기 자신을 intance에 넣는다.
            instance = this;
            //OnLoad(씬이 로드 되었을때) 자신을 파괴하지 않고 유지
            DontDestroyOnLoad(gameObject);
        }
        // 이미 존재한다면
        else 
        {
            Destroy(this.gameObject);
        }
    }
    #endregion
    
    // 플레이어 이름
    private string playerName;
    // 플레이어 이름 저장
    public void SettingPlayerName(string name)
    {
        playerName = name;
    }

    // 플레이어 이름 불러오기
    public string OutputPlayerName()
    {
        return playerName;
    }





📌 캐릭터 선택 시스템

// GameManager.cs
// 생략

    private void Start()
    {
        Initalize();
    }

    // 캐릭터 정보
    private GameObject kngiht;
    private GameObject wizzard;

    // 캐릭터 선택 정보
    private int characterIndex = 0;
    
    private void Initalize()
    {
        kngiht = Resources.Load<GameObject>("Prefabs/PlayerKnight");
        wizzard = Resources.Load<GameObject>("Prefabs/PlayerWizzard");
    }
    #endregion

    // 플레이어 이름 저장
    public void SettingPlayerName(string name)
    {
        playerName = name;
    }

    // 플레이어 이름 불러오기
    public string OutputPlayerName()
    {
        return playerName;
    }

    // Knight 선택
    public void KnightChoice()
    {
        characterIndex = 0;
    }

    // Wizzard 선택
    public void WizzardChoice()
    {
        characterIndex = 1;
    }

    public void InvokeCharacter()
    {
        if (characterIndex == 0) 
        {
            Instantiate(kngiht);
            //Destroy(wizzard);
        }
        else if (characterIndex == 1) 
        {
            Instantiate(wizzard);
            //Destroy(kngiht);
        }
    }

캐릭터를 선택하고 그 정보를 가지고 다음 씬으로 넘어가면 Prefab화 해둔 캐릭터를 그 고른 값에 맞게 Instantiate하여 클론을 찍어내도록 하였다. ( 나중에 MainScene에서 캐릭터 변경을 위한 설계 )

Resources.Load를 이용하여 드래그&드롭 으로 할당하는게 아닌 스크립트로 정보를 얻게했다.






public class CameraTransform : MonoBehaviour
{
    [SerializeField] private GameObject player;


    private void Start()
    {
        player = GameObject.FindWithTag("Player");
    }

    public void LateUpdate()
    {
        transform.position = new Vector3(player.transform.position.x, player.transform.position.y, -10);
    }
}

캐릭터는 MainScene에 넘어가면 CharacterIndex를 가지고 클론은 찍어내기에 prefab에 태그를 걸어주어 메인씬이 셋팅될 때 camerafollow에 할당해주고 player를 따라다니게 하였다.






📌 참석 인원 UI

public class MainSceneSetting : MonoBehaviour
{
    // 접속자 명단 리스트
    [SerializeField] private List<GameObject> personnel = new List<GameObject>();

    private void Awake()
    {
        // 선택한 캐릭터 생성
        GameManager.instance.InvokeCharacter();
    }

    private void Start()
    {
        for (int i = 0; i < personnel.Count; i++)
        {
            // GameManager에 NPC이름 저장
            GameManager.instance.NPCNameSave(personnel[i].transform.GetChild(0).GetComponent<TextMesh>().text);
        }
    }
}

MainSceneSetting.cs에서 npc들의 이름을 GameManager로 옮겨 저장했다.






// GameManager.cs
// 생략

    // NPC 이름
    private List<string> npcNames = new List<string>();
    
    // NPC 이름 저장
    public void NPCNameSave(string name)
    {
        npcNames.Add(name);
    }

    // NPC 이름 불러내기
    public string[] OutPutNPCName()
    {
        string[] outName = new string[npcNames.Count];
        for(int i = 0; i < npcNames.Count; i++)
        {
            outName[i] = npcNames[i];
        }
        return outName;
    }

GameManager에서 Npc의 이름을 관리하고 뿌릴수 있게 해두었다.






public class MainUIManager : MonoBehaviour
{
    public Text personUI;

    //private void Awake()
    //{
    //    personUI = GetComponent<Text>();
    //}

    private void LateUpdate()
    {
        
    }

    // 접속자 명단 업데이트
    public void NameSetting()
    {
        string[] npcNames = GameManager.instance.OutPutNPCName();
        string playerName = GameManager.instance.OutputPlayerName();

        // 명단 초기화
        personUI.text = "";

        personUI.text += " ::접속자 명단:: \n\n";
        
        foreach (string npcName in npcNames) 
        {
            personUI.text += " " + npcName + "\n\n";
        }

        personUI.text += " " + playerName;
    }
}

MainUIManager에서 GameManager에 있는 NPC의 이름들을 가져와 표시할 Text에 함수가 불릴 때 마다 호출하도록 하였다.

NPC들을 Prefab화 하여 관리하고 씬이 불려올 때 List를 셋팅해주고 싶은데 시간이 없어서 시간이 남으면 해볼려고 한다.






📌 인게임 캐릭터 선택

// MainUIManager.cs
// 생략

    // 캐릭터 재선택
    public void KnightSelect()
    {
        GameManager.instance.KnightChoice();
    }

    public void WizzardSelect()
    {
        GameManager.instance.WizzardChoice();
    }

    public void SelectCharacter()
    {
        GameManager.instance.InvokeCharacter();
        Invoke("PlayerNameSetting", 0.1f);
    }

    // 바뀐 캐릭터에 이름 적용
    public void PlayerNameSetting()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        player.transform.GetChild(1).GetComponent<TextMesh>().text = GameManager.instance.OutputPlayerName();
    }

    // 원래 캐릭터 파괴
    public void CheckDestory()
    {
        beforeCharacter = GameObject.FindGameObjectWithTag("Player");
        Destroy(beforeCharacter);
    }

각각 메서드들을 캐릭터 선택에 맞는 버튼에 넣어 원래 있던 오브젝트는 파괴시키고 카메라 및 이름을 다시 달아주게 하였다.






📌 인게임 이름 바꾸기

위처럼 이름바꾸기 버튼을 눌러 이름을 입력한 뒤에 Chanage버튼을 누르면 이름이 바뀌게 하였다.

원래 StartScene에서 사용했던 패널을 그대로 들고와 씬이동같은 필요없는 기능만 빼고 이름을 바꾸면 이름을 다시 로드해주는 식으로 사용하였다.

한가지 문제점으로 이름을 바꾸려고 입력을 할 때에 뉴인풋시스템 때문에 입력이 들어가 캐릭터가 움직였는데, 이름 바꾸기 버튼을 누르면 Time.timeScale을 0으로 만들고 창을 끄거나 체인지를 하면 Time.timeScale을 1로 만들어주어 입력을 방지했다.






📌 시간 표시

좌측 상단에 현재 시간과 동일한 시간이 표시되게 해줬다.

public class DeltaTimeNow : MonoBehaviour
{
    private Text timeText;

    private void Awake()
    {
        timeText = transform.GetComponent<Text>();
    }

    private void Update()
    {
        timeText.text = GetCurrentDate();
    }

    public static string GetCurrentDate()
    {
        return DateTime.Now.ToString(("HH : mm"));
    }
}

text UI를 만들어 위에 스크립트를 넣어줘서 시간과 분까지 나오는 현재시간이 나오게 했다.

profile
No Easy Day

0개의 댓글