[Practice] 간단한 콤보 어택 만들기에 카메라 흔들기 추가
in Unity
간단한 콤보 어택 만들기에 카메라 흔들기 추가해보자.
(1) 간단한 콤보 어택 만들기 프로젝트를 열어서 ShakeCamera스크립트를 추가한다.
(2) CameraController 스크립트를 수정한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float minDistance=3;
[SerializeField] private float maxDistance = 30;
[SerializeField] private float wheelSpeed = 500;
[SerializeField] private float xMoveSpeed = 500;
[SerializeField] private float yMoveSpeed = 250;
private float yMinLimit = 5;
private float yMaxLimit = 80;
private float x, y;
private float distance;
// 카메라 흔들림 효과를 재생 중인지 체크 (흔들림 효과 재생 중일 땐 이동/회전 중지)
public bool IsOnShake { set; get; }
private void Awake()
{
distance=Vector3.Distance(transform.position, target.position);
Vector3 angles = transform.eulerAngles;
x= angles.y;
y= angles.x;
}
private void Update()
{
if(target == null) return;
// 카메라 흔들림 효과를 재생 중일 때는 이동/회전 값을 제어하지 않는다.
if (IsOnShake == true) return;
x+=Input.GetAxis("Mouse X")*xMoveSpeed*Time.deltaTime;
y-= Input.GetAxis("Mouse Y") * yMoveSpeed * Time.deltaTime;
y = ClampAngle(y, yMinLimit, yMaxLimit);
transform.rotation=Quaternion.Euler(y , x,0);
distance-=Input.GetAxis("Mouse ScrollWheel")*wheelSpeed*Time.deltaTime;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
}
private void LateUpdate()
{
if (target == null) return;
// 카메라 흔들림 효과를 재생 중일 때는 이동/회전 값을 제어하지 않는다.
if (IsOnShake == true) return;
transform.position=transform.rotation*new Vector3(0,0,-distance) + target.position;
}
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
(3) 이에 맞게 ShakeCamera스크립트도 수정한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShakeCamera : MonoBehaviour
{
private static ShakeCamera instance;
public static ShakeCamera Instance => instance;
private float shakeTime;
private float shakeIntensity;
private CameraController cameraController;
private void Awake()
{
cameraController = GetComponent<CameraController>();
}
public ShakeCamera()
{
instance = this;
}
// 외부에서 카메라 흔들림을 조작할 때 호출하는 메소드
// ex) OnShakeCamera(1); => 1초간 0.1의 세기로 흔들림
// ex) OnShakeCamera(0.5f,1); => 0.5초간 1의 세기로 흔들림
/// <param name="shakeTime">카메라 흔들림 지속 시간 (설정하지 않으면 디폴트 1)
/// <param name=shakeIntensity">카메라 흔들림 세기 (값이 클수록 세게 흔들린다)(설정하지 않으면 디폴트 0.1)
public void OnShakeCamera(float shakeTime=1.0f,float shakeIntensity = 0.1f)
{
this.shakeTime = shakeTime;
this.shakeIntensity = shakeIntensity;
//현재 코루틴이 실행중일 수도 있기 때문에 중복 실행하지 않기 위해 멈춘 후 실행한다.
StopCoroutine("ShakeByRotation");
StartCoroutine("ShakeByRotation");
}
// 카메라를 shakeTime동안 shakeIntensity의 세기로 흔드는 코루틴 함수
private IEnumerator ShakeByPosition()
{
// 흔들리기 직전의 시작 위치 (흔들림 종료 후 돌아올 위치)
Vector3 startPosition=transform.position;
while (shakeTime>0.0f)
{
// 특정 축만 변경하길 원하면 아래 코드 이용 (이동하지 않을 축은 0 값 사용)
// float x = Random.Range(-1f, 1f);
// float y = Random.Range(-1f, 1f);
// float z = Random.Range(-1f, 1f);
// transform.position = startPosition + new Vector3(x, y, z) * shakeIntensity;
// 초기 위치로부터 구 범위(Size 1) * shakeIntensity의 범위에서 카메라 위치 변동
transform.position=startPosition+Random.insideUnitSphere*shakeIntensity;
// 시간 감소
shakeTime-=Time.deltaTime;
yield return null;
}
transform.position=startPosition;
}
private IEnumerator ShakeByRotation()
{
// 카메라 흔들림 효과 재생 시작
cameraController.IsOnShake = true;
// 흔들리기 직전의 회전 값
Vector3 startRotation = transform.eulerAngles;
// 회전의 경우 shakeIntensity에 더 큰 값이 필요하기 때문에 변수로 만들었음
// (클래스 멤버변수로 선언해 외부에서 조작가능)
float power = 10f;
while (shakeTime > 0.0f)
{
// 회전하길 원하는 축만 지정해서 사용 (회전하지 않을 축은 0으로 설정
// (클래스 멤버변수로 선언해 외부에서 조작하면 더 좋다)
float x = 0;//Random.Range(-1f,1f)
float y = 0;//Random.Range(-1f,1f)
float z = Random.Range(-1f, 1f);
transform.rotation = Quaternion.Euler(startRotation + new Vector3(x, y, z) * shakeIntensity * power);
// 시간 감소
shakeTime-=Time.deltaTime;
yield return null;
}
// 흔들리기 직전의 회전 값으로 설정
transform.rotation=Quaternion.Euler(startRotation);
// 카메라 흔들림 효과 재생 종료
cameraController.IsOnShake = false;
}
}
(4) 플레이어의 공격이 적에게 적중 했을 때 화면을 흔들기 위해 PlayerAttackCollision스크립트를 수정한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttackCollision : MonoBehaviour
{
private void OnEnable()
{
StartCoroutine("AutoDisable");
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag=="Enemy")
{
// 플레이어의 공격이 적에게 적중했을 때 카메라 흔들기
ShakeCamera.Instance.OnShakeCamera(0.1f, 0.5f);
other.GetComponent<EnemyAnimator>().TakeDamage(10);
}
}
private IEnumerator AutoDisable()
{
yield return new WaitForSeconds(0.1f);
gameObject.SetActive(false);
}
}
(5) MainCamera 오브젝트에 ShakeCamera스크립트를 추가해준다.
그리고 게임을 실행해보면 플레이어의 공격이 적에게 닿았을때는 카메라가 흔들리지만 적에게 닿지 않으면 흔들리지 않는 모습을 볼 수 있다.