Skip to content

ThirteeNov

My personal blog about coding and internet

Menu
  • About me
  • About Zofia Kreasi
  • Cart
  • Checkout
  • Making an airplane game from scratch in Unity
  • My account
  • Privacy Policy
  • Privacy Policy – zkLeaderboard
  • Sample Page
  • Shop
  • Tutorials on Learning JavaScript
  • ZKAccounts – Privacy Policy
Menu

Make objects like wires and cables easily in Unity using Ciihuy Curved Mesh

Posted on August 23, 2025August 23, 2025 by Habibie

Welcome to the guide for using Ciihuy Curved Mesh.
This tool allows you to automatically create pipe or cable meshes in Unity, directly from points you define.

First, add the CiihuyCurvedMesh script to an empty GameObject in your scene.
Then, in the Inspector, you’ll see the Points list. Add several Empty GameObjects to this list as your path points.
The order of these points follows the order in the list, so make sure it matches the path you want.

Next, adjust the Mesh Settings.
‘Sides’ defines the number of sides of the mesh. Four sides for a box shape, three for a triangle, or a higher value for a tubular look.
‘Radius’ controls the thickness of the mesh.
You can assign any material you like, such as a cable or pipe material.
If the mesh looks inverted, enable the ‘Invert Normals’ option.

Under Curve Settings, adjust ‘Segments Per Curve’.
A lower value creates straighter lines, while a higher value makes the path smoother and more curved.

You’ll see the mesh generated directly in the Scene View.
If you move the Empty GameObjects, the mesh updates automatically, even without hitting Play.

This tool is perfect for creating cables, pipes, rails, or curved paths in your project, and it’s lightweight enough for mobile use.

Have fun experimenting, and create unique paths to bring your ideas to life!

using System.Collections.Generic;
using UnityEngine;

[ExecuteAlways] // Biar jalan di Editor tanpa Play
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class CiihuyCurvedMesh : MonoBehaviour
{
    [Header("Path Settings")]
    public List<Transform> points = new List<Transform>();

    [Header("Mesh Settings")]
    [Range(3, 64)] public int sides = 4;
    public float radius = 0.5f;
    public Material material;
    public bool invertNormals = false;

    [Header("Curve Settings")]
    [Range(2, 100)] public int segmentsPerCurve = 10;

    private MeshFilter meshFilter;
    private MeshRenderer meshRenderer;

    private Vector3[] lastPointPositions; // Untuk deteksi perubahan posisi

    void OnValidate()
    {
        InitComponents();
        GenerateMesh();
    }

    void Awake()
    {
        InitComponents();
        GenerateMesh();
    }

    void Update()
    {
        if (!Application.isPlaying) // Biar jalan di Editor
        {
            if (PointsMoved())
            {
                GenerateMesh();
            }
        }
    }

    void InitComponents()
    {
        if (!meshFilter) meshFilter = GetComponent<MeshFilter>();
        if (!meshRenderer) meshRenderer = GetComponent<MeshRenderer>();
    }

    bool PointsMoved()
    {
        if (points == null || points.Count == 0) return false;

        if (lastPointPositions == null || lastPointPositions.Length != points.Count)
            lastPointPositions = new Vector3[points.Count];

        bool moved = false;
        for (int i = 0; i < points.Count; i++)
        {
            if (points[i] == null) continue;

            Vector3 pos = points[i].position;
            if (pos != lastPointPositions[i])
            {
                moved = true;
                lastPointPositions[i] = pos;
            }
        }
        return moved;
    }

    void GenerateMesh()
    {
        if (points == null || points.Count < 2) return;

        List<Vector3> splinePoints = GetCatmullRomPoints(points, segmentsPerCurve);
        BuildMesh(splinePoints);

        if (material) meshRenderer.sharedMaterial = material;
    }

    List<Vector3> GetCatmullRomPoints(List<Transform> inputPoints, int segments)
    {
        List<Vector3> result = new List<Vector3>();

        for (int i = 0; i < inputPoints.Count - 1; i++)
        {
            Vector3 p0 = i == 0 ? inputPoints[i].position : inputPoints[i - 1].position;
            Vector3 p1 = inputPoints[i].position;
            Vector3 p2 = inputPoints[i + 1].position;
            Vector3 p3 = (i + 2 < inputPoints.Count) ? inputPoints[i + 2].position : p2;

            for (int j = 0; j < segments; j++)
            {
                float t = j / (float)segments;
                Vector3 point = CatmullRom(p0, p1, p2, p3, t);
                result.Add(transform.InverseTransformPoint(point));
            }
        }

        result.Add(transform.InverseTransformPoint(inputPoints[inputPoints.Count - 1].position));
        return result;
    }

    Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
    {
        return 0.5f * (
            (2 * p1) +
            (-p0 + p2) * t +
            (2 * p0 - 5 * p1 + 4 * p2 - p3) * (t * t) +
            (-p0 + 3 * p1 - 3 * p2 + p3) * (t * t * t)
        );
    }

    void BuildMesh(List<Vector3> path)
    {
        Mesh mesh = new Mesh();
        List<Vector3> vertices = new List<Vector3>();
        List<int> triangles = new List<int>();
        List<Vector2> uvs = new List<Vector2>();

        float totalLength = 0f;
        for (int i = 1; i < path.Count; i++)
            totalLength += Vector3.Distance(path[i - 1], path[i]);

        float currentLength = 0f;

        for (int i = 0; i < path.Count; i++)
        {
            Vector3 forward = (i < path.Count - 1) ? (path[i + 1] - path[i]).normalized : (path[i] - path[i - 1]).normalized;
            Vector3 up = Vector3.up;
            Vector3 right = Vector3.Cross(up, forward).normalized;
            up = Vector3.Cross(forward, right);

            for (int s = 0; s < sides; s++)
            {
                float angle = (s / (float)sides) * Mathf.PI * 2;
                Vector3 offset = (Mathf.Cos(angle) * right + Mathf.Sin(angle) * up) * radius;
                vertices.Add(path[i] + offset);

                uvs.Add(new Vector2(s / (float)sides, currentLength / totalLength));
            }

            if (i < path.Count - 1)
                currentLength += Vector3.Distance(path[i], path[i + 1]);
        }

        for (int i = 0; i < path.Count - 1; i++)
        {
            for (int s = 0; s < sides; s++)
            {
                int curr = i * sides + s;
                int next = i * sides + (s + 1) % sides;
                int currNextRow = (i + 1) * sides + s;
                int nextNextRow = (i + 1) * sides + (s + 1) % sides;

                if (!invertNormals)
                {
                    triangles.Add(curr);
                    triangles.Add(currNextRow);
                    triangles.Add(nextNextRow);

                    triangles.Add(curr);
                    triangles.Add(nextNextRow);
                    triangles.Add(next);
                }
                else
                {
                    triangles.Add(curr);
                    triangles.Add(nextNextRow);
                    triangles.Add(currNextRow);

                    triangles.Add(curr);
                    triangles.Add(next);
                    triangles.Add(nextNextRow);
                }
            }
        }

        mesh.SetVertices(vertices);
        mesh.SetTriangles(triangles, 0);
        mesh.SetUVs(0, uvs);
        mesh.RecalculateNormals();

        meshFilter.sharedMesh = mesh;
    }
}
Post Views: 320
ciihuy2020

Welcome!

  • My YouTube Channel
  • My GitHub Page
  • About me

Categories

  • 3DVista
  • Android
  • Apache
  • C#
  • Cordova
  • Electron & Node JS
  • HTML5, CSS & JavaScript
  • iOS
  • Let's Make Unity Games
  • Misc
  • Photoshop
  • PHP
  • Python
  • Uncategorized
  • Unity
  • WordPress

Recent Posts

  • Make objects like wires and cables easily in Unity using Ciihuy Curved Mesh
  • [SOLVED] Can’t Add Custom Domain to Blogger After Losing CNAME Verification
  • iOS App Icon Generator by CiihuyCom
  • Advanced Blinking Marker Script to show objects position in your game canvas
  • Ciihuy Images Merger – Fast & Easy Online Image Combiner
© 2025 ThirteeNov | Powered by Superbs Personal Blog theme