본문 바로가기

Unity/로봇 체스 개발 일지

[Unity] 템플릿 메서드 패턴 : Action

개요

로봇 이동, 총알 이동은 단순히 이동으로 조준, 이동 방향 보기는 대상 보기 등 동일한 알고리즘을 Action 클래스에 담아 중복, 분산, 수정과 같은 일에 유연하게 대처할 수 있도록 하였다.


Action.cs

public class Action : MonoBehaviour
{
    public bool UpdateLookAtTarget(Vector3 target, Transform transObject, float accuracy, float rotationSpeed)
    {
        Quaternion targetRotation = Quaternion.Euler(new Vector3(0, 0, LeftAbj(transObject, TargetToAngle(transObject, target))));

        // 현재 회전 각도와 목표 각도 차이 계산
        float angleDifference = Quaternion.Angle(transObject.rotation, targetRotation);
        // 각도 차이가 임계값보다 클 경우에만 회전
        if (angleDifference > accuracy)
        {
            // 부드럽게 회전
            transObject.rotation = Quaternion.Slerp(transObject.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        }
        else
        {
            return false;
        }
        return true;
    }

유니티에는 transform. Look At()가 있지만 문제점은 부드럽게 돌아가지 않는다. 그래서 새로운 LookAt을 만들었다.

 

    public bool UpdateMove(Transform transObject, Vector3 targetPos, float accuracy, float speed)
    {
        float distance = Vector2.Distance(transObject.position, targetPos);
        // 최종적으로 움직이는 좌표의 거리, 좌표 오차는 여기서 수정
        transObject.position = Vector2.MoveTowards(transObject.position, targetPos, speed * Time.deltaTime);
        // 정확도 보다 거리가 크면 아직 도착하지 않은것으로 판단
        if (distance > accuracy)
        {
            return true;
        }
        return false;
    }

목표까지 단순히 천천히 움직이는 역할을 한다.

 

    // 좌측일경우 반대로 돌림
    public float LeftAbj(Transform transObject, float angle)
    {
        // 좌측일경우 물체를 반대로 돌림
        if (Mathf.Sign(transObject.root.localScale.x) < 0)
        {
            angle -= 180;
        }
        return angle;
    }

오브젝트를 반전시킬 시 생기는 문제를 해결하기 위한 코드이다.

 

    public bool TurnAngle(Vector3 position, Transform transObject, float rotationSpeed)
    {
        if (transObject.rotation != Quaternion.Euler(position))
        {
            transObject.rotation = Quaternion.Slerp(
            transObject.rotation,
            Quaternion.Euler(position),
            rotationSpeed * Time.deltaTime);
            return false;
        }
        return true;
    }

오브젝트를 회전시킬 때 사용한다.

 

    // 타겟에 각도 계산
    public float TargetToAngle(Transform transObject, Vector3 target)
    {
        float angle;
        Vector3 direction = target - transObject.position;
        direction.Normalize(); // 방향 벡터 정규화
        angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        return angle;
    }    
}

대상과 자신의 각도를 구하기 위해 사용한다.