
오늘 학습 키워드
유니티 심화
오늘 학습 한 내용을 나만의 언어로 정리하기
유니티 심화 (3D)
시네머신
-
유니티에서 제공하는 고급 카메라 시스템
-
1개의 브레인 카메라와 여러 개의 가상 카메라로 이루어짐
-
시네머신 시스템 내에 있는 다양한 기능들
- 블렌드 카메라 리스트 : 여러 개의 가상 카메라가 있을 때 그 카메라들 간의 전환을 도와줌
- 스테이트 드라이브 카메라 : 애니메이션 상태에 따라 카메라 전환을 도와줌
- 클리어 샷 카메라 : 오브젝트 때문에 카메라가 가릴 때 알아서 전환해줌
- 돌리 카메라 : 가상의 돌리 레일을 깔아두면 그 경로대로 카메라가 이동함
-
시네머신 자체의 주요 기능
- 가상 카메라
- 카메라 블렌딩
- 트랙킹과 추적
- 애니메이션 연동
- 렌즈 세트

- Follow : 따라갈 트랜스폼
- Look At : 보는 방향 트랜스폼
- Body : 카메라의 트랜스폼을 여기서 설정
- Transposer : 기본
- Framing Transposer : 탑다운 방식으로 할 때 유용
- Aim : 카메라 회전 관련으로 여기서 설정 (Input으로 바로 받아오게도 할 수 있음)
- Add Extension : 여기서 추가 기능 설정 가능
- Cinemachine Collider : 카메라가 Follow 말고 다른 물체를 가리키게 될 때 자동으로 Follow 다시 비출 수 있도록 이동 (ex. 벽 안에 들어갔을 때)
플레이어 점프 구현
// ForceReceiver.cs
void Update()
{
if (controller.isGrounded)
{
verticalVelocity = Physics.gravity.y * Time.deltaTime;
}
else
{
// 땅 위에 있으면 가속도를 계속 더해서 받게
verticalVelocity += Physics.gravity.y * Time.deltaTime;
}
}
public void Jump(float jumpForce)
{
verticalVelocity += jumpForce;
}// PlayerBaseState.cs
private void Move(Vector3 direction)
{
float movementSpeed = GetMovementSpeed();
stateMachine.Player.Controller.Move(((direction * movementSpeed) + stateMachine.Player.ForceReceiver.Movement) * Time.deltaTime);
}// PlayerJumpState.cs
public override void Update()
{
base.Update();
// 점프 상태인데 속도가 음수다 > 떨어지는 중이다 > Idle 로 변경
if (stateMachine.Player.Controller.velocity.y <= 0)
{
stateMachine.ChangeState(stateMachine.IdleState);
return;
}
}플레이어 추락 구현
- 점프하지 않았는데도 떨어질 때
// PlayerGroundState.cs
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
// isGrounded 가 아니고,
// 플레이어의 수직 이동속도가 중력 가속도 * fixedDeltaTime보다 작을 때 => 떨어지는 중이라고 판정
if (!stateMachine.Player.Controller.isGrounded
&& stateMachine.Player.Controller.velocity.y < Physics.gravity.y * Time.fixedDeltaTime)
{
stateMachine.ChangeState(stateMachine.FallState);
}
}- 점프하고 떨어질 때
// PlayerJumpState.cs
public override void Update()
{
base.Update();
if (stateMachine.Player.Controller.velocity.y <= 0)
{
stateMachine.ChangeState(stateMachine.FallState);
return;
}
}플레이어 공격 구현
- 현재 애니메이션에 대해서 정보를 가져오는 방법 = AnimatorStateInfo
// PlayerBaseState.cs
protected float GetNormalizedTime(Animator animator, string tag)
{
AnimatorStateInfo currentInfo = animator.GetCurrentAnimatorStateInfo(0);
AnimatorStateInfo nextInfo = animator.GetNextAnimatorStateInfo(0);
// 애니메이션이 전환되고 있을 때 && 다음 애니메이션이 tagif (animator.IsInTransition(0) && nextInfo.IsTag(tag))
{
return nextInfo.normalizedTime;
}
// 전환되고 있지 않을 때 && 현재 애니메이션이 tag else if (!animator.IsInTransition(0) && currentInfo.IsTag(tag))
{
return currentInfo.normalizedTime;
}
else
{
return 0;
}
}- 이걸로 콤보어택 구현
// PlayerComboAttackState.cs
public override void Update()
{
base.Update();
ForceMove();
float normalizedTime = GetNormalizedTime(stateMachine.Player.Animator, "Attack");
if (normalizedTime < 1f) // 공격 모션이 끝나지 않았을 때
{
if (normalizedTime >= attackInfoData.ComboTransitionTime)
{
// 콤보 시도
TryComboAttack();
}
if (normalizedTime >= attackInfoData.ForceTransitionTime)
{
// 댐핑 시도
TryApplyForce();
}
}
else // 공격 모션이 끝났을 때
{
if (alreadyAppliedCombo) // 콤보를 적용했을 때
{
// 콤보 인덱스에 다음 콤보 넣어주고 상태 다시 실행 => 다음 콤보 진행
stateMachine.ComboIndex = attackInfoData.ComboStateIndex;
stateMachine.ChangeState(stateMachine.ComboAttackState);
}
else // 콤보를 적용하지 않았을 때
{
stateMachine.ChangeState(stateMachine.IdleState);
}
}
}
void TryComboAttack()
{
if (alreadyAppliedCombo) return; // 이미 다음 콤보 적용 했을 때
if (attackInfoData.ComboStateIndex == -1) return; // 마지막 콤보일 때
if (!stateMachine.IsAttacking) return;
alreadyAppliedCombo = true;
}
void TryApplyForce()
{
if (alreadyAppliedForce) return; // 이미 힘을 적용했을 때
alreadyAppliedForce = true;
stateMachine.Player.ForceReceiver.Reset(); // 힘 초기화
stateMachine.Player.ForceReceiver.AddForce(Vector3.forward * attackInfoData.Force); // 앞쪽으로 나아가도록 설정
}적 만들기
- 플레이어랑 똑같이 진행하지만 상태를 세 개만 설정 (Idle, Chasing, Attack)
플레이어 피격 설정

- 오른쪽 팔 조인트 부분에 빈 오브젝트 만들어서 콜라이더랑 리지드 바디 설정