
preview Link : https://velog.io/@suhan0304/Unity-Electricity-10
gitHub Link : https://github.com/suhan0304/Electricity
사이즈가 다른 블럭을 만들다 보니 오류가 생겼다. raycast를 아래쪽을 기준으로 쏘는데 end Point의 높이가 달라질 수도 있다는 점을 망각했다. 그래서 raycast를 옆 방향으로 쏘는 것이 아니라 블럭의 scale Y를 가져와서 시작 점을 애초에 옆 블럭 쪽으로 잡고 아래 방향으로 scale Y만큼 쏘는 방식으로 바꿔보자.
public List<Block> GetBlockAdjacentBlocks()
{
Vector3[] directions = {
Vector3.up,
Vector3.down,
Vector3.left,
Vector3.right,
Vector3.forward,
Vector3.back
};
List<Block> blocksInRaycast = new List<Block>();
LayerMask blockLayer = LayerMask.GetMask("Block");
Vector3 startRayPos = transform.position;
Debug.Log(transform.localScale.y);
float rayDistance = 0f;
foreach (Vector3 direction in directions)
{
Vector3 dir = Vector3.zero;
if (direction == Vector3.up || direction == Vector3.down)
{
rayDistance = transform.localScale.y / 2 + 1.0f;
startRayPos = transform.position;
dir = direction;
}
else
{
rayDistance = transform.localScale.y;
startRayPos = transform.position + direction * transform.localScale.x + new Vector3(0, transform.localScale.y / 2, 0);
dir = Vector3.down;
}
Ray ray = new Ray(startRayPos, dir);
RaycastHit[] hitData = Physics.RaycastAll(ray, rayDistance, blockLayer);
foreach(RaycastHit hit in hitData)
{
if (hit.collider.CompareTag(GameManager.Instance.startTag))
{
ChangeOnState(); // Block State On - Adjacent StartPoint
}
if (hit.collider.CompareTag(GameManager.Instance.endTag))
{
endPoint = hit.collider.gameObject; // if end-Poin is adjacent me : initialization endPoint
}
else {
Block hitBlock = hit.collider.gameObject.GetComponent<Block>();
//Debug.Log(hit.collider.name); // For Debug Test
blocksInRaycast.Add(hitBlock);
}
}
}
return blocksInRaycast;
}
이렇게 수정했는데 작동이 잘 안한다.. Ray 시작 좌표가 잘못된거 같은데 시작 좌표를 출력해서 확인해보자.

localScale로 해서 문제가 발생한 거 같다.
좌표를 찍어주는 메소드를 작성해서 테스트해보자.
/// <summary>
/// Draw Gizmo on Point
/// </summary>
private void OnDrawGizmos()
{
float pointSize = 0.1f;
Color pointColor = Color.red;
Gizmos.color = pointColor;
Gizmos.DrawSphere(gizmoPoint, pointSize);
}

RayCast는 표면에 Ray가 접촉할 때만 감지된다. 따라서 내부에서 출발하도록 하면 감지가 안 된다.
OverlapBox 함수로 구현해보자. 일단 범위를 눈으로 확인하기 위해 기즈모로 확인해보자. 기즈모로 하기전에 오브젝트(애니메이션)의 스케일을 좀 정리해줬다.

/// <summary>
/// Draw Gizmo on Point
/// </summary>
private void OnDrawGizmos()
{
Color pointColor = Color.red;
Gizmos.color = pointColor;
Gizmos.DrawWireCube(transform.position, new Vector3(transform.lossyScale.x*2, 1, 1));
Gizmos.DrawWireCube(transform.position, new Vector3(1, transform.lossyScale.y * 2, 1));
Gizmos.DrawWireCube(transform.position, new Vector3(1, 1, transform.lossyScale.z * 2));
}

기즈모 범위가 상하좌우 블럭을 잘 인지한다. 이제 OverlapBox로 구현해보자.
OverlapBox는 중심을 기준으로 각 축의 방향으로 Vector Size 만큼 가기 때문에 기즈모의 size를 그대로 넣으면 안된다. 따라서 기즈모가 사이즈의 2배로 들어가도록 하고 2배 하기 전의 사이즈를 OverlapBox로 넘겨준다.
실제 OverlapBox 범위를 확인하기 위한 OnDrawGizmos
/// <summary>
/// Draw Gizmo on Point
/// </summary>
private void OnDrawGizmos()
{
Color pointColor = Color.green;
Vector3 size1 = new Vector3(transform.localScale.x, transform.localScale.y / 2, 0.1f);
Vector3 size2 = new Vector3(0.1f, transform.localScale.y, 0.1f);
Vector3 size3 = new Vector3(0.1f, transform.transform.localScale.y / 2, transform.localScale.z);
Gizmos.color = pointColor;
Gizmos.DrawWireCube(transform.position, size1 * 2);
Gizmos.DrawWireCube(transform.position, size2 * 2);
Gizmos.DrawWireCube(transform.position, size3 * 2);
}
/// <summary>
/// Get Block use OverlapBox
/// </summary>
public List<Block> GetBlockAdjacentBlocks()
{
List<Block> blocksInOverlapBox = new List<Block>();
LayerMask blockLayer = LayerMask.GetMask("Block");
Vector3 centerPoint = transform.position;
Vector3 size1 = new Vector3(transform.localScale.x, transform.localScale.y / 2, 0.1f);
Vector3 size2 = new Vector3(0.1f, transform.localScale.y, 0.1f);
Vector3 size3 = new Vector3(0.1f, transform.transform.localScale.y / 2, transform.localScale.z);
List<Collider> colliders = new List<Collider>();
colliders.AddRange(Physics.OverlapBox(centerPoint, size1, Quaternion.identity, blockLayer));
colliders.AddRange(Physics.OverlapBox(centerPoint, size2, Quaternion.identity, blockLayer));
colliders.AddRange(Physics.OverlapBox(centerPoint, size3, Quaternion.identity, blockLayer));
foreach (Collider collider in colliders)
{
if (collider.CompareTag(GameManager.Instance.startTag))
{
ChangeOnState(); // Block State On - Adjacent StartPoint
}
else if (collider.CompareTag(GameManager.Instance.endTag))
{
endPoint = collider.gameObject; // if end-Poin is adjacent me : initialization endPoint
}
else if (collider.CompareTag(GameManager.Instance.blockTag))
{
if (collider.transform != transform)
blocksInOverlapBox.Add(collider.gameObject.GetComponent<Block>());
}
}
return blocksInOverlapBox;
}

이제 높이차가 좀 있어도 높이가 어느 정도 일치하면 전기가 흐르는지 보도록 하자! y좌표를 좀 줄이도록 하자 동일한 블럭이 오면 위에 있는 블럭도 동시에 켜진다..
마이그레이션 모두 완료했다.. 힘든 작업이었다.
굳이 RayCast 쓰지말고 그냥 Overlap을 쓸 걸 그랬다..
추가적으로 StartNode와 EndNode를 하나 만들어서 프리팹화 해줬다.
이것 저것 수정하고 최적화하느라 너무 오래 걸렸다.. 이제 진짜 맵 에디터를 제작해보자.