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가 없는 경우의 예외처리도 해줬다.
자원 오브젝트는 특정 조건을 만족하면 채집할 수 있는 상태가 되고, 채집을 하게 되면 잔해로 돌아가야한다.
이를 관리하기 위한 Parent 객체를 하나 두고, 자식 객체로 채집 가능한 객체인 Gathering 객체와 잔해 객체인 Debris 객체를 넣어보기로 했다.
자식 객체인 Gathering과 Debris는 다음 상태의 ID를 가지고 있다.
각각의 조건에 따라 Parent 객체에게 상태 변화를 요청하고, Parent는 ID에 알맞는 오브젝트를 활성화한다.
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
객체와 연락을 위한 필드, 초기화 메서드 등 공통의 기능을 뽑아서 추상 클래스로 만들어봤다.
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
인터페이스를 구현해야한다.
채집 후 인벤토리에 추가될 루팅 아이템의 정보도 갖고 있다.
채집이 되면, 부모 객체에게 다음 상태로의 전환을 요청한다.
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;
}
}
잔해 상태에서는 시간이 지나면 다시 채집이 가능한 상태로 돌아가야한다.
농작물을 얻을 수 있는 밭 오브젝트 추가.
기능에 이것 저것 있지만 사실 위에서 다 구현해놨다.
현재 Gathering 컴포넌트를 가진 객체는 상호작용을 통해 다음 상태로 넘어갈 수 있다.
또, Debris 컴포넌트를 가진 객체는 시간이 지나면 다음 상태로 넘어가게 된다.
우선, 프리팹을 다음과 같이 만들어줬다.