활과 화살의 게임 오브젝트 만들기

활과 화살의 이미지 에셋을 씬뷰에 끌어놔 게임오브젝트를 만들고 Sprite Renderer의 Order in Layer값을 3으로 설정합니다.

활 : 이름을 Bow로 변경하고 위치는 0으로 합니다.

화살 : 이름을 Arrow라는 태그와 레이어를 만들어 설정합니다. 접촉판정에 사용됩니다.

활과 화살을 Player폴더로 끌어서 프리팹으로 만들고 씬뷰의 활과 화살은 제거합니다.

 

화살을 발사하는 스크립트

ArrowShoot이라는 스크립트를 Player폴더에 만들고 Player에 어태치합니다.

ArrowShoot.cs
0.00MB

변수

public float shootSpeed = 12.0f;    //화살 속도
public float shootDelay = 0.25f;    //발사 간격
public GameObject bowPrefab;        //활의 프리펩
public GameObject arrowPrefab;      //호살의 프리펩

bool inAttack = false;               //공격 중 여부
GameObject bowObj;                   //활의 게임 오브젝트

Start()

bow프리팹을 이용해 오브젝트를 만들고 플레이어의 자식으로 만듭니다.

void Start(){
    //활을 플레이어 캐릭터에 배치
    Vector3 pos = transform.position;
    bowObj = Instantiate(bowPrefab, pos, Quaternion.identity);
    bowObj.transform.SetParent(transform);//활의 부모로 플레이어 캐릭터를 설정
}

Update()

활을 캐릭터에 맞게 회전시키고 위치시킵니다.

z값을 조정해 캐릭터보다 앞으로 놓습니다. 

공격키가 눌리면 Attack()를 실행합니다.

void Update() {
    if ((Input.GetButtonDown("Fire3"))) {
        //공격 키가 눌림
        Attack();
    }
    //활의 회전과 우선순위
    float bowZ = -1;    //활의 Z값(캐릭터보다 앞으로 설정)
    PlayerController plmv = GetComponent<PlayerController>();
    if (plmv.angleZ > 30 && plmv.angleZ < 150)  {
        //위 방향
        bowZ = 1;       //활의 Z값(캐릭터 보다 뒤로 설정)
    }
    //활의 회전
    bowObj.transform.rotation = Quaternion.Euler(0, 0, plmv.angleZ);
    //활의 우선순위
    bowObj.transform.position = new Vector3(transform.position.x,
                                transform.position.y, bowZ);
}

Attack()

화살을 쏘는 처리를 합니다 . ItemKeepr.hasArrows를 하나 줄입니다. static이므로 참조없이 바로 접근이 가능합니다.

public void Attack()
{
    //화살을 가지고 있음 & 공격중이 아님
    if (ItemKeeper.hasArrows > 0 && inAttack == false)
    {
        ItemKeeper.hasArrows -= 1;	//화살을 소모
        inAttack = true;		//공격 중으로 설정
        //화살 발사
        PlayerController playerCnt = GetComponent<PlayerController>();
        float angleZ = playerCnt.angleZ; //회전 각도
        //화살의 게임 오브젝트 만들기(진행 방향으로 회전)
        Quaternion r = Quaternion.Euler(0, 0, angleZ);
        GameObject arrowObj = Instantiate(arrowPrefab, transform.position, r);
        //화살을 발사할 벡터 생성
        float x = Mathf.Cos(angleZ * Mathf.Deg2Rad);
        float y = Mathf.Sin(angleZ * Mathf.Deg2Rad);
        Vector3 v = new Vector3(x, y) * shootSpeed;
        //화살에 힘들 가하기
        Rigidbody2D body = arrowObj.GetComponent<Rigidbody2D>();
        body.AddForce(v, ForceMode2D.Impulse);
        //공격 중이 아님으로 설정
        Invoke("StopAttack", shootDelay);
    }
}

화살을 제어하는 스크립트 만들기

발사된 화살을 제어하는 스크립트를 만들어봅니다. ArrowController라는 스크립트를 Player폴더에 만들고 Player에 어태치 합니다.(이미 어태치되어있으면 두번할 필요는 없습니다.)  발사된 화살은 접촉된 물체의 자식이 되어 붙어 있다가 deleteTime후 제거됩니다.

ArrowController.cs
0.00MB

변수

public float deleteTime = 2;  //제거 시간

Start()

void Start()  {
    Destroy(gameObject, deleteTime); //이정 시간후 제거하기
}

OnCollisionEnter2D()

private void OnCollisionEnter2D(Collision2D collision)
{
    //접촉한 게임 오브젝트의 자식으로하기
    transform.SetParent(collision.transform);
    //충돌 판정을 비활성
    GetComponent<CircleCollider2D>().enabled = false;
    //물리 시뮬레이션을 비활성
    GetComponent<Rigidbody2D>().simulated = false;
}

레이어의 접촉 설정 편집하기

화살은 발사되면서 Player와 접촉하기 때문에 나가지도 못하고 멈춥니다. 이걸 막기위해

Edit>Project Setting에서 Layer Collision Matrix를 열어 Player와 Arrow가 교차하는 점을 꺼줍니다.

게임 실행하기

활의 발사를 확인해 봅니다. 테스트를 위해 임시로 ItemKeeper의 hasArrow를 0 이상의 숫자로 해줍니다. 

PlayerController.cs 의 Start()에  ItemKeeper.hasArrows = 10; 적어도 된다.

[Shift]키를 누르면 이동 방향으로 화살이 발사됩니다. 벽에 닿으면 화살은 그자리에 멈추고 잠시뒤 사라집니다.

 

+ Recent posts