개인개발기록/게임개발프로젝트

2025_04_24_플랫포머_게임개발_연습_프로젝트

pop2bubbledev 2025. 4. 24. 22:59

#오늘 한 작업

Unity3D

https://www.youtube.com/watch?v=07q9RUTRq4M

본 강의를 기반으로 실력향상을 위한 연습을 진행하였다

 

우선 총알을 만들어주는 작업을 진행하였다.

HandgunTrailRenderer

변경한 작업은 Width 값조정(권총 0.5 기관단총 0.2) 색 그리고 Materials(기본제공하는 Default-Line) 였다

그후 충돌판정을 위한 Rigidbody 와 Collider 추가후 발사 그리고 Reload 애니메이션을 추가했다

현재 Player의 Animator

public int damage;

private void OnCollisionEnter(Collision collision)
{
    if(collision.gameObject.tag == "Floor")
    {
        Destroy(gameObject, 3);
    }else if(collision.gameObject.tag == "Wall")
    {
        Destroy(gameObject);
    }
}

총알이 벽 또는 바닥에 충돌하면 사라지는 스크립트 이는 탄피또한 공유하는 스크립트기에 바닥충돌시 조건도 넣어주었다

 

이제 원거리 발사의 스크립트를 추가할 차례이다

public void Use()
{
    if (type == Type.Melee)
	{
    	StopCoroutine("Swing");
    	StartCoroutine("Swing");
	}
	else if (type == Type.Range && curAmmo > 0)
	{
    	curAmmo --;
    	StartCoroutine("Shot");
	}
    
}

이전코드에 else if 문으로 Type Range 의 조건을 추가해 Shot 코루틴함수를 추가해주었다

//총알 발사
GameObject 총알생성 = 생성한다(오브젝트(총알), 총알생성위치, 기준방향값);
Rigidbody bulletRigid = intantBullet.GetComponent<Rigidbody>();
bulletRigid.velocity = 총알의위치 (Z축 + 방향 :forward)

yield return null;	//1프레임 대기
//탄피 배출
GameObject 탄창 = 생성한다(오브젝트(탄창), 탄창생성위치, 기준방향값);
Rigidbody caseRigid = intantBullet.GetComponent<Rigidbody>();
Vector3 caseVec = 탄창생성위치 기준 앞 (Z축 + qkdgid : forward) * Random.Range(-4, -2) + Vector3.up(Y축으로 + 2~3) * Random.Range(2, 3); //케이스가 튈 방향 랜덤하게 정하기  
caseRigid.AddForce(케이스방향, ForceMode.Impulse);                                                                                 //케이스의 물리 방향에 힘을 더한다 즉시
caseRigid.AddTorque(회전축 * 10, ForceMode.Impulse);                                                                    //총알을 돌리기

1프레임간격으로 실행하며 탄알 생성 및 탄창 오브젝트를 생성한다

 

발사까지 완성되었으니 재장전 차례이다

 

재장전의경우 영상구현함수상 조건이 부족해보여 새로 만들었다

 if(equipWeapon == null) return;

 if(equipWeapon.type == Weapon.Type.Melee) return;

 if(ammo == 0) return;

우선 재장전하기 이전 3가지 항목을 검사한다

장착한 무기가있는가? 장착한무기가 원거리인가? 내가가진 총알이 있는가?

이 세가지 조건을 만족한다면 재장전 애니메이션을 재생하고 3초뒤 재장전 함수를 호출한다

 

영상에선 재장전함수를

int reAmmo = ammo < equipWeapon.maxAmmo ? ammo : equipWeapon.maxAmmo;
        equipWeapon.curAmmo += reAmmo;                                                                                       //ammo = 플레이어가 가진 탄약 reAmmo = 장전할 탄약 maxAmmo = 한탄창 최대량
        ammo -= reAmmo

이런식으로 구현하였는데 이 방식은

재장전할 총알 = 내가가진총알의 수가 내 무기의 탄창보다 적다면 가진총알만큼을 아니라면 최대탄창을 넣는 방식이다

그러면 문제가 생기는데 탄창을 전부 소모하지 않고 재장전을한다면 그만큼 추가 되어 최대탄창을 넘어서게된다

 

이 문제를 해결하기 위해 식을 약간 변경하였다

int reqAmmo = equipWeapon.maxAmmo - equipWeapon.curAmmo;
if (reqAmmo > ammo) 
{
    equipWeapon.curAmmo += ammo;
    ammo = 0;
}else if (reqAmmo <= ammo)
{
    equipWeapon.curAmmo += reqAmmo;
    ammo -= reqAmmo;
}

필요한 총알을 우선 구한다 (최대탄창 - 현재 탄창)

그 값이 내가가진 총알보다 많다면 내가가진 총알을 전부 장전한다

아니라면 부족한 총알만큼 장전한다

매커니즘 변경후 마지막 작업인 시선처리에 들어갔다 이전 함수로는 내가 바라보는 방향만을 공격할수있어

Trun 함수를 수정하였다

 

 //#2. 마우스에 의한 회전
 if (fDown && !isDodge)
 {
     Ray ray = followCamera.ScreenPointToRay(Input.mousePosition);              //스크린에서 () 안의 위치로 Ray를 쏜다 Ray = 레이져 가끔나오는 Raycast등의 레이저
     RaycastHit rayHit;
     if (Physics.Raycast(ray, out rayHit, 100))                                                       //ray가 어딘가에 닿으면 out <= 저장한다 rayHit 에 Return과 비슷한 역할
     {
         Vector3 nextVec = rayHit.point - transform.position;
         nextVec.y = 0;
         transform.LookAt(transform.position + nextVec);
     }
 }

여기선 Ray가 많이 등장하는데 간단하게 설명하면

내가 누른지점으로 레이저빔을 발사한다고 생각하면된다

위 함수는 내가 마우스를 누르면 그 방향으로 카메라를 돌리는 함수이다

계산은 이전 방향계산 공식과 동일하게

내가 찍은 지점의 방향에서 플레이어 포지션을 빼고 그 숫자만큼을 플레이어 포지션에 더하였다

 

 

 

#작업중 변경(수정) 사항

몇가지 제약조건이 부족한거같아 추가하였다

회피시 시점변환 / 점프중 공격 / 탄약 미소모장전시 탄약 추가적용 / 최대 탄창에서 장전

 

#예상시간/실제시간

1시간 / 1시간

#작업중 애로사항

몇가지 부족해보이는 제약조건이보여 몇몇 함수를 개선하였다

#예상되는 애로사항

플레이어 물리충돌 플레이어가 벽에 끼어있을때 계속해서 전진하면 맵 밖으로 탈출가능

해결방법 전부터 맵과의 지속적충돌이 많은 고민거리였으나

다음 강좌가 물리문제 고치기인만큼 영상에서 해결책을 찾아보려고한다

#지난주 애로사항

해당없음