daily debugging

Day 7 (2023.09.25) + 과제 본문

(좋은 개발자로 롱런하는 법)
1년 후에는 게임을 보았을 때, 특정 기능에 대해서 머리에서 다 그려져야 한다. 안 그려지면 공부가 부족했을 확률이 높다. 개발자가 카메라 잘 쓰면 보너스 요소다. 상위 개념을 매우 잘 만들어야 한다.

ex) 모든 충돌체들은 어떤 클래스를 상속받으면 되는가?

ex) 최상위 부모 스크립트에는 무엇이 들어가야 하는가?

ex) 최상위 부모 스크립트간 관계는 어떻게 되는가?

최상위 부모 클래스에서 Update를 구현하면 상속받은 크래스들에서는 Update를 구현하지 않아도 되므로 최적화가 매우 좋다. -강사님 왈-

 

공식문서 참고하기

Awake() - 초기화1

Start() - 초기화2

FixedUpdate() - 물리

Update() - 캐릭터 이동

LateUpdate() - 카메라 이동


과제

벽을 감지하지 못하고 플레이어와 Ai가 일직선상에 있으면 발사하는 것을 해결하여 벽이 사이에 없을 때만 발사하기.

기존의 코드를 최대한 이용하려 노력했다.

//射撃の思考をするか
if( m_shootInterval < 0f) {

    //X、またはZの距離が近い場合、直線上にいると判断して射撃を行う
    if ((Mathf.Abs(aiSubPosition.x) < 1f) || (Mathf.Abs(aiSubPosition.z) < 1f))
    {
        Vector3 target = -aiSubPosition;
        Vector3 start = transform.position + Vector3.up;
        Debug.DrawRay(start, target, Color.yellow);
        Ray ray = new Ray(start, target);
        RaycastHit hit;
        LayerMask mask = LayerMask.GetMask("PlayerAi");
        if (Physics.Raycast(ray, out hit, mask))
        {
            Debug.Log(hit.collider.tag);

            if (hit.collider.CompareTag("Player"))
            {
                //射撃操作
                m_playerInput[(int)PlayerInput.Shoot] = true;

                //次の射撃はこの時間が経過するまで待つ(連射の抑制)
                m_shootInterval = SHOOT_INTERVAL;
            }
        }

    }
}

레이케스트를 이용해 일직선상에서 Ai에서 시작해 플레이어까지 향하는 레이를 발사하고 플레이어가 맞으면 그때 투사체를 발사하도록 작성했다. 여기서 Ai가 자기 자신을 처음으로 ray를 발사할 때 감지하는 것을 막기 위해 Layer를 사용했다. 방법은 다음과 같다.

플레이어 Ai 프리펩에 PlayerAi라는 Layer를 만들어 설정해준다. 이후 프로젝트 세팅에서 물리

PlayerAi PlayerAi끼리 충돌 감지 체크를 해제해준다. 그리고 마지막으로 플레이어 프리팹에 Player라는 태그를 추가해준다.


해당 과제는 달성했으나 보너스 과제를 완수하지 못했다. 플레이어가 죽으면 리셋할 수 있게 만드는 것인데.. 기존의 코드에 어떤 부분이 플레이어가 맞았는가 이용할 수 있는 부분인지 찾지 못했다. 고민하다가 플레이어가 맞을 때 애니매이션은 작동했기에 해당 부분 코드를 찾아보았고 아니나 다를까 거기에 해답이 있었다. 

다음과 같이 맞으면 죽었는지 불값을 갱신해주는 부분에 게임 오브젝트를 비활성화한다는 내용을 추가했다.

그리고

버튼과 빈 오브젝트를 만들어주고 버튼을 비활성화 시켜놓은 다음 빈 오브젝트에 있는 스크립트의 Update에서 플레이어가 비활성화 되었는지 Ai가 비활성화되었는지 확인 후 리스타트 버튼을 활성화시켜준다. 다음과 같다

스크립트 MyButton을 생성

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyButton : MonoBehaviour
{
    GameObject player1;
    GameObject playerAi;
    [SerializeField] GameObject bt;
    // Start is called before the first frame update
    void Start()
    {
        player1 = GameObject.FindWithTag("Player");
        playerAi = GameObject.FindWithTag("PlayerAi");
    }

    // Update is called once per frame
    void Update()
    {
        if(!player1.activeInHierarchy ) 
        {
            playerAi.SetActive(false);
            bt.SetActive(true);
        }
        else if(!playerAi.activeInHierarchy)
        {
            player1.SetActive(false);
            bt.SetActive(true);
        }
    }
}

빈 오브젝트에 해당 스크립트를 넣어주고 Bt변수에 비활성화 활성화 여부를 바꿔줄 버튼을 연결해준다. 그리고 버튼이 눌리면 실행될 함수를 작성할 Reset이라는 스크립트를 만들고

public class Reset : MonoBehaviour
{
    public void ReSetScene()
    {
        SceneManager.LoadScene(0);
    }
}

다음과 같이 씬을 다시 로드하는 함수를 public으로 만든다. 이후 버튼에

다음과 같이 해당 스크립트를 넣어주고 OnClick()에서 해당 함수를 선택해준다. 아 까먹은 것으로 PlayerAi라는 태그를 만들어 Ai 프리팹에 할당해준다.

그럼 다음과 같은 게임이 만들어진다.

https://youtu.be/6gylzVfzqj4

 

Comments