
BuildManager에서 Block을 가져다가 건설할 수 있도록 Block Script를 생성해준 다음에 Node에 onMouseDown 이벤트를 작성해보자. 작성하면서 변수들도 어느정도 정리를 해주어 인스펙터에서 쉽게 어떤 변수인지 파악할 수 있도록 해주었다.
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;
public class Node : MonoBehaviour
{
[Header("Height")]
[SerializeField]
private float nodeHeight = 0; // to calculate buildBlock Position
private float blocksTotalHeight = 0; // total of blocks height on node
[Space(10)]
[Header("Colors")]
[SerializeField]
public Color hoverColor; // color changes when mouse is hovered over
private Renderer rend; // renderer component
private Color startColor; // start color
[Space(10)]
[Header("Block On Node")]
[SerializeField]
private GameObject blockOnNode; // Block Object ( built on node )
private void Start()
{
nodeHeight = transform.localScale.y / 2; // half of node height - for build
rend = GetComponent<Renderer>(); // call renderer component
startColor = rend.material.color; // remember start color
}
private void OnMouseEnter() // When the mouse passes or enters an object collider
{
rend.material.color = hoverColor; // change color to hoverColor
}
private void OnMouseExit() // When the mouse leaves the object collider
{
rend.material.color = startColor; // return color to startColor
}
private void OnMouseDown() //When the mouse click the object collider
{
// Build a Block
BuildBlockOnNode();
}
/// <summary>
/// Build Block On Node
/// - The buildManager holds information about the blocks the player has chosen to build.
/// </summary>
private void BuildBlockOnNode()
{
GameObject blockBuild = BuildManager.instance.GetBlockToBuild();
float blockHeight = blockBuild.transform.localScale.y;
blockOnNode = (GameObject)Instantiate(blockBuild, new Vector3(
transform.position.x, // Build Position - Vector.x
transform.position.y + nodeHeight + blocksTotalHeight + blockHeight, // Build Position - Vector.y
transform.position.z), // Build Position - Vector.z
transform.rotation);
blocksTotalHeight += blockHeight; // Update blocksTotalHeights ( add block height )
Debug.Log("Build the Block!");
}
}
여기서 중요한 점은 블럭을 위로 계속 쌓을 수 있도록 초기 높이값을 지정해주었다. 나중에 Rigidbody 쓸 수 있는데 그러면 어느 정도 높이 위에서 생성한 후 물리 법칙 적용 시켜서 중력으로 떨어지게 하면 저런 높이 계산 과정을 모두 삭제해도 되지만 일단 지금은 Block에 Rigidbody를 추가하게 된다면 그 때 적용시키자.
초기 높이값을 설정해주면 해당 높이에 맞게 Block을 Build 해주고 Node에 지어진 블럭들의 총 높이 변수인 blocksTotalHeight을 늘려줘서 다음 블럭을 지으면 현재 블록의 위에 지어지도록 해준다.

뭔가 이상하다. 초기 높이 값 설정이 좀 이상한거 같은데 한번 확인해보자.
transform.position.y + nodeHeight + blocksTotalHeight + blockHeight
block의 Position은 block의 가운데를 기준으로 결정되기 때문에 blockHeight을 2로 나누어서 더해주어야한다.
transform.position.y + nodeHeight + blocksTotalHeight + (blockHeight/2)

원하는 그림이 나왔다. 막상 Block을 Build하고 나니깐 가시성이 좀 떨어지는점 2가지 있는데
1. 그냥 Instantiate하다 보니깐 "standardBlock(Clone)"이 그냥 아래로 계속해서 생성된다는 점
2. 블럭이 몇 개 쌓여있는지 확인하기 어려운점
먼저 1번을 해결보자. 생성할 때 누른 노드의 자식 오브젝트로 생성되게 해서 Hierarchy가 좀 정돈된 형태로 유지되도록 하고 나중에 노드를 삭제할 일이 생기면 그 위에 쌓여있는 블럭들도 같이 삭제가 될 수 있도록 해보자.
blockOnNode = (GameObject)Instantiate(blockBuild, new Vector3(
transform.position.x, // Build Position - Vector.x
transform.position.y + nodeHeight + blocksTotalHeight + (blockHeight/2), // Build Position - Vector.y
transform.position.z), // Build Position - Vector.z
transform.rotation,
transform);
마지막에 transform을 넣어서 node를 부모 오브젝트로 수정해준다.

자식 오브젝트로 들어가면서 scale에 문제가 발생했다.
blockOnNode = (GameObject)Instantiate(blockBuild, new Vector3(
transform.position.x, // Build Position - Vector.x
transform.position.y + nodeHeight + blocksTotalHeight + (blockHeight/2), // Build Position - Vector.y
transform.position.z), // Build Position - Vector.z
transform.rotation);
blockOnNode.transform.SetParent(transform, true); // set Parent
transform.setParent를 써서 기존 오브젝트의 scale을 유지시켜주도록 한다.
worldPositionStays란 bool 인자가 참일 경우 개체가 이전과 동일한 월드 위치, 각도, 스케일을 유지하도록 부모오브젝트와 관계에 의해 상대적으로 수정된다.

Block이 정상 사이즈로 잘 생성되는 것을 확인할 수 있다. Block을 나중에 기회가 된다면 제작할 예정이지만 일단은 가시성을 높이기 위해 기존 standardBlock을 Cube 오브젝트 1개가 아니라 3개로 다시 제작해서 각 부분별로 다른 Material을 적용시켜서 여러 블럭을 Build해서 올렸을때 개수를 쉽게 파악할 수 있도록 했다. ( 개수를 알아야 어느 정도 높이를 알고 이를 이용한 z 축 플레이가 가능해질 것이라고 생각했다 )

이제 여러개 건설을 해보면 아래처럼 몇개를 쌓아올렸는지 플레이어 입장에서 쉽게 구별할 수 있다.

일단 여러 노드를 여러개 바닥에 깔아놓은 다음에 start와 end Point를 추가할 예정이다. 그리고 카메라 뷰를 키보드를 이용해서 제어할 예정이다. 마우스를 게임 창의 가장자리로 가져갔을때 카메라의 움직임을 추가할지 말지는 실제로 테스트해보고 좀 불편하다 싶으면 키보드로만 카메라 회전 이동 제어를 사용할 예정이다.
일단은 Node들을 이용해 맵을 구성하게 될텐데 카메라가 해당 맵 가운데를 중심으로 어느정도 높이에서 원 형태로 움직이도록 구현할 예정이다.