책장 첫줄 자동

This commit is contained in:
dldydtn9755-crypto
2026-07-10 21:33:59 +09:00
parent 9073825501
commit e927f24ad8
205 changed files with 597 additions and 403 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f936f05cbf9b1004ca04bb731f53e11e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
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);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 459335048be3f7f478ee1aa64d9dca2e