[유니티]탑다운 슈팅 따라하기 #20 반동 및 재장전
- 게임 개발 - Unity3d
- 2020. 4. 14. 23:23
안녕하세요 유랑입니다.
실력향상을 위해서 오늘은 유튜브를 따라하면서 공부하겠습니다.
궁금하신점 있으시다면 댓글로 남겨주세요^^
1. 탑다운 슈팅 따라하기
이번 강의는 Sebastian Lague님께서 만든 예제이며,
유튜브를 보시면 자세한 내용을 배우실 수 있습니다.
유튜브 사이트 => 유튜브
2. 반동 및 재장전
이번 시간에는 반동 및 재장전을 만들어 보겠습니다.
애니메이션으로 만들어도 되지만, 코딩으로 구현해 보겠습니다.
2-1) 스크립트 작성 -㉠Gun
Gun 스크립트에 반동과 재장전에 대한 내용을 추가해 주겠습니다.
총알을 발사할 때 총에 움직임을 줘 반동효과를,
그리고 재장전이 가능하도록 메소드도 추가해 주세요.
그리고 총이 조준점을 바라보도록 코드도 수정해 주겠습니다.
using UnityEngine;
using System.Collections;
// 총에 해당
public class Gun : MonoBehaviour
{
// 발사 모드
public enum FireMode { Auto, Burst, Single };
public FireMode fireMode;
public Transform[] projectileSpawn; // 발사 위치
public Projectile projectile; // 총알
public float msBetweenShots = 100; // 연사 간격
public float muzzleVelocity = 35; // 총알 속도
public int burstCount; // 버스트 횟수
public int projectilesPerMag; // 총알 갯수
public float reloadTime = 0.3f;
// 반동
[Header("Recoil")]
public Vector2 kickMinMax = new Vector2(0.05f, 0.2f);
public Vector2 recoilAngleMinMax = new Vector2(3, 5);
public float recoilMoveSettleTime = 0.1f;
public float recoilRotationSettleTime = 0.1f;
// 효과
[Header("Effects")]
public Transform shell; // 탄피
public Transform shellEjection; // 탄피 생성위치
MuzzleFlash muzzleflash; // 머즐플래쉬효과
float nextShotTime;
bool triggerReleasedSinceLastShot; // 총알발사 가능여부
int shotsRemainingInBurst; // 남아있는 버스트 횟수
int projectilesRemainingInMag;
bool isReloading;
Vector3 recoilSmoothDampVelocity;
float recoilRotSmoothDampVelocity;
float recoilAngle; // 반동 각도
void Start()
{
muzzleflash = GetComponent<MuzzleFlash>();
shotsRemainingInBurst = burstCount;
projectilesRemainingInMag = projectilesPerMag;
}
void LateUpdate()
{
// 반동 효과(제자리로)
transform.localPosition = Vector3.SmoothDamp(transform.localPosition, Vector3.zero, ref recoilSmoothDampVelocity, recoilMoveSettleTime);
recoilAngle = Mathf.SmoothDamp(recoilAngle, 0, ref recoilRotSmoothDampVelocity, recoilRotationSettleTime);
transform.localEulerAngles = transform.localEulerAngles + Vector3.left * recoilAngle;
if (!isReloading && projectilesRemainingInMag == 0)
{
Reload();
}
}
void Shoot()
{
if (!isReloading && Time.time > nextShotTime && projectilesRemainingInMag > 0)
{
// 버스트 모드
if (fireMode == FireMode.Burst)
{
if (shotsRemainingInBurst == 0)
{
return;
}
shotsRemainingInBurst--;
}
// 싱글 모드
else if (fireMode == FireMode.Single)
{
if (!triggerReleasedSinceLastShot)
{
return;
}
}
// 총알 생성
for (int i = 0; i < projectileSpawn.Length; i++)
{
if (projectilesRemainingInMag == 0)
{
break;
}
projectilesRemainingInMag--;
nextShotTime = Time.time + msBetweenShots / 1000;
Projectile newProjectile = Instantiate(projectile, projectileSpawn[i].position, projectileSpawn[i].rotation) as Projectile;
newProjectile.SetSpeed(muzzleVelocity);
}
Instantiate(shell, shellEjection.position, shellEjection.rotation); // 탄피 생성
muzzleflash.Activate(); // 머즐플래쉬 효과
transform.localPosition -= Vector3.forward * Random.Range(kickMinMax.x, kickMinMax.y); // 반동 효과
recoilAngle += Random.Range(recoilAngleMinMax.x, recoilAngleMinMax.y);
recoilAngle = Mathf.Clamp(recoilAngle, 0, 30);
}
}
// 재장전
public void Reload()
{
if (!isReloading && projectilesRemainingInMag != projectilesPerMag)
{
StartCoroutine(AnimateReload());
}
}
IEnumerator AnimateReload()
{
isReloading = true;
yield return new WaitForSeconds(0.2f);
float reloadSpeed = 1f / reloadTime;
float percent = 0;
Vector3 initialRot = transform.localEulerAngles;
float maxReloadAngle = 30;
while (percent < 1)
{
percent += Time.deltaTime * reloadSpeed;
float interpolation = (-Mathf.Pow(percent, 2) + percent) * 4;
float reloadAngle = Mathf.Lerp(0, maxReloadAngle, interpolation);
transform.localEulerAngles = initialRot + Vector3.left * reloadAngle;
yield return null;
}
isReloading = false;
projectilesRemainingInMag = projectilesPerMag;
}
// 조준점 바라보기
public void Aim(Vector3 aimPoint)
{
if (!isReloading)
{
transform.LookAt(aimPoint);
}
}
// 마우스 버튼을 누르고 있을 때
public void OnTriggerHold()
{
Shoot();
triggerReleasedSinceLastShot = false;
}
// 마우스 버튼을 땠을 때
public void OnTriggerRelease()
{
triggerReleasedSinceLastShot = true;
shotsRemainingInBurst = burstCount;
}
}
2-2) 스크립트 작성 -㉡GunController
GunController 스크립트는 Gun의 조준점과 리로드 기능을 실행하도록
코도를 구현해 줄게요!!
2-3) 스크립트 작성 -㉢Player
최종적으로 Player 스크립트에서 일정 범위 밖이면 총이 조준점을 바라보도록,
그리고 "R"키를 누르면 재장전이 되도록 코드구현을 해줍니다.
총이 조준점을 따라가며,
플레이어 가까이 가져다 놓아도 별 문제가 없죠ㅎㅎ
2-4) 스크립트 적용
총알의 개수를 증가시켜주고,
테스트를 해보겠습니다.
반동과 함께 총알을 다쓰면 재장전이 되는걸 확인할 수 있습니다!!
3. 마무리
오늘 강의는 여기까지입니다.
탑다운 슈팅을 따라하면서 반동 및 재장전을 구현하였습니다.
감사합니다.
수업자료: 탑다운 슈팅 따라하기 #20 반동 및 재장전