내일배움캠프 Unity 87일차 TIL - 팀 9와 4분의 3 - 개발일지

Wooooo·2024년 2월 29일
0

내일배움캠프Unity

목록 보기
89/94

[오늘의 키워드]

InteractSystem 클래스 구조 변경


[InteractSystem 클래스 구조 변경]

InteractSystem의 추가로 캐릭터가 상호작용 시 주변 오브젝트들 중 우선순위에 따라 상호작용이 진행되는 기능이 생겼다.

유저가 현 시점에서 상호작용 할 오브젝트가 뭔지 알 수 있도록 상호작용할 오브젝트에 아웃라인으로 하이라이트 효과를 주기로 했다.

하이라이트 효과를 적용하기 위해선 현재 InteractSystem의 구조를 살짝 바꿀 필요성이 있다.

기존 구조

InteractSystem.cs

    public void TryInteractSequence()
    {
        SearchAllObject(_transform.position);

        var tool = GetCurrentTool();
        var isWeapon = tool is WeaponItemData;

        // # 1. 타게팅 공격
        if (isWeapon)
        {
            if (TryWeaponInteract(tool))
                return;
        }

        // # 2. 도구 상호작용
        if (tool != _emptyHand)
        {
            // # 2-1. 파괴
            if (TryToolDestruct(tool))
                return;

            // # 2-2. 벌목, 채광
            if (TryToolInteract(tool))
                return;
        }

        // # 3. 구조물 상호작용
        if (TryArchitectureInteract(_emptyHand))
            return;

        // # 4. 채집 상호작용
        if (TryToolInteract(_emptyHand))
            return;

        // # 5. 허공에 공격
        if (isWeapon)
        {
            if (TryWeaponInteract(tool, true))
                return;
        }
    }
PlayerBaseState.cs

    protected virtual void OnInteractStarted(InputAction.CallbackContext context)
    {
        if (_stateMachine.IsFalling) return;
        _stateMachine.InteractSystem.TryInteractSequence();
    }

기존의 구조는 PlayerBaseState에서 상호작용 입력을 받으면, InteractSystem에게 우선순위에 따라 상호작용을 진행할 것을 요청한다.

InteractSystem은 요청을 받았을 때 주변 오브젝트를 탐색하여 순차적으로 상호작용을 시도한 다음, event를 날리는 구조이다.

하지만, 지금 상호작용을 눌렀을 때 어떤 오브젝트에게 상호작용될지 보여주는 하이라이트 효과를 적용하기 위해서는, InteractSystem은 항상 어떤 오브젝트에게 상호작용 될지 알고 있어야한다.

변경 구조

InteractSystem.cs

    private Action _onInteract;
    
    public void TryInteract()
    {
        _onInteract?.Invoke();
    }

    public void SearchInteractableObjectsSequence()
    {
        var tool = GetCurrentTool();
        var isWeapon = tool is WeaponItemData;

        SearchAllObject(_transform.position);

        // # 1. 타게팅 공격
        if (isWeapon)
        {
            if (SearchWeaponInteract(tool))
                return;
        }

        // # 2. 도구 상호작용
        if (tool != _emptyHand)
        {
            // # 2-1. 파괴
            if (SearchToolDestruct(tool))
                return;

            // # 2-2. 벌목, 채광
            if (SearchToolInteract(tool))
                return;
        }

        // # 3. 구조물 상호작용
        if (SearchArchitectureInteract(_emptyHand))
            return;

        // # 4. 채집 상호작용
        if (SearchToolInteract(_emptyHand))
            return;

        // # 5. 허공에 공격
        if (isWeapon)
        {
            if (SearchWeaponInteract(tool, true))
                return;
        }
    }
    
    private bool SearchToolInteract(ToolItemData tool)
    {
        foreach (var target in _targets)
        {
            if (!target.CompareTag(tool.targetTagName) || (1 << target.gameObject.layer & tool.targetLayers) == 0)
                continue;

            if (target.distance > tool.range * tool.range)
                break;

            if (target.TryGetComponent<IInteractable>(out var interactable))
            {
                _onInteract = () => OnToolInteract?.Invoke(interactable, target.tag, target.transform.position);
                HighlightTarget(target);
                //OnToolInteract?.Invoke(interactable, target.tag, target.transform.position);
                return true;
            }
        }
        return false;
    }

우선 InteractSystem에서는 이벤트 호출 구조와 메서드의 이름을 살짝 바꿨다.
이제 요청을 받으면 바로 상호작용 이벤트를 호출하는게 아니라, 오브젝트 탐색과 이벤트 호출부를 나눴다.

검색을 진행하면 _onInteract Action에 플레이어가 상호작용 버튼을 눌렀을 때 호출될 이벤트를 담아둔다.

TryInteract() 메서드가 호출되면, 담고 있던 이벤트를 호출한다 !

이에 맞춰 PlayerBaseState의 구조도 바꿨다.

PlayerBaseState.cs

    public virtual void Update()
    {
        Move();
        _stateMachine.InteractSystem.SearchInteractableObjectsSequence();
    }
    
    protected virtual void OnInteractStarted(InputAction.CallbackContext context)
    {
        if (_stateMachine.IsFalling) return;
        _stateMachine.InteractSystem.TryInteract();
    }

기존엔 OnInteractStarted()에서 검색과 이벤트호출을 모두 담당하는 TryInteractSequence()를 호출했지만, InteractSystem이 담아두고 있던 이벤트를 호출하는 TryInteract()를 호출하도록 했고, 오브젝트의 탐색은 매 프레임 호출되는 Update()에서 SearchInteractableObjectsSequence()를 호출하도록 했다.


[TODO]

테스트용으로 아웃라인 하이라이트를 적용해봤는데, 나무 오브젝트의 경우 버텍스 수가 6천개쯤 돼서 다가가면 0.5초 ~ 1초 정도 게임이 멈춘다.

우선은 잡 시스템으로 스무스노말을 계산하는 로직을 적용해보고,

상호작용할 수 있는 오브젝트, 즉 하이라이트가 적용될 수 있는 오브젝트들을 선별해서 해당 오브젝트들이 스무스 노말이 적용된 메시를 미리 알고 있게 해주는게 좋을 것 같다.

profile
game developer

0개의 댓글