I’m trying to make a wall using EditableMeshes. However, if you render it on the server, it ONLY renders correctly on the server.
This is a wall generated on the server
But on the client, you can see it has not rendered correctly whatsoever. It’s just a little cube
local WALL_THICKNESS = 0.8
local WALL_HEIGHT = 14
local AssetService = game:GetService("AssetService")
local RunService = game:GetService("RunService")
-- Given 4 vertex IDs, adds a quad with shared normals for smooth shading
local function addSmoothQuad(eMesh, vid0, vid1, vid2, vid3, normal0, normal1, normal2, normal3)
local nid0 = eMesh:AddNormal(normal0)
local nid1 = eMesh:AddNormal(normal1)
local nid2 = eMesh:AddNormal(normal2)
local nid3 = eMesh:AddNormal(normal3)
local fid1 = eMesh:AddTriangle(vid2, vid1, vid0)
eMesh:SetFaceNormals(fid1, {nid2, nid1, nid0})
local fid2 = eMesh:AddTriangle(vid3, vid2, vid0)
eMesh:SetFaceNormals(fid2, {nid3, nid2, nid0})
end
-- Creates a straight wall mesh between two points in local space (0,0,0 centered)
local function makeWallMesh(length)
local eMesh = AssetService:CreateEditableMesh()
-- Create vertices in local space, centered at origin
local halfLength = length/2
-- Calculate vertices for the wall
local backTopLeft = Vector3.new(-halfLength, WALL_HEIGHT, WALL_THICKNESS/2)
local backTopRight = Vector3.new(halfLength, WALL_HEIGHT, WALL_THICKNESS/2)
local backBottomLeft = Vector3.new(-halfLength, 0, WALL_THICKNESS/2)
local backBottomRight = Vector3.new(halfLength, 0, WALL_THICKNESS/2)
local frontTopLeft = Vector3.new(-halfLength, WALL_HEIGHT, -WALL_THICKNESS/2)
local frontTopRight = Vector3.new(halfLength, WALL_HEIGHT, -WALL_THICKNESS/2)
local frontBottomLeft = Vector3.new(-halfLength, 0, -WALL_THICKNESS/2)
local frontBottomRight = Vector3.new(halfLength, 0, -WALL_THICKNESS/2)
-- Add vertices
local v1 = eMesh:AddVertex(backBottomLeft)
local v2 = eMesh:AddVertex(backBottomRight)
local v3 = eMesh:AddVertex(backTopLeft)
local v4 = eMesh:AddVertex(backTopRight)
local v5 = eMesh:AddVertex(frontBottomLeft)
local v6 = eMesh:AddVertex(frontBottomRight)
local v7 = eMesh:AddVertex(frontTopLeft)
local v8 = eMesh:AddVertex(frontTopRight)
-- Front face
addSmoothQuad(
eMesh,
v5, v6, v8, v7,
Vector3.new(0, 0, -1), Vector3.new(0, 0, -1),
Vector3.new(0, 0, -1), Vector3.new(0, 0, -1)
)
-- Back face
addSmoothQuad(
eMesh,
v2, v1, v3, v4,
Vector3.new(0, 0, 1), Vector3.new(0, 0, 1),
Vector3.new(0, 0, 1), Vector3.new(0, 0, 1)
)
-- Top face
addSmoothQuad(
eMesh,
v7, v8, v4, v3,
Vector3.new(0, 1, 0), Vector3.new(0, 1, 0),
Vector3.new(0, 1, 0), Vector3.new(0, 1, 0)
)
-- Bottom face
addSmoothQuad(
eMesh,
v1, v2, v6, v5,
Vector3.new(0, -1, 0), Vector3.new(0, -1, 0),
Vector3.new(0, -1, 0), Vector3.new(0, -1, 0)
)
-- End caps
addSmoothQuad(
eMesh,
v1, v5, v7, v3,
Vector3.new(-1, 0, 0), Vector3.new(-1, 0, 0),
Vector3.new(-1, 0, 0), Vector3.new(-1, 0, 0)
)
addSmoothQuad(
eMesh,
v6, v2, v4, v8,
Vector3.new(1, 0, 0), Vector3.new(1, 0, 0),
Vector3.new(1, 0, 0), Vector3.new(1, 0, 0)
)
eMesh:RemoveUnused()
return eMesh
end
-- Create and setup the wall part
local function createDynamicWall()
-- First create a MeshPart with initial mesh
local initialMesh = makeWallMesh(1)
local meshPart = AssetService:CreateMeshPartAsync(Content.fromObject(initialMesh))
meshPart.Name = "DynamicWall"
meshPart.Material = Enum.Material.SmoothPlastic
meshPart.Anchored = true
meshPart.Parent = workspace
local currentLength = 1
local function updateWall(startPos, endPos)
-- Calculate wall properties
local wallVector = endPos - startPos
local length = wallVector.Magnitude
local midPoint = startPos:Lerp(endPos, 0.5)
local direction = wallVector.Unit
-- Update mesh if length changed
if math.abs(length - currentLength) > 0.01 then
local wallMesh = makeWallMesh(length)
meshPart:ApplyMesh(AssetService:CreateMeshPartAsync(Content.fromObject(wallMesh)))
-- Update the MeshPart's size to match new length
meshPart.Size = Vector3.new(length, WALL_HEIGHT, WALL_THICKNESS)
currentLength = length
end
-- Calculate orientation
local rightVector = direction
local upVector = Vector3.new(0, 1, 0)
local forwardVector = rightVector:Cross(upVector)
-- Set CFrame
meshPart.CFrame = CFrame.fromMatrix(
midPoint,
rightVector,
upVector,
forwardVector
)
end
return meshPart, updateWall
end
-- Example usage:
local wall, updateWall = createDynamicWall()
local startPos = workspace.PartA.Position -- Replace with your dynamic positions
local endPos = workspace.PartB.Position -- Replace with your dynamic positions
updateWall(startPos, endPos)
Expected behavior
The wall should render correctly across client/server. Otherwise, this whole feature is borderline useless