본문 바로가기
스파르타 내배캠

스파르타 내배캠 Unity 3기 - 49

by LemongO 2024. 3. 21.


PartsSO UI 연동

 

각 파츠에는 SO 가 달려있고 실제 적용될 수치들이 들어있다.

public class BasePartsSO : ScriptableObject
{
    [Header("# Info")]
    public int dev_ID;
    public string dev_Name;

    public string display_Name;
    [TextArea]
    public string display_Description;

    [Header("# Common Stats")]
    public float armor;
    public float weight;
}

(이 외에도 Lower, Upper SO가 있다.)

 

그리고 실제 파츠가 변경될 때 모듈만 변경되는 것을 보는게 아니라 각 수치들의 변화도 시각적으로 보여야 한다.

그럼 UI를 연동을 해야하는데 수치가 변화될 부분은

상체, 하체 어느 파츠를 변경할시 선택하는 SelectorMenu

상체 변경 패널 UpperSelector

하체 변경 패널 LowerSelector

세 곳에서 확인할 수 있어야 하는 것으로 정했다.

 

그 중 전체 파츠에 대한 수치가 보이는 SelectorMenu만 대표적으로 보자면

// ### UI_SelectorMenu.cs

[SerializeField] TextMeshProUGUI[] _specTexts;

enum SpecType
{
    AP,
    Weight,
    AttackMain,
    AttackSub,
    ReloadSub,
    MoveSpeed,
    RotateSpeed,
    JumpPower,
    BoostPower,
}

private float lowerAP;
private float upperAP;
private float lowerWeight;
private float upperWeight;

protected override void Init()
{
    base.Init();

    Managers.Module.OnLowerChange += ApplyLowerModuleSpec;
    Managers.Module.OnUpperChange += ApplyUpperModuleSpec;        
    InitSpecTexts();
}

private void InitSpecTexts()
{
    lowerAP = Managers.Module.CurrentLowerPart.lowerSO.armor;
    lowerWeight = Managers.Module.CurrentLowerPart.lowerSO.weight;        

    upperAP = Managers.Module.CurrentUpperPart.upperSO.armor;
    upperWeight = Managers.Module.CurrentUpperPart.upperSO.weight;

    float attakMain = Managers.Module.CurrentUpperPart.Primary.WeaponSO.atk;
    float attakSub = Managers.Module.CurrentUpperPart.Secondary.WeaponSO.atk;
    float reloadSub = Managers.Module.CurrentUpperPart.Secondary.WeaponSO.coolDownTime;
    float rotSpeed = Managers.Module.CurrentUpperPart.upperSO.smoothRotation;

    float moveSpeed = Managers.Module.CurrentLowerPart.lowerSO.speed;        
    float jumpPower = Managers.Module.CurrentLowerPart.lowerSO.jumpPower;
    float boostPower = Managers.Module.CurrentLowerPart.lowerSO.boosterPower;        

    _specTexts[(int)SpecType.AP].text = $"{lowerAP + upperAP}";
    _specTexts[(int)SpecType.Weight].text = $"{lowerWeight + upperWeight}";
    _specTexts[(int)SpecType.AttackMain].text = $"{attakMain}";
    _specTexts[(int)SpecType.AttackSub].text = $"{attakSub}";
    _specTexts[(int)SpecType.ReloadSub].text = $"{reloadSub}";

    _specTexts[(int)SpecType.MoveSpeed].text = $"{moveSpeed}";
    _specTexts[(int)SpecType.RotateSpeed].text = $"{rotSpeed}";
    _specTexts[(int)SpecType.JumpPower].text = $"{jumpPower}";
    _specTexts[(int)SpecType.BoostPower].text = $"{boostPower}";
}

private void ApplyLowerModuleSpec(LowerPart lower)
{
    lowerAP = lower.lowerSO.armor;
    lowerWeight = lower.lowerSO.weight;

    _specTexts[(int)SpecType.AP].text = $"{upperAP + lower.lowerSO.armor}";
    _specTexts[(int)SpecType.Weight].text = $"{upperWeight + lower.lowerSO.weight}";

    _specTexts[(int)SpecType.MoveSpeed].text = $"{lower.lowerSO.speed}";        
    _specTexts[(int)SpecType.JumpPower].text = $"{lower.lowerSO.jumpPower}";
    _specTexts[(int)SpecType.BoostPower].text = $"{lower.lowerSO.boosterPower}";
}

private void ApplyUpperModuleSpec(UpperPart upper)
{
    upperAP = upper.upperSO.armor;
    upperWeight = upper.upperSO.weight;

    _specTexts[(int)SpecType.AP].text = $"{lowerAP + upper.upperSO.armor}";
    _specTexts[(int)SpecType.Weight].text = $"{lowerWeight + upper.upperSO.weight}";

    _specTexts[(int)SpecType.AttackMain].text = $"{upper.Primary.WeaponSO.atk}";
    _specTexts[(int)SpecType.AttackSub].text = $"{upper.Secondary.WeaponSO.atk}";
    _specTexts[(int)SpecType.ReloadSub].text = $"{upper.Secondary.WeaponSO.coolDownTime}";
    _specTexts[(int)SpecType.RotateSpeed].text = $"{upper.upperSO.smoothRotation}";
}

 

위와 같이 처음에 보여질 현재파츠의 SO를 받아와 각 수치를 Text에 적용시키고

 

각 파츠 Selector 패널에서 파츠를 변경했을 때도 역시 Text가 변경되어야 한다.

 

InitSpecTexts는 패널이 처음 보일 때만 보여지면 되기 때문에 곧바로 ModuleManager에서 해당 SO를 불러오면 된다.

하지만 파츠가 교체될 땐 변경된 파츠의 SO를 가져와야하기 때문에 ModuleManager의 파츠 변경할 때 호출되는
Action에 구독하여 해당 Part를 가져와 SO에 접근하여 Text를 변경시켜준다.

 

// ### ModuleManager.cs

public event Action<UpperPart> OnUpperChange;
public event Action<LowerPart> OnLowerChange;

public void ChangeUpperPart(int index)
{
    if (CurrentUpperPart.upperSO.dev_ID == index) // 같은 파츠면 바꿀 필요X
        return;

    UnityEngine.Object.DestroyImmediate(CurrentUpperPart.gameObject); // 즉시 파괴로 Transform 참조를 이전 Upper가 아니게 방지.

    CurrentUpperPart = CreatePart<UpperPart>(CurrentModule.UpperPivot, index);
    CurrentUpperPart.Setup(CurrentModule);
    CurrentModule.SetPivot(FindPivot(CurrentUpperPart.transform));

    OnUpperChange?.Invoke(CurrentUpperPart);
}