how to place something on skin of animated object?

i want to place a blood splat on the skin of my player or a NPC when hit.

sure, raycast will give you a hit point of the collider but that’s no use if i want the skin.

so i wrote a handy little bit of code to find the closest bone to the hitpoint

Transform hips = transform.Find("mixamorig:Hips");
        if (!hips)
            Debug.LogError("AiOnDamage ArrowHit NO mixamorig:Hips");

        float closestSoFar = Mathf.Infinity;
        Transform closestBone = null;
        FindClosestBone(hips, hitPosition, ref closestSoFar, ref closestBone);
        Debug.Log("AiOnDamage DoDamage closestBone=" + closestBone);

void FindClosestBone(Transform root, Vector3 point, ref float closestSoFar, ref Transform closestBone)
    {
        foreach(Transform t in root)
        {
            float distFromPoint = Vector3.Distance(t.position, point);
            if (distFromPoint < closestSoFar)
            {
                closestSoFar = distFromPoint;
                closestBone = t;
            }
            
            if (t.childCount > 0)
                FindClosestBone(t, point, ref closestSoFar, ref closestBone);
        }
    }

which is great for parenting something so it moves with the mesh.
but still no idea how to find the exact point on the mesh that matches the hit point
any ideas?

thx

I believe you are looking for decals, ie textures you place on other textures. The new’ish HDRP includes a Decal (“Projector”) Shader you could use: Redirecting to latest version of com.unity.render-pipelines.high-definition , even tho i dont know how well it works with animated meshes.

You could also try writing your own. Overlaying textures should only be a matter of blending two textures together, but i’m not exactly a shader pro and cant say a lot about how difficult it may be to turn this on / off for multiple blood splat locations.
You could use RaycastHit.textureCoord to get the UV coordinates of the texture at the hit location, which gives you information on where to put the decal.

I believe putting the blood splat directly on the material is your only option if you want it to look decent. Otherwise i’m not sure how you would make it deform to follow animations and so on.

1 Like

thanks,
RaycastHit.textureCoord wouldn’t work because it needs a mesh collider and for characters, people typically use capsule colliders for efficiency i guess, and anyhow, i don’t think mesh colliders will deform with the animation

but maybe i could add a temporary mesh collider just to find the uv coord?

i’ll experiment with it, but i think you are right, ‘putting the blood splat directly on the material is your only option if you want it to look decent’

even if its not exactly the right spot, i can probably get it close just from the capsule collider hit

so how to paint directly onto the characters texture?
some discussion here

but no clear answer
UPDATE
i just tried added a blood splat png with transparent background into the detail mask and detail albedo slots on the standard shader and it does work
the trick is how to create potentially hundreds of blood splats in different locations if i go for a pre canned approach, or create an on the fly texture and no idea how to do that

You will probably want to look into writing a small shader to do so. The new shader graph may help, but i’m am not an expert on either. Blending two textures should be rather easy. You can also pass a coordinate for where to put it. So doing it for one blood splat should be trivial. Doing it for multiple… i’m not sure. You may be able to pass an array of coordinates and just place a bloodsplat for each of them, which would make the whole thing kind of easy. But then again, i’m not very experienced at all in writing shaders yet, so that may or may not be possible.