AR 증강현실 비대면 합방 [홍드로이드x고라니]




MapManager.cs 소스입니다



using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapManager : MonoBehaviour
{
    public readonly int SIZE = 16;              // Inspector의 한 페이지에 표시 될 Cell 의 최대 갯수
    public GameObject[] GrassMaps;              // 타일 맵 오브젝트의 배열
    [HideInInspector] public int curGrassMap;   // 현재 타일 맵의 포지션
    [HideInInspector] public int pageIndex;     // 현재 Page Index
    [HideInInspector] public Transform MapsTR;  // Maps 오브젝트의 Tranform       
    [HideInInspector] public GameObject PreviewMap;
    [HideInInspector] public Material PreviewMapMt;

                                                
    public void MovePage(bool isPrevious)       
    {
int maxPageIndex = GrassMaps.Length / SIZE;

        if (isPrevious)
        {
            if (--pageIndex < 0) pageIndex = maxPageIndex;
        }
        else
        {
            if (++pageIndex > maxPageIndex) pageIndex = 0;
        }
    }    

    public float RoundFloat(float f) 
    {
        float gap = f % 100;
        float floorFloat = 0;
        if (f > 0) floorFloat = f - gap;
        else floorFloat = f - gap - 100;

        return floorFloat;
    }

}








MapEditor.cs 소스입니다



using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(MapManager)), CanEditMultipleObjects]
class MapEditor : Editor
{
MapManager MM;  // MapManager Script
int selectToolIndex = 0;




// 해당 Object가 마우스로 선택되어 사용가능한 상태에 딱 1번 호출됨.. (초기화 구문을 적는것이 좋음)
void OnEnable()
{
        MM = GameObject.FindWithTag("MapManager").GetComponent<MapManager>();
}

void OnDisable()
{
if (MM.PreviewMap != null) DestroyImmediate(MM.PreviewMap);
}

// 일반적인 Scene Script의 Update 생명주기와 같다고 보면 됨..
protected virtual void OnSceneGUI()
    {
Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
Vector3 mousePos = mouseRay.GetPoint((-mouseRay.origin.y) / mouseRay.direction.y);
Event current = Event.current;

// 미리보기
if (selectToolIndex == 1) 
{
Vector3 RoundPos = new Vector3(MM.RoundFloat(mousePos.x), 0, MM.RoundFloat(mousePos.z));

if (MM.PreviewMap == null) 
{
MM.PreviewMap = Instantiate(MM.GrassMaps[MM.curGrassMap], RoundPos, Quaternion.identity);
MM.PreviewMap.transform.SetParent(MM.MapsTR);
MM.PreviewMap.transform.SetAsFirstSibling();
MM.PreviewMap.name = "PreviewMap";
MM.PreviewMap.GetComponent<MeshCollider>().enabled = false;

Material originMt = MM.GrassMaps[MM.curGrassMap].GetComponent<Renderer>().sharedMaterial;
Renderer PreviewRenderer = MM.PreviewMap.GetComponent<Renderer>();

PreviewRenderer.sharedMaterial = MM.PreviewMapMt;
PreviewRenderer.sharedMaterial.mainTexture = originMt.mainTexture;
PreviewRenderer.sharedMaterial.color = new Color(originMt.color.r, originMt.color.g, originMt.color.b, 0.4f);
PreviewRenderer.sharedMaterial.SetColor("_SpecColor", originMt.GetColor("_SpecColor"));
}
MM.PreviewMap.transform.position = RoundPos;
}


if (current.type == EventType.MouseDown && current.button == 0) 
{
if (selectToolIndex == 0) return;

GameObject hitObj = null; 
Vector3 screenPosition = Event.current.mousePosition;
screenPosition.y = Camera.current.pixelHeight - screenPosition.y;
Ray ray = Camera.current.ScreenPointToRay(screenPosition);
if (Physics.Raycast(ray, out RaycastHit hit)) hitObj = hit.collider.gameObject;

if (selectToolIndex == 1)
{
// 생성
if (hitObj != null) return;

Vector3 RoundPos = new Vector3(MM.RoundFloat(mousePos.x), 0, MM.RoundFloat(mousePos.z));
GameObject curGrassMap = MM.GrassMaps[MM.curGrassMap];

/* Spawn Object 생성  */
Transform spawnParentTR = new GameObject(curGrassMap.name).transform;
spawnParentTR.position = RoundPos + new Vector3(50, 0, 50);
spawnParentTR.name = curGrassMap.name;
Transform spawnTR = Instantiate(curGrassMap, RoundPos, Quaternion.identity).transform;
spawnTR.name = curGrassMap.name;
spawnTR.SetParent(spawnParentTR);
spawnParentTR.SetParent(MM.MapsTR);
}
else if (selectToolIndex == 2) 
{
// 회전
if (hitObj == null) return;
hitObj.transform.parent.Rotate(0, 90, 0);
}

else if (selectToolIndex == 3)
{
// 파괴
if (hitObj == null) return;
DestroyImmediate(hitObj.transform.parent.gameObject);
}
}

if (current.type == EventType.Layout)
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
}



// Inspector의 GUI를 조작할 시에 호출 됨.. ex ) 마우스 오버, Inspector내에 값 수정...
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
Event current = Event.current;


/* Paging Control Button Area */
GUILayout.BeginHorizontal();
if (GUILayout.Button("<", GUILayout.Width(70), GUILayout.Height(30))) { MM.MovePage(true); MM.curGrassMap = -1; }
GUILayout.FlexibleSpace();
selectToolIndex = GUILayout.SelectionGrid(selectToolIndex, new string[4] { "없음", "생성", "회전", "파괴" }, 4, GUILayout.Width(300), GUILayout.Height(30));
GUILayout.FlexibleSpace();
if (GUILayout.Button(">", GUILayout.Width(70), GUILayout.Height(30))) { MM.MovePage(false); MM.curGrassMap = -1; }
GUILayout.EndHorizontal();


/* Map Object의 Thumnail 을 가져옴 */
Texture[] GrassTextures = new Texture[MM.SIZE];
for (int i = 0; i < MM.SIZE; i++)
{
int curIndex = i + MM.SIZE * MM.pageIndex;
if (curIndex >= MM.GrassMaps.Length) break;
GrassTextures[i] = AssetPreview.GetAssetPreview(MM.GrassMaps[curIndex]);
}

/* 선택 된 Map Object의 Index 를 가져옴.. */
EditorGUI.BeginChangeCheck();
int selectMapIndex = GUILayout.SelectionGrid(MM.curGrassMap % MM.SIZE, GrassTextures, 4);
if (EditorGUI.EndChangeCheck()) 
{
MM.curGrassMap = selectMapIndex + MM.SIZE * MM.pageIndex;
if(MM.PreviewMap != null) DestroyImmediate(MM.PreviewMap);

}
}


}