BallShooter
클래스는 MonoBehaviour를 상속받아 Unity 게임 오브젝트에 붙일 수 있는 스크립트이다. 이 클래스에서 사용되는 변수들은 다음과 같다.
public Rigidbody ball; // 볼의 물리적 특성을 조절할 Rigidbody
public Transform firePos; // 볼을 발사할 위치
public Slider powerSlider; // 파워를 표시할 UI 슬라이더
public AudioSource shootingAudio; // 발사 소리를 재생할 오디오 소스
public AudioClip fireClip; // 발사 소리
public AudioClip chargingClip; // 충전 소리
Rigidbody ball
: 이는 발사될 볼의 Rigidbody 컴포넌트를 저장한다. Rigidbody는 물리 엔진에서 물체의 운동 상태를 계산하기 위해 사용된다.Transform firePos
: 볼이 발사될 시작점의 위치와 방향을 나타낸다.Slider powerSlider
: 발사 힘의 크기를 시각적으로 표현하기 위한 UI 슬라이더 컴포넌트이다.AudioSource shootingAudio
, AudioClip fireClip
, AudioClip chargingClip
: 이 변수들은 발사와 충전 소리를 처리한다.OnEnable()
과 Start()
함수는 게임 오브젝트나 스크립트가 활성화될 때 호출된다.
OnEnable(): 이 함수에서는 발사 힘(currentForce
)과 파워 슬라이더의 값(powerSlider.value
)을 초기 상태(minForce)로 설정한다. 이는 스크립트가 활성화되거나 재활성화될 때마다 호출되므로, 각 발사 이벤트 후에도 이 값들이 초기화된다.
private void OnEnable()
{
currentForce = minForce;
powerSlider.value = minForce;
}
Start(): Start()
함수에서는 chargeSpeed
를 초기화한다. 이 값은 maxForce
와 minForce
를 chargingTime
으로 나눠 계산한다. 이렇게 계산하면, 충전 버튼을 누르고 있을 때 currentForce
가 얼마나 빠르게 증가해야 하는지 알 수 있다.
private void Start()
{
chargeSpeed = (maxForce - minForce) / chargingTime;
}
Update()
함수는 매 프레임마다 호출되며, 여기에서 발사 로직과 파워 슬라이더의 업데이트가 이루어진다.
발사 힘의 최대치 확인: currentForce
가 maxForce
를 초과하거나 동일할 경우, 볼을 발사한다.
Fire1 버튼 입력 처리: Fire1 버튼(기본적으로 마우스 왼쪽 버튼)이 처음 눌렸을 때, currentForce
를 minForce
로 재설정하고 충전 소리를 재생한다.
Fire1 버튼을 계속 누르고 있는 경우: Fire1 버튼을 누르고 있으면 currentForce
가 시간에 따라 증가하며, 이에 따라 powerSlider.value
역시 업데이트된다.
Fire1 버튼을 뗐을 때: 볼을 발사한다.
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
currentForce = minForce;
shootingAudio.clip = chargingClip;
shootingAudio.Play();
}
else if (Input.GetButton("Fire1"))
{
currentForce += chargeSpeed * Time.deltaTime;
powerSlider.value = currentForce;
}
else if (Input.GetButtonUp("Fire1") && !fired)
{
Fire();
}
}
Input.GetButtonDown("Fire1")
메서드로 확인하고, currentForce
를 minForce
로 재설정하며, 충전 소리를 재생합니다.Input.GetButton("Fire1")
메서드로 확인하고, currentForce
를 증가시킵니다. 이 값을 powerSlider.value
로 설정하여 UI 슬라이더를 업데이트합니다.Input.GetButtonUp("Fire1")
메서드로 확인하고, Fire()
함수를 호출하여 볼을 발사합니다.Fire()
함수는 실제로 볼을 발사하는 코드를 담고 있다. 여기에서는 Instantiate
함수를 사용하여 ball
프리팹을 firePos
위치에 생성한다. 그리고 Rigidbody의 velocity
속성을 사용하여 발사 힘을 적용한다.
private void Fire()
{
fired = true;
Rigidbody ballInstance = Instantiate(ball, firePos.position, firePos.rotation) as Rigidbody;
ballInstance.velocity = currentForce * firePos.forward;
shootingAudio.clip = fireClip;
shootingAudio.Play();
currentForce = minForce;
powerSlider.value = minForce;
}
볼 인스턴스 생성: Instantiate
함수를 사용하여 볼의 Rigidbody 인스턴스를 생성합니다. 생성된 인스턴스의 위치(position
)와 회전(rotation
)은 firePos
로 설정됩니다.
볼에 힘 적용: 생성된 볼의 Rigidbody에 발사 힘을 적용합니다. 이 힘은 currentForce
와 firePos.forward
의 곱으로 계산됩니다.
발사 소리 재생: 발사 소리 클립을 설정하고 재생합니다.
볼 발사 후 초기화: 발사한 후 currentForce
와 powerSlider.value
를 minForce
로 리셋합니다.
볼을 발사하는 로직은 주로 Update()
함수와 Fire()
함수에서 처리된다. 이들 함수는 다음과 같은 단계로 이루어져 있다.
사용자 입력 감지: Update()
함수에서는 Input.GetButtonDown("Fire1")
, Input.GetButton("Fire1")
, Input.GetButtonUp("Fire1")
메서드를 사용하여 사용자의 입력을 감지한다.
파워 충전: Input.GetButton("Fire1")
이 true일 경우, currentForce
변수를 chargeSpeed * Time.deltaTime
만큼 증가시킨다.
파워 슬라이더 업데이트: currentForce
값이 변경될 때마다 powerSlider.value
를 이 값으로 업데이트한다.
볼 발사: Input.GetButtonUp("Fire1")
이 true일 경우 또는 currentForce
가 maxForce
에 도달하면 Fire()
함수를 호출하여 볼을 발사한다.
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
currentForce = minForce;
}
else if (Input.GetButton("Fire1"))
{
currentForce += chargeSpeed * Time.deltaTime;
}
else if (Input.GetButtonUp("Fire1"))
{
Fire();
}
powerSlider.value = currentForce;
}
초기화: OnEnable()
함수에서 powerSlider.value
를 minForce
로 초기화한다. 이렇게 함으로써, 새로운 볼을 발사할 준비가 완료된다.
실시간 업데이트: Update()
함수에서 powerSlider.value
를 currentForce
로 업데이트한다. 이렇게 하면, 파워 슬라이더가 현재 충전된 파워를 정확하게 반영한다.
볼 발사 시 리셋: 볼을 발사한 후에는 currentForce
와 powerSlider.value
를 minForce
로 리셋한다. 이는 Fire()
함수에서 처리된다.
private void Fire()
{
Rigidbody ballInstance = Instantiate(ball, firePos.position, firePos.rotation);
ballInstance.velocity = firePos.forward * currentForce;
currentForce = minForce;
powerSlider.value = minForce;
}
볼이 발사될 때와 파워가 충전될 때 사운드 효과를 재생한다. 이는 AudioSource
와 AudioClip
을 사용하여 구현되며, shootingAudio.clip
을 fireClip
또는 chargingClip
으로 설정하고 shootingAudio.Play()
를 호출하여 처리한다.
shootingAudio.clip = fireClip;
shootingAudio.Play();
기존의 ShooterRotator 스크립트는 단순히 발사대의 회전만을 담당했다. 새롭게 추가된 부분은 다음과 같다.
이전 버전에서는 ShooterRotator 스크립트 내에서 BallShooter 스크립트를 참조하지 않았다. 새로운 버전에서는 BallShooter 스크립트를 활성화 및 비활성화하기 위해 참조한다.
public BallShooter ballShooter; // 추가
OnEnable() 함수가 추가되어 스크립트가 활성화될 때 발사대의 회전을 초기화하고, BallShooter 스크립트를 비활성화한다.
private void OnEnable() // 추가
{
transform.rotation = Quaternion.identity;
state = RotateState.Idle;
ballShooter.enabled = false;
}
RotateState.Ready
상태일 때, BallShooter 스크립트가 활성화된다. 이 부분은 기존 스크립트에 없던 새로운 로직이다.
case RotateState.Ready:
ballShooter.enabled = true; // 추가
break;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShooterRotator : MonoBehaviour
{
private enum RotateState
{
Idle, Vertical, Horizontal, Ready
}
private RotateState state = RotateState.Idle;
public float verticalRotateSpeed = 360f;
public float horizontalRotateSpeed = 360f;
public BallShooter ballShooter; // 추가
void Update()
{
switch (state)
{
case RotateState.Idle:
if (Input.GetButtonDown("Fire1"))
{
state = RotateState.Horizontal;
}
break;
case RotateState.Horizontal:
if (Input.GetButton("Fire1"))
{
transform.Rotate(new Vector3(0, horizontalRotateSpeed * Time.deltaTime, 0));
}
else if (Input.GetButtonUp("Fire1"))
{
state = RotateState.Vertical;
}
break;
case RotateState.Vertical:
if (Input.GetButton("Fire1"))
{
transform.Rotate(new Vector3(-verticalRotateSpeed * Time.deltaTime, 0, 0));/
}
else if (Input.GetButtonUp("Fire1"))
{
state = RotateState.Ready;
ballShooter.enabled = true; // 추가
}
break;
case RotateState.Ready:
break;
}
}
private void OnEnable() // 추가
{
transform.rotation = Quaternion.identity;
state = RotateState.Idle;
ballShooter.enabled = false;
}
}