Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- public class WaveFloor : MonoBehaviour
- {
- [Header("Basic")]
- public MeshFilter meshFilter;
- [Header("Floor")]
- [Tooltip("Where the floor should start")]
- public Transform transformStart;
- [Tooltip("Where the floor should end")]
- public Transform transformEnd;
- [Min(2)]
- [Tooltip("How many modules the floor will have")]
- public int floorParts = 8;
- [Tooltip("How strong should the waving be")]
- public float power = 0.5f;
- [Tooltip("How quick should the waving be")]
- public float speed = 1.2f;
- [Tooltip("Y offset of the vertices")]
- public float yOffset = 0.5f;
- [Tooltip("Speed offset")]
- public float speedOffset = 0.5f;
- [Tooltip("How high should the floor be")]
- public float floorHeight = 0.5f;
- [Header("Colliders")]
- [Tooltip("How many capsule colliders will handle this floor")]
- public int collidersAmount = 32;
- public float colliderRadius = 0.5f;
- public float colliderHeight = 8f;
- private CapsuleCollider[] capsuleColliders;
- private int vertexAmount;
- private Vector3[] vertices;
- private Mesh mesh;
- private void Start()
- {
- mesh = CreateMesh();
- CreateColliders();
- meshFilter.sharedMesh = mesh;
- }
- #if UNITY_EDITOR
- private void OnDrawGizmos()
- {
- // Some rendering for the scene view so we know what's up.
- if(transformStart == null)
- {
- return;
- }
- if(transformEnd == null)
- {
- return;
- }
- Color color = Color.red;
- color.a = 0.4f;
- Gizmos.color = color;
- Vector3 start = transformStart.position;
- Vector3 end = transformEnd.position;
- Vector3 size = (end - start);
- Vector3 middle = start + (size * 0.5f);
- size.y = floorHeight;
- Gizmos.DrawCube(middle, size);
- }
- #endif
- private void FixedUpdate()
- {
- UpdateWaveFloor();
- }
- private void UpdateWaveFloor()
- {
- // Animate the floor vertices over time.
- //
- // This code could have been jobified and bursted, so if you ever need a ton of those moving floors
- // it's a pretty quick way to optimize it.
- Vector3 start = transformStart.position;
- Vector3 end = transformEnd.position;
- float stepX = (end.x - start.x) / floorParts;
- Vector3 currentStart = start;
- Vector3 currentEnd = new Vector3(start.x + stepX, end.y, end.z);
- for (int i = 0; i <= floorParts; i++)
- {
- float currentOffset = i * speedOffset;
- float yPositon = currentStart.y + power * Mathf.Sin((Time.time + currentOffset) * speed) + yOffset;
- vertices[i * 4] = new Vector3(currentStart.x,
- yPositon,
- currentStart.z);
- vertices[i * 4 + 1] = new Vector3(currentStart.x,
- yPositon,
- currentEnd.z);
- vertices[i * 4 + 2] = new Vector3(currentStart.x,
- yPositon - floorHeight,
- currentEnd.z);
- vertices[i * 4 + 3] = new Vector3(currentStart.x,
- yPositon - floorHeight,
- currentStart.z);
- currentStart.x = currentStart.x + stepX;
- currentEnd.x = currentEnd.x + stepX;
- }
- Vector3 position = Vector3.zero;
- position.y = end.y;
- float stepXColliders = (end.x - start.x) / (collidersAmount - 1);
- float speedOffsetMultiplier = stepXColliders / stepX;
- float colliderYOffset = colliderRadius;
- for (int i = 0; i < capsuleColliders.Length; i++)
- {
- float currentOffset = i * speedOffset * speedOffsetMultiplier;
- float yPositon = currentStart.y + power * Mathf.Sin((Time.time + currentOffset) * speed) + yOffset;
- CapsuleCollider collider = capsuleColliders[i];
- position.x = start.x + i * stepXColliders;
- position.y = yPositon - colliderYOffset;
- collider.center = position;
- }
- mesh.vertices = vertices;
- mesh.RecalculateNormals();
- mesh.UploadMeshData(false);
- }
- private void CreateColliders()
- {
- //Create capsule colliders to handle collisions.
- //
- //You could also skip this if you don't care about primitive colliders and just throw in the generated mesh
- //into a mesh collider component and collisions will be more accurate. Do have in mind though that it might be less performant if updated each frame.
- capsuleColliders = new CapsuleCollider[collidersAmount];
- Vector3 start = transformStart.position;
- Vector3 end = transformEnd.position;
- Vector3 difference = end - start;
- Vector3 position = Vector3.zero;
- float yOffset = colliderRadius;
- position.y = end.y - yOffset;
- float xStep = difference.x / (collidersAmount-1);
- for (int i = 0; i < collidersAmount; i++)
- {
- CapsuleCollider collider = gameObject.AddComponent<CapsuleCollider>();
- collider.height = colliderHeight;
- collider.radius = colliderRadius;
- collider.direction = 2; //This makes it streched using its height on the z axis.
- position.x = start.x + i * xStep;
- collider.center = position;
- capsuleColliders[i] = collider;
- }
- }
- private Mesh CreateMesh()
- {
- // We'll do a procedural mesh generation using extruding approach, starting
- // from the left side and stepping towards the end at the right side.
- Mesh mesh = new Mesh();
- mesh.name = "Wave Floor";
- //Some quick maths to create arrays of just right sizes to not have to resize them.
- Vector3 start = transformStart.position;
- Vector3 end = transformEnd.position;
- vertexAmount = 12 + 4 * (floorParts - 2);
- int triangleAmount = 20 + 8 * (floorParts - 2);
- vertices = new Vector3[vertexAmount];
- int[] triangles = new int[triangleAmount * 3];
- float stepX = (end.x - start.x) / floorParts;
- Vector3 currentStart = start;
- Vector3 currentEnd = new Vector3(start.x + stepX, end.y, end.z);
- // Start/Left part
- //
- // Top
- // ..1..
- // 0` | `2
- // |``-3-``|
- // | | |
- // | ..5.. |
- // 4` | `6
- // ``-7-``
- // Bottom
- //
- // 0,1,2,3 - Top
- // 5,4,7,6 - Bottom
- // 4,0,3,7 - Front
- // Skip right, no wall needed
- // 1,0,4,5 - Left
- // 2,1,5,6 - Back
- vertices[0] = currentStart;
- vertices[1] = new Vector3(currentStart.x, currentStart.y, currentEnd.z);
- vertices[2] = new Vector3(currentStart.x, currentStart.y - floorHeight, currentEnd.z);
- vertices[3] = new Vector3(currentStart.x, currentStart.y - floorHeight, currentStart.z);
- int triangleID = 0;
- triangles[triangleID] = 1; triangleID++;
- triangles[triangleID] = 0; triangleID++;
- triangles[triangleID] = 3; triangleID++;
- triangles[triangleID] = 3; triangleID++;
- triangles[triangleID] = 2; triangleID++;
- triangles[triangleID] = 1; triangleID++; //Left
- // Middle part
- //
- // Top
- // ..1..
- // 0` | `2
- // |``-3-``|
- // | | |
- // | ..5.. |
- // 4` | `6
- // ``-7-``
- // Bottom
- //
- // 0,1,2,3 - Top
- // 5,4,7,6 - Bottom
- // 4,0,3,7 - Front
- // Skip right, no wall needed
- // Skip left, no wall needed
- // 2,1,5,6 - Back
- //
- // Iterate until we'll generate all the floor parts
- // Congratulations. You are one of the few people to reach this place :)
- int i = 0;
- for (i = 0; i < floorParts; i++)
- {
- vertices[i * 4 + 4] = new Vector3(currentEnd.x, currentStart.y, currentStart.z);
- vertices[i * 4 + 5] = new Vector3(currentEnd.x, currentStart.y, currentEnd.z);
- vertices[i * 4 + 6] = new Vector3(currentEnd.x, currentEnd.y - floorHeight, currentEnd.z);
- vertices[i * 4 + 7] = new Vector3(currentEnd.x, currentStart.y - floorHeight, currentStart.z);
- triangles[triangleID] = i * 4 + 0; triangleID++;
- triangles[triangleID] = i * 4 + 1; triangleID++;
- triangles[triangleID] = i * 4 + 5; triangleID++;
- triangles[triangleID] = i * 4 + 5; triangleID++;
- triangles[triangleID] = i * 4 + 4; triangleID++;
- triangles[triangleID] = i * 4 + 0; triangleID++; //Top
- triangles[triangleID] = i * 4 + 3; triangleID++;
- triangles[triangleID] = i * 4 + 7; triangleID++;
- triangles[triangleID] = i * 4 + 6; triangleID++;
- triangles[triangleID] = i * 4 + 6; triangleID++;
- triangles[triangleID] = i * 4 + 2; triangleID++;
- triangles[triangleID] = i * 4 + 3; triangleID++; //Bottom
- triangles[triangleID] = i * 4 + 0; triangleID++;
- triangles[triangleID] = i * 4 + 4; triangleID++;
- triangles[triangleID] = i * 4 + 7; triangleID++;
- triangles[triangleID] = i * 4 + 7; triangleID++;
- triangles[triangleID] = i * 4 + 3; triangleID++;
- triangles[triangleID] = i * 4 + 0; triangleID++; //Front
- triangles[triangleID] = i * 4 + 5; triangleID++;
- triangles[triangleID] = i * 4 + 1; triangleID++;
- triangles[triangleID] = i * 4 + 2; triangleID++;
- triangles[triangleID] = i * 4 + 2; triangleID++;
- triangles[triangleID] = i * 4 + 6; triangleID++;
- triangles[triangleID] = i * 4 + 5; triangleID++; //Back
- currentStart.x = currentStart.x + stepX;
- currentEnd.x = currentEnd.x + stepX;
- }
- // End/Right part
- // Top
- // ..1..
- // 0` | `2
- // |``-3-``|
- // | | |
- // | ..5.. |
- // 4` | `6
- // ``-7-``
- // Bottom
- //
- // 0,1,2,3 - Top
- // 5,4,7,6 - Bottom
- // 4,0,3,7 - Front
- // Skip left, no wall needed
- // 1,0,4,5 - Right
- // 2,1,5,6 - Back
- triangles[triangleID] = i * 4 + 0; triangleID++;
- triangles[triangleID] = i * 4 + 1; triangleID++;
- triangles[triangleID] = i * 4 + 2; triangleID++;
- triangles[triangleID] = i * 4 + 2; triangleID++;
- triangles[triangleID] = i * 4 + 3; triangleID++;
- triangles[triangleID] = i * 4 + 0; triangleID++; //Right
- mesh.vertices = vertices;
- mesh.triangles = triangles;
- mesh.RecalculateNormals();
- mesh.UploadMeshData(false);
- return mesh;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment