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

Wooooo·2024년 1월 24일
0

내일배움캠프Unity

목록 보기
65/94

[오늘의 키워드]

  1. Resource Object Spawner
  2. Resource Object
  3. 신규 자원 오브젝트 - 밭

[Resource Object Spawner]

using UnityEngine;

// 2024-01-23 WJY
public class ResourceObjectSpawner
{
    [SerializeField] private ResourceObjectSpawnData _spawnData;

    private World _world;

    public void Initialize()
    {
        _spawnData = Managers.Resource.GetCache<ResourceObjectSpawnData>("ResourceObjectSpawnData.data");

        _world = Managers.Game.World;
        SpawnObject();
    }

    private void SpawnObject()
    {
        // TEST SCENE CODE
        if (_world == null)
        {
            foreach (var data in _spawnData.SpawnList)
                UnityEngine.Object.Instantiate(data.Prefab, data.spawnPosition, Quaternion.identity);
            return;
        }

        foreach (var data in _spawnData.SpawnList)
            _world.SpawnObjectInWorld(data.Prefab, data.spawnPosition);
    }
}

SpawnData 스크립터블 오브젝트를 이용해서 데이터의 SpawnList에 있는 오브젝트들을 생성하게 해줬다.

생성 시, World가 있는 MainScene에서는 각 위치에 맞는 청크의 자식으로 들어가도록 구현했다.

테스트 씬의 경우에는 World 초기화 과정이 오래걸려서 빼놓고 작업하시는 팀원분들이 있어서 World가 없는 경우의 예외처리도 해줬다.


[Resource Object]

자원 오브젝트 설계

자원 오브젝트는 특정 조건을 만족하면 채집할 수 있는 상태가 되고, 채집을 하게 되면 잔해로 돌아가야한다.

이를 관리하기 위한 Parent 객체를 하나 두고, 자식 객체로 채집 가능한 객체인 Gathering 객체와 잔해 객체인 Debris 객체를 넣어보기로 했다.

자식 객체인 Gathering과 Debris는 다음 상태의 ID를 가지고 있다.
각각의 조건에 따라 Parent 객체에게 상태 변화를 요청하고, Parent는 ID에 알맞는 오브젝트를 활성화한다.

하이어라키에서의 모습

클래스 설계

Base

using UnityEngine;

public abstract class ResourceObjectBase : MonoBehaviour
{
    protected ResourceObjectParent _parent;
    [SerializeField] protected int _toObjectID;

    public ResourceObjectParent Parent => GetParent();

    public ResourceObjectParent GetParent()
    {
        if (_parent == null)
            _parent = GetComponentInParent<ResourceObjectParent>();
        return _parent;
    }

    public virtual void Initialize()
    {
        GetParent();
    }
}

다음 상태 오브젝트의 ID, ResourceObjectParent 객체와 연락을 위한 필드, 초기화 메서드 등 공통의 기능을 뽑아서 추상 클래스로 만들어봤다.

Gathering

using UnityEngine;

public class ResourceObjectGathering : ResourceObjectBase, IInteractable
{
    [SerializeField] private ItemData _lootingItem;

    public void Interact(Player player)
    {
        if (!gameObject.activeSelf)
            return;

        if (_lootingItem != null)
            player.Inventory.AddItem(_lootingItem, 1);
        _parent.SwitchObject(_toObjectID);
    }
}

채집 가능한 상태에서는 플레이어의 상호작용을 위해 IInteractable 인터페이스를 구현해야한다.
채집 후 인벤토리에 추가될 루팅 아이템의 정보도 갖고 있다.
채집이 되면, 부모 객체에게 다음 상태로의 전환을 요청한다.

Debris

using UnityEngine;

public class ResourceObjectDebris : ResourceObjectBase
{
    private float _remainingTime;
    [SerializeField] private float _respawnTime;

    private void Update()
    {
        TimeLapse();
    }

    public void Respawn()
    {
        _remainingTime = _respawnTime;
        _parent.SwitchObject(_toObjectID);
    }

    private void TimeLapse()
    {
        _remainingTime -= Time.deltaTime;
        if (_remainingTime < 0f)
            Respawn();
    }

    public override void Initialize()
    {
        base.Initialize();
        _remainingTime = _respawnTime;
    }
}

잔해 상태에서는 시간이 지나면 다시 채집이 가능한 상태로 돌아가야한다.


[신규 자원 오브젝트 - 밭]

농작물을 얻을 수 있는 밭 오브젝트 추가.

밭 오브젝트 라이프 사이클

핵심 기능

  1. 상태가 3개
  2. 모든 상태에 상호작용이 가능

상태 별 기능

  1. 빈 밭
    1. 상호작용 조건 : 씨앗/감자 등 심을 수 있는 아이템
    2. 상호작용 이벤트 : 팝업이 열리고 심을 아이템 선택???
  2. 무언가 심어진 밭
    1. 상호작용 조건 : 맨손, 물뿌리개??
    2. 상호작용 이벤트 : 심은 아이템 수거하기, 성장까지 남은 시간 추가감소
  3. 다 자란 밭
    1. 상호작용 조건 : 맨손? 삽, 낫, 괭이?????? 아직 못정함
    2. 상호작용 이벤트 : 작물 수확 (아이템 루팅)

구현

기능에 이것 저것 있지만 사실 위에서 다 구현해놨다.

현재 Gathering 컴포넌트를 가진 객체는 상호작용을 통해 다음 상태로 넘어갈 수 있다.
또, Debris 컴포넌트를 가진 객체는 시간이 지나면 다음 상태로 넘어가게 된다.

우선, 프리팹을 다음과 같이 만들어줬다.

  1. 부모인 Farm에게는 Parent 컴포넌트를 추가한다.
  2. empty farm에게는 gathering 컴포넌트를 넣고 toObject를 1번(seed farm)으로 설정한다.
  3. seed farm에게는 gathering 컴포넌트를 넣고 toObject를 0번(empty farm)으로 설정한 다음, debris 컴포넌트도 추가한 다음 toObject를 2번(ripe farm)으로 추가한다.
    이렇게 하면, 덜 자란 밭의 경우엔 상호작용으로 씨앗의 회수를, 시간이 지나면 다 자란 밭으로 변하는 객체가 된다.
  4. ripe farm에게는 gathering 컴포넌트를 넣고 toObject를 0번(empty farm)으로 설정한 다음, 원하는 아이템을 lootingItem에 넣어준다.
profile
game developer

0개의 댓글