184 lines
5.7 KiB
C#
184 lines
5.7 KiB
C#
using UnityEngine;
|
|
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEditor.SceneManagement;
|
|
#endif
|
|
|
|
public class BookShelfAutoFill : MonoBehaviour
|
|
{
|
|
[Header("책 프리팹들")]
|
|
public GameObject[] bookPrefabs;
|
|
|
|
[Header("책장 배치 설정")]
|
|
public int rows = 4;
|
|
public int booksPerRow = 12;
|
|
|
|
[Tooltip("첫 번째 책 위치. 이 오브젝트 기준 로컬 좌표")]
|
|
public Vector3 startLocalPosition = new Vector3(-1.0f, 0f, 0f);
|
|
|
|
[Tooltip("책 사이 간격. X는 옆으로, Y는 위 칸으로")]
|
|
public Vector3 spacing = new Vector3(0.13f, 0.42f, 0f);
|
|
|
|
[Header("책 랜덤 느낌")]
|
|
public Vector2 randomXOffset = new Vector2(-0.015f, 0.015f);
|
|
public Vector2 randomYOffset = new Vector2(-0.015f, 0.015f);
|
|
public Vector2 randomZOffset = new Vector2(-0.01f, 0.01f);
|
|
|
|
public Vector2 randomHeightScale = new Vector2(0.85f, 1.15f);
|
|
public Vector2 randomWidthScale = new Vector2(0.9f, 1.1f);
|
|
public Vector2 randomDepthScale = new Vector2(0.9f, 1.05f);
|
|
|
|
public Vector2 randomYRotation = new Vector2(-3f, 3f);
|
|
public Vector2 randomZRotation = new Vector2(-2f, 2f);
|
|
|
|
[Header("기본 회전")]
|
|
public Vector3 baseRotation = Vector3.zero;
|
|
|
|
[Header("기타")]
|
|
public bool clearBeforeGenerate = true;
|
|
public int seed = 10;
|
|
|
|
private const string GeneratedParentName = "Generated_Books";
|
|
|
|
[ContextMenu("책 자동 배치")]
|
|
public void GenerateBooks()
|
|
{
|
|
if (bookPrefabs == null || bookPrefabs.Length == 0)
|
|
{
|
|
Debug.LogWarning("[BookShelfAutoFill] Book Prefabs에 책 프리팹을 넣어줘.");
|
|
return;
|
|
}
|
|
|
|
Random.InitState(seed);
|
|
|
|
if (clearBeforeGenerate)
|
|
{
|
|
ClearBooks();
|
|
}
|
|
|
|
GameObject parent = new GameObject(GeneratedParentName);
|
|
parent.transform.SetParent(transform);
|
|
parent.transform.localPosition = Vector3.zero;
|
|
parent.transform.localRotation = Quaternion.identity;
|
|
parent.transform.localScale = Vector3.one;
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
Undo.RegisterCreatedObjectUndo(parent, "Create Generated Books Parent");
|
|
}
|
|
#endif
|
|
|
|
for (int r = 0; r < rows; r++)
|
|
{
|
|
float currentX = startLocalPosition.x;
|
|
|
|
for (int c = 0; c < booksPerRow; c++)
|
|
{
|
|
GameObject prefab = bookPrefabs[Random.Range(0, bookPrefabs.Length)];
|
|
|
|
if (prefab == null)
|
|
continue;
|
|
|
|
GameObject book = CreateBook(prefab, parent.transform);
|
|
|
|
if (book == null)
|
|
continue;
|
|
|
|
float offsetX = Random.Range(randomXOffset.x, randomXOffset.y);
|
|
float offsetY = Random.Range(randomYOffset.x, randomYOffset.y);
|
|
float offsetZ = Random.Range(randomZOffset.x, randomZOffset.y);
|
|
|
|
book.transform.localPosition = new Vector3(
|
|
currentX + offsetX,
|
|
startLocalPosition.y + r * spacing.y + offsetY,
|
|
startLocalPosition.z + offsetZ
|
|
);
|
|
|
|
book.transform.localRotation = Quaternion.Euler(
|
|
baseRotation.x,
|
|
baseRotation.y + Random.Range(randomYRotation.x, randomYRotation.y),
|
|
baseRotation.z + Random.Range(randomZRotation.x, randomZRotation.y)
|
|
);
|
|
|
|
Vector3 originalScale = book.transform.localScale;
|
|
|
|
book.transform.localScale = new Vector3(
|
|
originalScale.x * Random.Range(randomWidthScale.x, randomWidthScale.y),
|
|
originalScale.y * Random.Range(randomHeightScale.x, randomHeightScale.y),
|
|
originalScale.z * Random.Range(randomDepthScale.x, randomDepthScale.y)
|
|
);
|
|
|
|
currentX += spacing.x;
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
EditorUtility.SetDirty(gameObject);
|
|
EditorSceneManager.MarkSceneDirty(gameObject.scene);
|
|
}
|
|
#endif
|
|
|
|
Debug.Log("[BookShelfAutoFill] 책 자동 배치 완료. 마음에 들면 Ctrl+S 저장 후 이 스크립트 컴포넌트는 삭제해도 됨.");
|
|
}
|
|
|
|
[ContextMenu("생성된 책 삭제")]
|
|
public void ClearBooks()
|
|
{
|
|
Transform old = transform.Find(GeneratedParentName);
|
|
|
|
if (old == null)
|
|
{
|
|
Debug.Log("[BookShelfAutoFill] 삭제할 Generated_Books가 없음.");
|
|
return;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
// Inspector가 삭제될 오브젝트를 보고 있으면 에러가 나서 선택을 부모로 돌림
|
|
if (Selection.activeGameObject != null)
|
|
{
|
|
Transform selected = Selection.activeGameObject.transform;
|
|
|
|
if (selected == old || selected.IsChildOf(old))
|
|
{
|
|
Selection.activeGameObject = gameObject;
|
|
}
|
|
}
|
|
|
|
Undo.DestroyObjectImmediate(old.gameObject);
|
|
|
|
EditorUtility.SetDirty(gameObject);
|
|
EditorSceneManager.MarkSceneDirty(gameObject.scene);
|
|
|
|
Debug.Log("[BookShelfAutoFill] 생성된 책 삭제 완료.");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
Destroy(old.gameObject);
|
|
}
|
|
|
|
private GameObject CreateBook(GameObject prefab, Transform parent)
|
|
{
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying)
|
|
{
|
|
GameObject obj = PrefabUtility.InstantiatePrefab(prefab, parent) as GameObject;
|
|
|
|
if (obj != null)
|
|
{
|
|
Undo.RegisterCreatedObjectUndo(obj, "Create Book");
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
#endif
|
|
|
|
return Instantiate(prefab, parent);
|
|
}
|
|
} |