[Unity] Electricity (11)

suhan0304·2024년 6월 5일

유니티-Electricity

목록 보기
11/18
post-thumbnail

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를 하나 만들어서 프리팹화 해줬다.


추후 계획

이것 저것 수정하고 최적화하느라 너무 오래 걸렸다.. 이제 진짜 맵 에디터를 제작해보자.

profile
Be Honest, Be Harder, Be Stronger

0개의 댓글