2026-06-09 룸 프로토타입 디자인 (진행중)
This commit is contained in:
238
Assets/Stylized Water 3/Runtime/Components/WaterGrid.cs
Normal file
238
Assets/Stylized Water 3/Runtime/Components/WaterGrid.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
|
||||
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
|
||||
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
|
||||
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace StylizedWater3
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
[AddComponentMenu("Stylized Water 3/Water Grid")]
|
||||
public class WaterGrid : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Material used on the tile meshes")]
|
||||
public Material material;
|
||||
|
||||
[Tooltip("When not in play-mode, the water will follow the scene-view camera position.")]
|
||||
public bool followSceneCamera = false;
|
||||
[Tooltip("If enabled, the object with the \"MainCamera\" tag will be assigned as the follow target when entering play mode")]
|
||||
public bool autoAssignCamera;
|
||||
[Tooltip("The grid will follow this Transform's position on the XZ axis. Ideally set to the camera's transform.")]
|
||||
public Transform followTarget;
|
||||
|
||||
[Tooltip("Scale of the entire grid in the length and width")]
|
||||
public float scale = 500f;
|
||||
[Range(0.15f, 10f)]
|
||||
[Tooltip("Distance between vertices, rather higher than lower")]
|
||||
public float vertexDistance = 2f;
|
||||
[Min(0)]
|
||||
public int rowsColumns = 4;
|
||||
|
||||
[HideInInspector]
|
||||
public int m_rowsColumns = 4;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Mesh mesh;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private List<WaterObject> objects = new List<WaterObject>();
|
||||
|
||||
[NonSerialized]
|
||||
private float tileSize;
|
||||
[NonSerialized]
|
||||
private WaterObject m_waterObject = null;
|
||||
[NonSerialized]
|
||||
private Transform actualFollowTarget;
|
||||
[NonSerialized]
|
||||
private Vector3 targetPosition;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public static bool DisplayGrid = true;
|
||||
public static bool DisplayWireframe;
|
||||
#endif
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
Recreate();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (autoAssignCamera) followTarget = Camera.main ? Camera.main.transform : followTarget;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.SceneView.duringSceneGui += OnSceneGUI;
|
||||
#endif
|
||||
m_rowsColumns = rowsColumns;
|
||||
|
||||
//Mesh is serialized with the scene, if component is used as a prefab, regenerate it
|
||||
if (mesh == null)
|
||||
{
|
||||
RecreateMesh();
|
||||
ReassignMesh();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDisable()
|
||||
{
|
||||
UnityEditor.SceneView.duringSceneGui -= OnSceneGUI;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Application.isPlaying) actualFollowTarget = followTarget;
|
||||
|
||||
if (actualFollowTarget)
|
||||
{
|
||||
targetPosition = actualFollowTarget.transform.position;
|
||||
|
||||
targetPosition = SnapToGrid(targetPosition, vertexDistance);
|
||||
targetPosition.y = this.transform.position.y;
|
||||
this.transform.position = targetPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void Recreate()
|
||||
{
|
||||
RecreateMesh();
|
||||
|
||||
bool requireRecreate = (m_rowsColumns != rowsColumns) || objects.Count < (rowsColumns * rowsColumns);
|
||||
if (requireRecreate) m_rowsColumns = rowsColumns;
|
||||
|
||||
//Only destroy/recreate objects if grid subdivision has changed
|
||||
if (requireRecreate && objects.Count > 0)
|
||||
{
|
||||
foreach (WaterObject obj in objects)
|
||||
{
|
||||
if (obj) DestroyImmediate(obj.gameObject);
|
||||
}
|
||||
objects.Clear();
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (int x = 0; x < rowsColumns; x++)
|
||||
{
|
||||
for (int z = 0; z < rowsColumns; z++)
|
||||
{
|
||||
if (requireRecreate)
|
||||
{
|
||||
m_waterObject = WaterObject.New(material, mesh);
|
||||
objects.Add(m_waterObject);
|
||||
|
||||
m_waterObject.transform.parent = this.transform;
|
||||
m_waterObject.name = "WaterTile_x" + x + "z" + z;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_waterObject = objects[index];
|
||||
m_waterObject.AssignMesh(mesh);
|
||||
m_waterObject.AssignMaterial(material);
|
||||
}
|
||||
|
||||
m_waterObject.transform.localPosition = GridLocalCenterPosition(x, z);
|
||||
m_waterObject.transform.localScale = Vector3.one;
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateTileSize()
|
||||
{
|
||||
rowsColumns = Mathf.Max(rowsColumns, 0);
|
||||
float m_scale = scale * this.transform.lossyScale.x;
|
||||
tileSize = Mathf.Max(1f, m_scale / rowsColumns);
|
||||
}
|
||||
|
||||
private void RecreateMesh()
|
||||
{
|
||||
CalculateTileSize();
|
||||
|
||||
float m_vertexDistance = vertexDistance * this.transform.lossyScale.x;
|
||||
|
||||
//Value should never be larger than an individual tile
|
||||
m_vertexDistance = Mathf.Min(m_vertexDistance, tileSize);
|
||||
|
||||
mesh = WaterMesh.Create(WaterMesh.Shape.Rectangle, tileSize, m_vertexDistance, tileSize);
|
||||
}
|
||||
|
||||
private void ReassignMesh()
|
||||
{
|
||||
foreach (WaterObject obj in objects)
|
||||
{
|
||||
obj.AssignMesh(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 GridLocalCenterPosition(int x, int z)
|
||||
{
|
||||
return new Vector3(x * tileSize - ((tileSize * (rowsColumns)) * 0.5f) + (tileSize * 0.5f), 0f,
|
||||
z * tileSize - ((tileSize * (rowsColumns)) * 0.5f) + (tileSize * 0.5f));
|
||||
}
|
||||
|
||||
public static Vector3 SnapToGrid(Vector3 position, float cellSize)
|
||||
{
|
||||
return new Vector3(SnapToGrid(position.x, cellSize), SnapToGrid(position.y, cellSize), SnapToGrid(position.z, cellSize));
|
||||
}
|
||||
|
||||
private static float SnapToGrid(float position, float cellSize)
|
||||
{
|
||||
return Mathf.FloorToInt(position / cellSize) * (cellSize) + (cellSize * 0.5f);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (DisplayWireframe)
|
||||
{
|
||||
Gizmos.matrix = this.transform.localToWorldMatrix;
|
||||
Gizmos.color = new Color(0, 0, 0, 0.5f);
|
||||
|
||||
foreach (WaterObject waterObject in objects)
|
||||
{
|
||||
if(waterObject.meshFilter.sharedMesh) Gizmos.DrawWireMesh(waterObject.meshFilter.sharedMesh, waterObject.transform.localPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if (DisplayGrid)
|
||||
{
|
||||
if (tileSize <= 0) CalculateTileSize();
|
||||
|
||||
Gizmos.color = new Color(1f, 0.25f, 0.25f, 0.5f);
|
||||
Gizmos.matrix = this.transform.localToWorldMatrix;
|
||||
|
||||
for (int x = 0; x < rowsColumns; x++)
|
||||
{
|
||||
for (int z = 0; z < rowsColumns; z++)
|
||||
{
|
||||
Vector3 pos = GridLocalCenterPosition(x, z);
|
||||
|
||||
Gizmos.DrawWireCube(pos, new Vector3(tileSize, 0f, tileSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSceneGUI(UnityEditor.SceneView sceneView)
|
||||
{
|
||||
if (followSceneCamera)
|
||||
{
|
||||
actualFollowTarget = sceneView.camera.transform;
|
||||
Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
actualFollowTarget = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user