쯔꾸르식 유니티 게임 공부

10.5 추가설명

ruripanda 2025. 1. 14. 23:32

using System.Collections;
using UnityEngine;

public class MovingObjcet : MonoBehaviour
{ 
    //케릭터 이동속도
    public float speed;
    //픽셀 단위로 움직이기 구현
    public int walkCount;
    protected int currentWalkCount;

    protected bool npcCanMove = true;
    //벡터(케릭터의 이동 방향)
    protected Vector3 vector;//protected는 부모자식간에 참조는 가능하지만 인스펙터창과 외부클레스는 접근불가
    public BoxCollider2D boxCollider;//박스콜라이더
    public LayerMask layerMask;//통과불가 에이리어 설정
    public Animator animator;//애니메이터

    protected void Move(string _dir, int _frequency)
    {
        npcCanMove = false;
        StartCoroutine(MoveCoroutine(_dir, _frequency));
    }

    IEnumerator MoveCoroutine(string _dir, int _frequency)
    {
        vector.Set(0, 0, vector.z);
        switch (_dir)
        {
            case "UP":
                vector.y = 1f;
                break;
            case "DOWN":
                vector.y = -1f;
                break;
            case "RIGHT":
                vector.x = 1f;
                break;
            case "LEFT":
                vector.x = -1f;
                break;
        }

        //에니메이터 불러오기
        animator.SetFloat("DirX", vector.x);
        animator.SetFloat("DirY", vector.y);
        animator.SetBool("Walking", true);

        while (currentWalkCount < walkCount)
        {
            transform.Translate(vector.x * speed, vector.y * speed, 0);
            currentWalkCount++;
            yield return new WaitForSeconds(0.01f);
        }
        currentWalkCount = 0;
        if (_frequency != 5)
        {
            animator.SetBool("Walking", false);
        }
        animator.SetBool("Walking", false);
        npcCanMove = true;
    }
    protected bool CheckCollsion()
    {
        RaycastHit2D hit;//레이케스트

        Vector2 start = transform.position; //캐릭터의 현제 위치 값
        Vector2 end = start + new Vector2(vector.x * speed * walkCount, vector.y * speed * walkCount);
        //캐릭터가 이동하고자하는 위치 값 그리고 사이즈

        boxCollider.enabled = false;
        hit = Physics2D.Linecast(start, end, layerMask);
        boxCollider.enabled = true;

        if (hit.transform != null)
            return true;
        return false;
    }
}

 

using System.Collections;
using UnityEngine;

public class PlayerManager : MovingObjcet
{
    static public PlayerManager instance;

    //public string currentMapName;
    
    public string walkSound_1;
    public string walkSound_2;
    public string walkSound_3;
    public string walkSound_4;

    private AudioManager theAudio;

    //public AudioClip walkSound_1;//사운드 파일
    //public AudioClip walkSound_2;

    private AudioSource audioSource;//사운드 플레이어

    //뛰기,평범하게 걷기
    public float runSpeed;
    private float applyRunSpeed;
    private bool applyRunFlag = false;

    

    //한칸한칸 이동할때 플레그 형식으로 구현
    private bool canMove = true;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        if (instance == null)
        {
            DontDestroyOnLoad(this.gameObject);
            boxCollider = GetComponent<BoxCollider2D>();
            //audioSource = GetComponent<AudioSource>();
            animator = GetComponent<Animator>();
            theAudio = FindAnyObjectByType<AudioManager>();
            instance = this;
        }
        else
        {
            Destroy(this.gameObject);
        }
    }

    //코루틴으로 이동제어 한칸 한칸 이동하게
    IEnumerator MoveCoroutine()
    {
        while (Input.GetAxisRaw("Vertical") != 0 || Input.GetAxisRaw("Horizontal") != 0)
        {
            //시프트 키 입력 여부에 따라 뛰기 걷기 구분
            if (Input.GetKey(KeyCode.LeftShift))
            {
                applyRunSpeed = runSpeed;
                applyRunFlag = true;
            }

            else
            {
                applyRunSpeed = 0;
                applyRunFlag = false;
            }

            //이동방향 벡터 움직임 구현
            vector.Set(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"), transform.position.z);

            //좌상,좌하 등 대각선 방향이동 장금
            if (vector.x != 0)
                vector.y = 0;

            //에니메이터 불러오기
            animator.SetFloat("DirX", vector.x);
            animator.SetFloat("DirY", vector.y);

            bool checkCollsionFlag = base.CheckCollsion();
            if (checkCollsionFlag)
                break;

            animator.SetBool("Walking", true);

            int temp = Random.Range(1, 4);
            switch (temp)
            {
                case 1:
                    theAudio.Play(walkSound_1);
                    break;
                case 2:
                    theAudio.Play(walkSound_2);
                    break;
                case 3:
                    theAudio.Play(walkSound_3);
                    break;
                case 4:
                    theAudio.Play(walkSound_4);
                    break;
            }
            theAudio.SetVolumn(walkSound_2, 0.5f);

            //캐릭터 이동구현 코드
            while (currentWalkCount < walkCount)
            {
                if (vector.x != 0)
                {
                    //Translate는 현제 값에서 +를 해주는 코드
                    transform.Translate(vector.x * (speed + applyRunSpeed), 0, 0);
                }
                else if (vector.y != 0)
                {
                    transform.Translate(0, vector.y * (speed + applyRunSpeed), 0);
                }
                if (applyRunFlag)
                    currentWalkCount++;//위의 applyRunFlas가 되면 추가되는 카운트 만약 아니라면 더해지지 않음
                currentWalkCount++;//위의 카운트와는 별개의 카운트로 구분 됨
                yield return new WaitForSeconds(0.01f);//0.01초마다 대기

                /*if(currentWalkCount % 9 == 2)
                {
                    int temp = Random.Range(1, 2);
                    switch (temp)
                    {
                        case 1:
                            //audioSource.clip = walkSound_1;
                            //audioSource.Play();
                            break;
                        case 2:
                            //audioSource.clip = walkSound_2;
                            //audioSource.Play();
                            break;
                    }
                }*/

            }
            currentWalkCount = 0;//0을 넣어서 반복문 초기화

        }

        animator.SetBool("Walking", false);
        //한칸한칸 이동할때 bool값
        canMove = true;
    }

    //매 프레임마다 이동명령을 받음
    void Update()
    {
        if (canMove)
        {
            //이동 방향키 입력을 할때 쯔구르 처럼 상하좌우 구분하게 하는 코드
            if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
            {
                //한칸 한칸 이동할때 bool값으로 canMove를 이용함
                canMove = false;
                StartCoroutine(MoveCoroutine());
            }
        }
    }
}

 

이번 장에서는 PlayerManager에서 MovingObject에 넣을 함수를 마저 넣을 것이다

 

 

PlayerManager에서 MovingObject에 레이케스트 히트로 쯔구르 처럼 이동하게 하면서 이동에 제한을 걸어주는 부분을 MovingObject를 넣어준다

그리고 원본과 이 부분이 차이가 있으니 수정해준다

 

protected로 인스팩터에는 드러내지 않으면서 스크립트에서는 참조하게 바꿔준다

그리고 bool로 참과 거짓을 나눈다

즉 새로운 함수를 만드는 것이다

 

 

그리고 기존의 레이케스트 히트가 있던 PlayerManager에는 이렇게 적어준다

 

bool checkCollsionFlag = base.CheckCollsion();은

 

임시로 선언해준 함수이고 PlayerManager에는 MovingObject가 참조가 되어 있으니

base.CheckCollsion(); 함수로 호출한다

그 뒤 if(checkCollsionFlag)를 조건문으로 걸어서 true가 되면 트루가 되면서 이동을 멈추가 된다

만약 true가 아니라면 break가 걸리지 않고 아래의 함수가 실행된다