일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- KRAFTON JUNGLE
- 4기
- Unity
- 유니티
- 다익스트라
- project3
- 이벤트 함수 실행 순서
- 크래프톤정글4기
- 전쟁-전투
- 알고리즘
- 알고리즘수업-너비우선탐색2
- 오블완
- 크래프톤 정글 4기
- BFS
- c#
- 파이썬
- 연결리스트
- User Stack
- TiL
- 백준
- pintos
- anonymous page
- 추상클래스와인터페이스
- C
- 네트워크
- kraftonjungle
- 티스토리챌린지
- 핀토스
- 크래프톤정글
- 크래프톤 정글
Archives
- Today
- Total
말감로그
[Unity] Valley - 식물 성장 코드 분리 및 확장성 개선 본문
728x90
ItemData ScriptableObject를 만들어서 아이템을 확장한 것과 같이 PlantData ScriptableObject를 만들어 식물 또한 데이터 관리와 확정성을 개선해주었다.
마찬가지로 Inventory 클래스와 Item.cs에 PlantData를 추가해주고 초기화한다.
public class Inventory
{
[System.Serializable]
public class Slot
{
public string itemName;
public Sprite icon;
public int count;
public int maxAllowed;
public PlantData plantData;
public Slot()
{
itemName = "";
count = 0;
maxAllowed = 99;
plantData = null;
}
:
[RequireComponent(typeof(Rigidbody2D))]
public class Item : MonoBehaviour
{
public ItemData itemData;
public PlantData plantData;
public bool canInteract;
[HideInInspector] public Rigidbody2D rigid;
void Awake()
{
rigid = GetComponent<Rigidbody2D>();
canInteract = true;
}
}
그리고 기존엔 Player.cs와 TileManager.cs 에서 식물 성장 코드를 작성하였는데 의존성을 위해 PlantGrowthManager.cs 를 만들어 코드를 분리해주었다.
그리고 해당 PlantData를 가져와 그 식물에 맞는 Prefab, Growth Stages Tiles, Growth Times를 설정하도록 각 타일의 좌표와 그 위치에 심어진 PlantData를 담는 딕셔너리를 생성였다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class PlantGrowthManager : MonoBehaviour
{
private Dictionary<Vector3Int, PlantData> plantDataDict = new Dictionary<Vector3Int, PlantData>(); //PlantData 딕셔너리
private Dictionary<Vector3Int, int> plantGrowthDays = new Dictionary<Vector3Int, int>(); // 씨앗 심은 날 저장
private Dictionary<Vector3Int, int> currentGrowthStages = new Dictionary<Vector3Int, int>(); // 현재 성장 단계 저장
private TileManager tileManager;
private TimeManager timeManager;
private void Start()
{
tileManager = GameManager.instance.tileManager;
timeManager = GameManager.instance.timeManager;
if (timeManager != null)
{
timeManager.OnDayEnd += OnDayEnd;
}
}
void OnDestroy()
{
if (timeManager != null)
{
timeManager.OnDayEnd -= OnDayEnd;
}
}
public void PlantSeed(Vector3Int position, PlantData plantData)
{
if (tileManager.DoesTileExist(position) && tileManager.GetTileName(position) == "Plowed")
{
tileManager.SetTileState(position,"Seeded");
tileManager.seedMap.SetTile(position, tileManager.plantedTile);
plantDataDict[position] = plantData;
plantGrowthDays[position] = 0;
currentGrowthStages[position] = 0;
}
}
IEnumerator GrowPlant(Vector3Int position)
{
if (!tileManager.DoesTileExist(position) || tileManager.GetTileState(position) == "Grown")
{
yield break;
}
PlantData plantData = plantDataDict[position];
int currentStage = currentGrowthStages[position];
int daysSincePlanted = plantGrowthDays[position];
// 각 성장 단계별로 경과된 시간이 맞는지 확인
if (currentStage < plantData.growthStagesTiles.Length && daysSincePlanted >= plantData.growthTimes[currentStage])
{
tileManager.seedMap.SetTile(position, plantData.growthStagesTiles[currentStage]);
plantData.growthStagesTiles[currentStage].colliderType = Tile.ColliderType.Sprite;
currentGrowthStages[position] = currentStage + 1; // 성장 단계 1 증가
// 모든 성장 단계를 완료했으면 "Grown" 상태로 변경
if (currentGrowthStages[position] >= plantData.growthStagesTiles.Length)
{
tileManager.SetTileState(position,"Grown");
}
else
{
tileManager.SetTileState(position,"Growing");
}
}
yield return null;
}
public void HarvestPlant(Vector3Int position)
{
PlantData plantData = GetPlantData(position);
if(plantData != null)
{
Vector3 spawnPosition = tileManager.interactableMap.GetCellCenterWorld(position);
GameObject plant = Instantiate(plantData.plantPrefab, spawnPosition, Quaternion.identity);
Debug.Log("Spawning plant prefab: " + plantData.plantName + " at " + spawnPosition);
Rigidbody2D rb = plant.GetComponent<Rigidbody2D>();
if (rb != null)
{
StartCoroutine(FloatAndLand(plant));
}
}
RemovePlantData(position);
}
private IEnumerator FloatAndLand(GameObject plant)
{
float floatDuration = 0.5f;
float landDuration = 0.5f;
float smoothTime = 0.2f; // 부드럽게 이동할 시간
Vector2 velocity = Vector2.zero; // 속도를 관리하기 위한 변수
Vector2 initialPosition = plant.transform.position;
Vector2 floatTargetPosition = initialPosition + new Vector2(0, 0.5f); // 살짝 위로 떠오를 목표 지점
float elapsedTime = 0;
Item interactable = plant.GetComponent<Item>();
if (interactable != null)
interactable.canInteract = false;
// 위로 부드럽게 떠오르는 애니메이션
while (elapsedTime < floatDuration)
{
plant.transform.position = Vector2.SmoothDamp(plant.transform.position, floatTargetPosition, ref velocity, smoothTime);
elapsedTime += Time.deltaTime;
yield return null; // 다음 프레임을 기다림
}
// 정확한 위치로 설정
plant.transform.position = floatTargetPosition;
// 약간 대기
yield return new WaitForSeconds(0.1f);
// 착지할 때 다시 속도 초기화
velocity = Vector2.zero;
elapsedTime = 0;
// 아래로 부드럽게 내려오는 애니메이션
while (elapsedTime < landDuration)
{
plant.transform.position = Vector2.SmoothDamp(plant.transform.position, initialPosition, ref velocity, smoothTime);
elapsedTime += Time.deltaTime;
yield return null; // 다음 프레임을 기다림
}
// 마지막으로 정확한 착지 위치로 설정
plant.transform.position = initialPosition;
interactable.canInteract = true;
}
void OnDayEnd()
{
// wateredTiles의 키를 미리 복사하여 List에 저장
List<Vector3Int> wateredTilesKey = tileManager.GetWateredTilesKeys();
foreach (var position in wateredTilesKey)
{
if (tileManager.GetWateringTile(position) && plantGrowthDays.ContainsKey(position))
{
plantGrowthDays[position]++;
StartCoroutine(GrowPlant(position));
tileManager.SetWateringTile(position, false);
}
TileBase tile = tileManager.interactableMap.GetTile(position);
if (tile != null)
tileManager.interactableMap.SetColor(position, Color.white);
}
}
public PlantData GetPlantData(Vector3Int position)
{
if(plantDataDict.ContainsKey(position))
return plantDataDict[position];
return null;
}
public void RemovePlantData(Vector3Int position)
{
plantDataDict.Remove(position);
currentGrowthStages.Remove(position);
plantGrowthDays.Remove(position);
}
}
728x90
'TIL' 카테고리의 다른 글
[Unity] Valley - 과일 나무(과일 , 나무조각 드랍) , 아이템 박스 인식 & 애니메이션 (0) | 2024.10.28 |
---|---|
[Unity] Valley - 나무 자르기(나무 애니메이션, 나무조각 생성) (0) | 2024.10.25 |
[Unity] Valley - DayCycle & 식물 성장 시스템 (1) | 2024.10.24 |
[Unity] Valley - 아이템 리팩토링 / 인벤토리 & Toolbar 간 슬롯 이동 (0) | 2024.10.18 |
[Unity] Valley - 인벤토리 시스템 (0) | 2024.10.16 |