Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티/디자인패턴

[Unity] 유니티 C#) Strategy 패턴

새벽_글쓴이 2024. 12. 9. 10:28
반응형

전략 패턴

알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있게 해주는 패턴

 

기본구현 방법

1. 전략 인터페이스 정의

public interface IMovementStrategy
{
    void Move(Transform transform);
}

 

2. 구체적인 전략 클래스들

public class WalkStrategy : IMovementStrategy
{
    private float speed = 5f;
    
    public void Move(Transform transform)
    {
        float horizontalInput = Input.GetAxis("Horizontal");
        float verticalInput = Input.GetAxis("Vertical");
        Vector3 movement = new Vector3(horizontalInput, 0f, verticalInput) * speed * Time.deltaTime;
        transform.Translate(movement);
    }
}

public class FlyStrategy : IMovementStrategy
{
    private float speed = 10f;
    private float heightOffset = 5f;
    
    public void Move(Transform transform)
    {
        float horizontalInput = Input.GetAxis("Horizontal");
        float verticalInput = Input.GetAxis("Vertical");
        Vector3 movement = new Vector3(horizontalInput, 0f, verticalInput) * speed * Time.deltaTime;
        
        // 높이 유지
        Vector3 newPosition = transform.position + movement;
        newPosition.y = heightOffset;
        transform.position = newPosition;
    }
}

public class TeleportStrategy : IMovementStrategy
{
    private float teleportDistance = 5f;
    private float cooldown = 2f;
    private float lastTeleportTime = 0f;
    
    public void Move(Transform transform)
    {
        if (Input.GetKeyDown(KeyCode.Space) && Time.time - lastTeleportTime >= cooldown)
        {
            Vector3 teleportDirection = transform.forward * teleportDistance;
            transform.position += teleportDirection;
            lastTeleportTime = Time.time;
        }
    }
}

 

3. 컨텍스트 클래스 ( 전략을 사용하는 클래스 )

public class Character : MonoBehaviour
{
    private IMovementStrategy movementStrategy;

    public void SetMovementStrategy(IMovementStrategy strategy)
    {
        movementStrategy = strategy;
    }

    void Update()
    {
        if (movementStrategy != null)
        {
            movementStrategy.Move(transform);
        }
    }

    // 전략 변경 메서드들
    public void SwitchToWalking()
    {
        SetMovementStrategy(new WalkStrategy());
    }

    public void SwitchToFlying()
    {
        SetMovementStrategy(new FlyStrategy());
    }

    public void SwitchToTeleporting()
    {
        SetMovementStrategy(new TeleportStrategy());
    }
}

 

4. 사용방법

// Character 컴포넌트에서 전략 변경하기
Character character = GetComponent<Character>();

// 걷기 모드로 변경
character.SwitchToWalking();

// 나중에 날기 모드로 변경
character.SwitchToFlying();

 

핵심개념

  • Strategy 패턴은 알고리즘을 정의하고 각각을 캡슐화하여 상호 교환 가능하게 만드는 디자인 패턴이다
  • 런타임에 알고리즘을 유연하게 변경할 수 있게 해준다
  • "행위(behavior)를 클래스로 캡슐화하여 동적으로 행위를 자유롭게 바꿀 수 있게 해주는 패턴"이라고도 한다

 

사용목적

1. 알고리즘의 교체 가능성

  • 런타임에 알고리즘을 동적으로 교체할 수 있어야 할 때
  • 예: 게임 중 캐릭터의 공격 방식이 무기에 따라 바뀌어야 하는 경우

 

2. 조건문 제거

  • 복잡한 if-else 구문을 제거하고 코드를 깔끔하게 유지
// Bad: 조건문 사용
if (weaponType == "sword") {
    // 칼로 공격
} else if (weaponType == "bow") {
    // 활로 공격
}

// Good: Strategy 패턴 사용
attackStrategy.Attack(); // 현재 설정된 전략으로 자동 공격

 

3. 코드 재사용성 향상

  • 동일한 알고리즘을 여러 클래스에서 공유하고 재사용 가능
  • 예: 동일한 이동 전략을 플레이어와 NPC가 공유

 

4. 확장성 확보

  • 기존 코드 수정 없이 새로운 알고리즘 추가 가능
  • OCP(Open-Closed Principle) 원칙 준수

 

5. 관심사의 분리

  • 알고리즘의 구현과 사용을 분리
  • 각 전략을 독립적으로 테스트하고 관리 가능

 

사용사례 및 간단한 예시 코드

게임 캐릭터의 공격패턴

// 플레이어 무기 변경 시스템
Player player = GetComponent<Player>();
player.SetAttackStrategy(new MeleeAttackStrategy()); // 근접 무기로 교체
player.SetAttackStrategy(new RangedAttackStrategy()); // 원거리 무기로 교체

 

AI행동 패턴

public interface IAIBehaviorStrategy 
{
    void ExecuteBehavior();
}

public class AggressiveBehavior : IAIBehaviorStrategy 
{
    public void ExecuteBehavior() 
    {
        // 적극적으로 플레이어를 추적하고 공격
    }
}

public class DefensiveBehavior : IAIBehaviorStrategy 
{
    public void ExecuteBehavior() 
    {
        // 방어적으로 행동하며 거리 유지
    }
}

 

아이템 효과 시스템

public interface IItemEffectStrategy 
{
    void ApplyEffect(GameObject target);
}

public class HealingEffect : IItemEffectStrategy 
{
    public void ApplyEffect(GameObject target) 
    {
        // 체력 회복 효과 적용
    }
}

public class BuffEffect : IItemEffectStrategy 
{
    public void ApplyEffect(GameObject target) 
    {
        // 버프 효과 적용
    }
}

 

결론

Strategy 패턴의 장점

알고리즘 변경이 쉽고 유연함
코드 재사용성이 높아짐
새로운 전략 추가가 용이함
조건문 사용을 줄여 코드 가독성 향상

 

주의점

전략이 많아지면 클래스 수가 증가할 수 있음
간단한 알고리즘의 경우 오버엔지니어링이 될 수 있음

 

Strategy 패턴은 캐릭터 행동, AI, 아이템 시스템 등
다양한 동작을 유연하게 교체해야 하는 상황에서 매우 유용하게 사용된다
반응형