My show of good faith. A script that combines/uncombines skinned mesh at runtime for the unity engine. (whatever)
This is a script i wrote with the help of a GTP model. It combines a skinned mesh at runtime allowing you to have an animated object of n parts combine into 1 object, and thus 1 draw call, at runtime in engine. My game was also kicking parts over the course of n frames, so if performance is an issue, be aware you can make that combination gradually. The major issue with that project was that the vertex order for mesh is lost once your model gets pushed to the gpu, i think that gets stored as a 4x4matrix prior to the decombine/recombing in order to preserve that information. I was working with a robot fps game that had a cascading failure and physics based armor ablation. I am self taught and I will need a job in about 3 months when I fail my startup company. Finally- this is also from a project from a year ago, so if it doesn't work for you then you need to be better at not being a massive faggot.
carbon image for ease on the eyes.
https://files.catbox.moe/3xp71m.png
text for copy/pasta
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshCombiner
{
///
/// Combines meshes and creates a new skinned mesh renderer, parenting to baseBone
///
///
///
///
///
///
Optional UV's to apply to each mesh
///
public static SkinnedMeshRenderer CombineFast(Transform baseBone, Material[] materials, Transform[] bones, Mesh[] meshes, Rect[] rects = null)
{
// Create mesh renderer and fuck the old ones, that kid cant code
GameObject newGameObject = new GameObject("Avatar", typeof(SkinnedMeshRenderer));
newGameObject.transform.parent = baseBone.parent;
newGameObject.transform.localPosition = Vector3.zero;
newGameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);
SkinnedMeshRenderer skinnedMeshRenderer = newGameObject.GetComponent
();
CombineFast(skinnedMeshRenderer, baseBone, materials, bones, meshes, rects);
return skinnedMeshRenderer;
}
///
/// Combines meshes and implements onto an existing skinned mesh renderer + bones
///
///
///
///
///
///
/// Optional UV's to apply to each mesh
public static void CombineFast(SkinnedMeshRenderer skinnedMeshRenderer, Transform baseBone, Material[] materials, Transform[] bones, Mesh[] meshes, Rect[] uvs = null)
{
if (meshes.Length == 0)
return;
CombineInstance[] combineInstances = new CombineInstance[meshes.Length];
for (int i = 0; i < meshes.Length; i++)
{
if (meshes[i] == null || !meshes[i].isReadable)
continue;
combineInstances[i] = new CombineInstance();
combineInstances[i].transform = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.zero), new Vector3(100, 100, 100));
combineInstances[i].mesh = meshes[i];
}
// Combine meshes
Mesh combinedMesh = new Mesh();
combinedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
combinedMesh.CombineMeshes(combineInstances, true, false);
// Align bone weights
int offset = 0;
BoneWeight[] boneWeights = combinedMesh.boneWeights;
for (int i = 0; i < meshes.Length; i++)
{
int boneCount = meshes[i].boneWeights.Length;
for (int j = 0; j < meshes[i].vertexCount; j++)
{
boneWeights[offset + j].boneIndex0 += boneCount * i;
boneWeights[offset + j].boneIndex1 += boneCount * i;
boneWeights[offset + j].boneIndex2 += boneCount * i;
boneWeights[offset + j].boneIndex3 += boneCount * i;
}
offset += meshes[i].vertexCount;
}
// Apply UVs
if (uvs != null)
{
Vector2[] newUvs = combinedMesh.uv;
offset = 0;
for (int i = 0; i < meshes.Length; i++)
{
for (int j = 0; j < meshes[i].vertexCount; j++)
{
Vector2 sourceMeshUV = meshes[i].uv[j];
newUvs[offset + j] = new Vector2(
sourceMeshUV.x * uvs[i].width + uvs[i].x,
sourceMeshUV.y * uvs[i].height + uvs[i].y);
}
offset += meshes[i].vertexCount;
}
combinedMesh.uv = newUvs;
}
// Set up the skinned mesh renderer
combinedMesh.boneWeights = boneWeights;
combinedMesh.RecalculateNormals();
combinedMesh.RecalculateBounds();
skinnedMeshRenderer.sharedMesh = combinedMesh;
skinnedMeshRenderer.sharedMaterials = materials;
skinnedMeshRenderer.bones = bones;
skinnedMeshRenderer.rootBone = baseBone;
}
}