본문 바로가기

유니티/확장 프로젝트[3D]

3D 미니 프로젝트 2 - 12 ] 정보 저장 버그 수정

지난 포스팅에서는 점프 맵의 점수와, 캐릭터 정보를 파일로 저장하였다.

 

3D 미니 프로젝트 2 - 11 ] 스코어 파일 저장 및 점프 맵 랭킹

지난 포스팅에서는 상점과 스탯 강화 등에 대해 구현하였다. 3D 미니 프로젝트 2 - 10 ] 상점, 스탯 강화 지난 포스팅에서는 던전 스테이지를 만들어 보았다. 3D 미니 프로젝트 2 - 9 ] 스테이지 설정

mini-noriter.tistory.com

 

이번에는 파일로 저장했던 것들이 정보를 로드하면서 무기를 습득하게 되면 일부가 초기화가 되는 버그가 생기게 되어 그것을 정리하고자 한다.


로드 후 새로운 무기 습득 시 특정 무기가 미습득이 되는 현상

제목 그대로 데이터 로드 후에 새로운 무기 습득 시에 특정 무기가 미습득이 되어 버린다.

 

따라서 디버깅을 해 보게 되었다.

 

0번 슬롯

앞서 무기를 WeaponItemInfo 클래스의 배열에 저장 했었다. (이곳에 나와 있다.)

 

3D 미니 프로젝트 2 - 4 ] 강화 시스템

지난 포스팅에서는 골드메탈님의 강의 중 공격에 대해 정리 해 보았다. 3D 미니 프로젝트 2 - 3 ] 공격 지난 포스팅에서는 아이템 수집 및 장착을 구현하였다. 3D 미니 프로젝트 2 - 2 ] 아이템 수집

mini-noriter.tistory.com

 

위 사진은 해당 배열의 0번 슬롯에 저장되어 있는 무기이다.

 

저장할 때, 9강까지 강화를 하고 정보가 로드 된 모습이다.

 

이제, 새롭게 머신건을 습득 하게 되면

 

0번 슬롯

0번 슬롯에 머신건의 데이터가 덮어 씌워지게 된다.

 

현상을 정리했으니, 코드의 어느 부분에 문제가 생겼는지 알아내기 위해 아이템 습득 부분 코드를 살펴 보았다.

 

PlayerCode.cs 의 InterAction 함수 일부

void InterAction()
    {
        if(iDown && nearObject != null && !isJump && !isSwap)
        {
            // 무기에 닿고 있고(근처 오브젝트가 null이 아님), 점프 상태가 아닐 때, 상호작용 버튼을 누르게 되면 아이템을 습득하게 된다.
            // 이것을 응용하여 NPC와도 대화를 하게끔?

            if(nearObject.layer == 14)
            {
                Item nearObjItem = nearObject.GetComponent();
                switch (nearObjItem.type)
                {
                    case Item.Type.Weapon:
                        int weaponIndex = nearObjItem.value; // value를 index로 설정 할 것!

                        ui.PopUI.SetActive(false);
                        ui.isNoticeOn = false; // 무기를 먹었을 때 비활성화!
                        hasWeapons[weaponIndex] = true;

                        playerItem.GetInfo(nearObject);

                        saveinfo.SaveItemInfo(playerItem.weapons[playerItem.returnIndex(weaponIndex)]);
                        // 아이템 정보 세이브, 이 자체가 포인터에 의한 참조?가 되어서 강화를 할 때, 강화 창에서만 갱신을 해도 세이브 자료에서도 반영이 되게 된다. 

                        Destroy(nearObject);
                        break;

 당장 여기서는 WeaponItemInfo 배열의 인덱스를 수정하지 않음을 볼 수 있기에, 무기를 습득하여 정보를 저장하는 playerItem.GetInfo() 함수로 넘어가서 살펴 보도록 하자.

 

PlayerItem.cs

public void GetInfo(GameObject obj)
{
    Item item = obj.GetComponent();

    switch (item.type)
    {
        case (Item.Type.Weapon):

            PlayerCode playerCode = GetComponent();
            Weapon weapon = playerCode.WeaponList[item.value].GetComponent();

            WeaponItemInfo weaponinfo = new WeaponItemInfo(item.value, 0 ,weapon.maxEnchant, weapon.Damage, weapon.AtkDelay, weapon.type,weapon.criticalPercent);
            if (weapon.bullet) // 만약 원거리라면 무기 자체에 세팅한 총알 데미지를 갱신 해 준다.
            {
                Bullet bullet = weapon.bullet.GetComponent();
                bullet.SetDamage(weapon.Damage);
            }
            weapons[weaponIndex] = weaponinfo;
            weaponIndex++;
            break;
    }

}

여기서 주목할 부분은 아래 두줄이다.

 

weapons[weaponIndex] = weaponinfo;
weaponIndex++;

이 곳을 보게 되면 weaponIndex가 정보 저장, 로드 유무에 상관없이 0부터 시작하게 됨을 볼 수 있다.

그래서 아까 0번 인덱스에 겹쳐서 저장 된 것이다.

 

방법은 두 가지이다.

  1. Index 정보도 같이 저장한다
  2. 매번 빈 Index를 찾게 만들어 준다.

그 중에서 2번을 사용 해 주도록 하겠다.

 

PlayerItem.cs에 새로운 함수를 만들어 준다.

public int checkIndex(WeaponItemInfo[] input)
{
    for(int i = 0; i < input.Length; i++)
    {
        if(input[i].baseAtk == 0)
        {
            return i;
        }
    }

    return -1;
}

baseAtk가 0이면 아무것도 없는 것이기에 그것을 가지고 새롭게 무기를 얻었을 때, 들어 갈 인덱스를 크기에 맞춰 설정 해 주게 된다.

 

물론 위 방법(2번)이 1번 방법보다 간단하게 추가할 수 있다는 장점이 있지만.. 부위가 많아지게 되면 함수를 더 만들어 주어야 한다는 단점도 있다.

(볼륨이 커지면 index를 저장하는 방식(1번)이 더 나을수도 있겠다는 생각이 든다.)

 

아무튼, 이 함수를 이용해서 위 두 줄을 아래와 같이 바꾸어 준다.

weapons[checkIndex(weapons)] = weaponinfo;

이렇게 해 주면

무기가 배열 뒤에 추가 된 모습

위 사진과 같이 머신건에 대한 정보가 뒤에 잘 들어가게 됨을 볼 수 있다.