Ammo & Reload
Ammo System
GunController 안에 AmmoSystem Class 를 따로 구현했다.
canReload 는 남은 탄약이 있고, 현재 장전된 탄약이 탄창 용량보다 작으면 true
public class AmmoSystem
{
public int magAmmo;
public int magCapacity;
public int remainAmmo;
public bool canReload { get => this.remainAmmo > 0 && this.magAmmo < this.magCapacity; }
public AmmoSystem(int magCapacity, int totalAmmo)
{
this.magAmmo = magCapacity;
this.magCapacity = magCapacity;
this.remainAmmo = totalAmmo - magAmmo;
}
public void Reload()
{
int addAmmo = this.magCapacity - this.magAmmo;
if (this.remainAmmo < addAmmo)
{
addAmmo = this.remainAmmo;
this.remainAmmo = 0;
}
else
{
this.remainAmmo -= addAmmo;
}
this.magAmmo += addAmmo;
}
}
public class GunController : MonoBehaviour
{
...
public int magCapacity = 30;
public int totalAmmo = 60;
public AmmoSystem ammoSystem;
private void Start()
{
...
ammoSystem = new AmmoSystem(magCapacity, totalAmmo);
}
private void FireWeapon()
{
if (ammoSystem.magAmmo <= 0) return;
ammoSystem.magAmmo--;
...
}
public void OnReload()
{
ammoSystem.Reload();
}
}
Reload
Input 처리
public class RobotInputHandler : MonoBehaviour
{
...
public InputAction reloadAction;
private void Start()
{
...
reloadAction.Enable();
...
reloadAction.performed += context =>
{
if (!gunController.ammoSystem.canReload) return;
reloadEvent.Invoke();
}
}
}
public class RobotAnimationController : MonoBehaviour
{
public void OnReload()
{
animator.SetBool("isReload", true);
}
}
Input 처리 코드를 작성해 주었다.
Animation Out
Reload 애니메이션을 제어하기 위해 animator 에 ReloadController 를 부착했다.
- Reload 애니메이션이 끝나면 자동으로 isReload 값을 false 로 설정한다.
- 원래 조준하고 있었으면 조준한 상태로 장전한다. (aimReload 변수)
- 장전 도중 조준하면 장전이 중단 (Interrupted) 된다.
- 장전 애니메이션이 성공적으로 완료되면 GunController 클래스의 OnReload 함수를 실행시킨다.
public class ReloadController : StateMachineBehaviour
{
private bool aimReload = false;
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
aimReload = animator.GetBool("isAim");
}
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (!aimReload && animator.GetBool("isAim"))
{
animator.SetBool("isReload", false);
}
if (stateInfo.normalizedTime > 1)
{
animator.transform.GetComponentInChildren<GunController>().OnReload();
animator.SetBool("isReload", false);
}
}
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
animator.SetBool("isReload", false);
}
}
Animation Mask 설정
걸으면서, 앉아서, 서서, 뛰면서 Reload 애니메이션이 재생되도록 하기 위해서
Animation Mask 설정을 해 주었다.
본 상단만 애니메이션을 적용시키기 위해 위와 같이 설정했다.