해당 스크립트를 File Manager 오브젝트에 넣어 오브젝트의 포지션을 농장에 맞추면 된다.
3. 농작물 심기
카메라가 Fleid 카메라로 전환된 경우 = 플레이어가 농장 안으로 들어온 경우에만
농작물이 심어질 수 있도록 GamaManager를 통해 관리해주려고 한다.
using Unity.Cinemachine;
using UnityEngine;
public enum CameraState { Outside, Field, House, Animal }
public class GameManager : Singleton<GameManager>
{
public CameraState cameraState = CameraState.Outside;
[SerializeField] private CinemachineClearShot clearShot;
public void SetCameraState(CameraState newState)
{
if (cameraState != newState)
{
cameraState = newState;
foreach (var camera in clearShot.ChildCameras)
camera.Priority = 1;
clearShot.ChildCameras[(int)cameraState].Priority = 10;
}
}
}
기존에 FieldEvent, HouseEvent, AnimalEvent 스크립트에서 각각 동일하게 처리하던 카메라 우선순위 로직을 통합하기 위해 clearShot 오브젝트를 삭제하고, CameraState 값을 기반으로 조건문 안에서 직접 우선순위를 지정하도록 수정했다.
using UnityEngine;
public class Tile : MonoBehaviour
{
public Vector2Int arrayPos;
}
타일 좌표를 받아오기 위하여 Tile 클래스를 만들어 주었고
using UnityEngine;
public class FieldManager : MonoBehaviour
{
public enum FieldState { Seed, Harvest }
public FieldState fieldState;
[SerializeField] private GameObject tilePrefab;
[SerializeField] private Vector2 fieldSize = new Vector2(6, 8);
[SerializeField] private float tileSize = 2f;
public GameObject plantPrefab;
private GameObject[,] tileArray;
private Camera mainCamera;
[SerializeField] private LayerMask fieldLayerMask;
void Awake()
{
mainCamera = Camera.main;
tileArray = new GameObject[(int)fieldSize.x, (int)fieldSize.y];
CreateField();
}
void Update()
{
if (GameManager.Instance.cameraState == CameraState.Field)
{
switch (fieldState)
{
case FieldState.Seed:
OnSeed();
break;
case FieldState.Harvest:
OnHarvest();
break;
}
}
}
private void CreateField()
{
float offsetX = (fieldSize.x - 1) * tileSize / 2;
float offsetY = (fieldSize.y - 1) * tileSize / 2;
for (int i = 0; i < fieldSize.x; i++)
{
for (int j = 0; j < fieldSize.y; j++)
{
float posX = transform.position.x + i * tileSize - offsetX;
float posZ = transform.position.z + j * tileSize - offsetY;
GameObject tileObj = Instantiate(tilePrefab, transform.GetChild(0));
tileObj.name = $"Tile_{i}_{j}";
tileObj.transform.position = new Vector3(posX, 0, posZ);
// tileArray[i, j] = tileObj;
tileObj.GetComponent<Tile>().arrayPos = new Vector2Int(i, j);
}
}
}
private void OnSeed()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100f, fieldLayerMask))
{
Tile tile = hit.collider.GetComponent<Tile>();
int tileX = tile.arrayPos.x;
int tileY = tile.arrayPos.y;
if (tileArray[tileX, tileY] == null)
{
GameObject plant = Instantiate(plantPrefab, transform.GetChild(1));
plant.transform.position = hit.transform.position;
tileArray[tileX, tileY] = plant;
}
}
}
}
private void OnHarvest()
{
}
}
마우스 클릭 위치 감지
마우스로 클릭한 위치가 어느 타일인지 알아내기 위해 Raycast 활용
fieldLayerMask를 통해서 필드 타일만 충돌 대상으로 설정
충돌한 오브젝트에서 Tile 컴포넌트를 꺼내 arrayPos로 타일의 좌표 파악
농작물이 심어져있지 않은 경우에만 plantPrefab을 해당 위치에 생성
tileArray[x, y]에 생성된 농작물을 참조 저장
Raycast 로직 상세
Input.GetMouseButtonDown(0) 왼쪽 클릭 확인
mainCamera.ScreenPointToRay(Input.mousePosition)로 레이 생성
Physics.Raycast()를 사용하고, fieldLayerMask로 필드 타일만 충돌 대상 지정
hit.collider.GetComponent<Tile>()로 arrayPos 좌표 확인
tileArray[x, y] == null일 때만 프리팹 생성, 배열에 저장
심기 / 수확 로직
Update문에서 현재 Field State가 어떤지 확인
당장은 심기 로직만 구현하였으나 추후 수확 로직도 손쉽게 구현 가능
오늘은 터레인 만질 때 익숙하지가 않아서 진짜 엄청 뒤처졌었다
급하게 부랴부랴 따라가느라 정신이 너무 없었다.. 3시간 동안 한 번도 못 쉬고 ㅠㅠ 에러 고치고 진도 따라가고 우웩