[TIL] Unity - 오브젝트 이동 (2)

MINO·2024년 6월 4일
post-thumbnail

2024-06-04


마인드맵

  1. 자동차가 오브젝트 풀을 통해 생성된다.
  2. 주변에서 플레이어를 감지하면, Random 상태나 Chase 상태로 변한다.
  3. 충돌이 감지되면, 폭발 모션이 발생하고 잠시 후, 소멸된다.
  4. 만약, 일정 시간동안 충돌이 감지되지 않으면 오브젝트가 소멸된다.

Update()

LifeTime 을 관리하고, 상태에 따라 함수를 호출한다.

private void Update()
{
    if (lifeTime > 0)
        lifeTime -= Time.deltaTime;
    else
        curState = State.Crashing;

    switch (curState)
    {
        case State.Idle:
            GoStraight(); break;
        case State.Random:
            HandleTurn(); break;
        case State.Chasing:
            GoToPlayer(); break;
        case State.Crashing:
            BeforeCrashing(); break;
    }
}

GoStraight()

자동차 오브젝트가 생성되고, 직진 방향으로 달린다.

 private void GoStraight() // 그냥 직진 방향으로 달려
 {
     // 오브젝트의 진행 방향으로 힘 더해주기
     rb.AddForce(transform.forward * IdleSpeed, ForceMode.Acceleration);
 }

OnTriggerEnter()

플레이어를 감지하여, 확률에 따라 Random 이나 Chasing 상태로 변환

private void OnTriggerEnter(Collider other) 
{
    if (curState != State.Idle)
    	return;
        
	if (other.gameObject.layer == LayerMask.NameToLayer("Player"))
    {
		if (Random.Range(0f, 1f) < percent)
		{
			// y축 기준, -fov' ~ fov' 회전
			float randomAngle = Random.Range(-fov, fov);
			
            // 쿼터니언으로 변환 후, 목표 진행 방향을 계산
			targetV = Quaternion.Euler(0f, randomAngle, 0f) * transform.forward;
			targetV = targetV.normalized;

			// 목표 회전 방향을  계산
			targetRot = Quaternion.LookRotation(targetV, transform.up);

			curState = State.Random;
		}

		else
			curState = State.Chasing;
    }
}

TurnHandle()

OnTriggerEnter 에서 설정한 랜덤 방향을 향해 달린다.

private void HandleTurn() // 캐릭터를 찾으면, 핸들 꺾어서 달려~
{
    if (curState != State.Random)
        return;

    curV = transform.forward;
    curRot = transform.rotation;

    if (curV != targetV)
        curV = Vector3.Lerp(curV, targetV, acc1 * Time.deltaTime);

    if (curRot != targetRot)
        curRot = Quaternion.Lerp(curRot, targetRot, acc1 * Time.deltaTime);

    curV.y = 0.0f;
    transform.rotation = curRot;

    rb.AddForce(curV * walkSpeed, ForceMode.Acceleration);
}

GoToPlayer()

플레이어 방향을 계속 추적하여, 해당 방향으로 자동차가 움직인다.

private void GoToPlayer() // 플레이어 방향으로 달려
{
    if (curState != State.Chasing)
        return;

    Vector3 playerPos = Player.transform.position;
    Vector3 carPos = transform.position;

    // 자동차 -> 플레이어 방향 벡터 계산
    targetV = (playerPos - carPos).normalized;
    dirV = targetV - curV;
    
    // 목표 회전 방향 계산
    targetRot = Quaternion.LookRotation(targetV, transform.up);
    
    // 현재 자동차의 방향과 회전
    curV = transform.forward;
    curRot = transform.rotation;

    if (curV != targetV)
        curV = Vector3.Lerp(curV, dirV, acc2 * Time.deltaTime);

    if (curRot != targetRot)
        curRot = Quaternion.Lerp(curRot, targetRot, acc2 * Time.deltaTime);

    curV.y = 0.0f;
    transform.rotation = curRot;
    rb.AddForce(curV * runSpeed, ForceMode.Acceleration);
}

결과

Random 상태 - 차량이 무작위 방향으로 돌진


Chasing 상태 - 플레이어를 따라가는 상태


TIL 마무리

플레이어가 차량과 충돌했을 때, 플레이어가 날아가는 충돌 작용이 일어나지 않는다.

해당 부분을 수정하고, 새로 알게된 레그돌 이라는 시스템을 도입하면
플레이어가 충돌했을 때 더 자연스러운 연출이 될 것 같다.

profile
안녕하세요 게임 개발하는 MINO 입니다.

0개의 댓글