LOD-- Where do I put the scripts and animators? The group or the meshes?

I’m a decent animator just trying to make something of quality for the Unity store for the first time. I’m not a programmer and I’ve had to invest a lot of time fiddling with Unity just to get this far…

I managed to get a root-motion monster working so far like this:

mesh.fbx with an animator (targets the appropriate animator controller and avatar), character controller, and a test script that takes keyboard input to play various animations, some of them selected randomly. It uses individually saved animation fbx files. It moves around just fine.

So I spent most of a week making a 4-level LOD set, assuming what I’d seen of the LOD-Group component that it was simple to use. No.

I made an empty object, named it, dropped the 4 meshes under it, added an LOD-Group component and dragged the meshes into their slots. Works fine. And this is where all documentation stops, assuming I’m supposed to be an experienced programmer in Unity I guess.

Now to make it move like the original non LOD version does. Duplicating the animator, character controller and script (like I had on the working non-LOD original mesh) on the “LOD group object” results in nothing-- Frozen model. So I thought perhaps the individual meshes need to be the ones with the animator. So I move the animator from the group object to its mesh children. That results in a moving, idling mesh but it is not responding to the script. So I moved the character controller from the LOD group object to its mesh children. Same thing-- no response to the script.

So here is where it gets stupid. I moved the keyboard-input script that manages the character controller from the LOD group object to its 4 mesh children. Oh it animates alright and takes keyboard input, but as I suspected, its considering each of these LOD levels its own instance of the script. When I pick a random animation, the different LODs are going their own way. As you zoom in and out you see the monster pop from here to there as it plays different animations. Obviously the script is supposed to be on the parent LOD group but it DOES NOT WORK.

None of this stuff is in the documentation. Every artist is going to encounter this problem. Even though I’m not a programmer, I know that the whole point of a LOD group would be to have it do nothing but control what mesh is being shown, but not what behaviors each LOD had. Or am I wrong and its that I cant have randomness in anything using an LOD because games never should have random animations of course! /sarc

Unity is frustrating for pure artists. Anyone got any solutions? Whats the “right” way.

Consider checking out a couple free asset packs with lods if you do not get a direct response. I have set up lods for only static meshes, but it sounds like you are probably missing a step, or doing something out of order. I’ve not experienced or read about lods not working like you have explained.
Side note: I’m also an animator and understand the frustration experienced. But - once things start to fall in line within Unity you’ll start to feel a lot better about working with it. This is like when starting to work with animation software for the first time, and having to deal with modeling, lighting, textures, shaders, particles etc within the software - when all you want to do is animate! :slight_smile: It gets easier the more time you spend in the software.

As far as I know you have to copy the rig of the main skinned mesh renderer to all of the skinned mesh renderers that are LODs like doing it to merge hair/clothes to the character.

I don’t know if this will work in your case (it didn’t in mine, but I guess the guy who made the asset failed to setup the LODs, but it still animates, only the mesh looks bad).

Well here is the script, let me know if it works. Add this script to your LODs and where it says Source Human Body add the first skinned mesh renderer. The script has 2 methods that do the same thing, you can just leave it as it is or use the second one if you prefer (It will ignore the bones that fail to map, while the first script will ignore every bone if one fails, imo it’s better because you know something messed up)

using System.Collections;
using System.Collections.Generic;
using Devdog.General.ThirdParty.UniLinq;
using UnityEngine;

public class BonesDuplicator : MonoBehaviour
{

    void Start()
    {
        CopyBones();
    }

    // Your character's Shape (containing Skinned Mesh Renderer)
    [SerializeField] private GameObject _sourceHumanBody;

    private void CopyBones()
    {
        var sourceRenderer = _sourceHumanBody.GetComponent<SkinnedMeshRenderer>();
        var targerRenderer = GetComponent<SkinnedMeshRenderer>();

        targerRenderer.bones = sourceRenderer.bones.Where(b => targerRenderer.bones.Any(t => t.name.Equals(b.name)))
            .ToArray();
    }

    private void CopyBonesWithDictionary()
    {
        SkinnedMeshRenderer targetRenderer = _sourceHumanBody.GetComponent<SkinnedMeshRenderer>();

        Dictionary<string, Transform> boneMap = new Dictionary<string, Transform>();
        foreach (Transform bone in targetRenderer.bones)
        {
            boneMap[bone.name] = bone;
        }

        SkinnedMeshRenderer thisRenderer = GetComponent<SkinnedMeshRenderer>();
        Transform[] boneArray = thisRenderer.bones;
        for (int idx = 0; idx < boneArray.Length; ++idx)
        {
            string boneName = boneArray[idx].name;
            if (false == boneMap.TryGetValue(boneName, out boneArray[idx]))
            {
                Debug.LogError("failed to get bone: " + boneName);
                Debug.Break();
            }
        }
        thisRenderer.bones = boneArray;
    }
}

I just gave up and bought this asset lol.

Last time I programmed was on the Atari ST before the invention of object-oriented programming. Unity is forcing me to learn C#, but programming isn’t the same as it was back then… Everything is all abstracted now. I don’t even see where b and t are declared in the CopyBones method. I’ll have to look at the => and see if its the same as >= or is it something else. And I have no idea what Devdog.General.ThirdParty.UniLing is all about. This code is beyond me but I’ll do my best.

I really appreciate your response, guys. I’ll be able to get to it in a few days. Currently I have to figure out layered animation controllers.

You can get rid of that, it’s a custom plugin that I use so it wont work for you. Now when you get rid of it and replace it with this line:

using System.Linq