High-performance C# ESP framework for Unity — 3D bounding boxes, 2D collider calculation, Animator skeleton bone tracking, and distance-scaled name tags.
main
1 星
0 フォーク
0 ウォッチャー
更新されました 3 days ago
C#
100%
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System.Collections.Generic;
using UnityEngine;
using CSharpESP.Drawing;
namespace CSharpESP.Renderers
{
public class BoneRenderer
{
// Humanoid bone joint pairs
private static readonly (HumanBodyBones, HumanBodyBones)[] s_BonePairs = new (HumanBodyBones, HumanBodyBones)[]
{
// Head and Spine
(HumanBodyBones.Head, HumanBodyBones.Neck),
(HumanBodyBones.Neck, HumanBodyBones.Chest),
(HumanBodyBones.Chest, HumanBodyBones.Spine),
(HumanBodyBones.Spine, HumanBodyBones.Hips),
// Left Arm
(HumanBodyBones.Neck, HumanBodyBones.LeftShoulder),
(HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm),
(HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm),
(HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand),
// Right Arm
(HumanBodyBones.Neck, HumanBodyBones.RightShoulder),
(HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm),
(HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm),
(HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand),
// Left Leg
(HumanBodyBones.Hips, HumanBodyBones.LeftUpperLeg),
(HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg),
(HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot),
// Right Leg
(HumanBodyBones.Hips, HumanBodyBones.RightUpperLeg),
(HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg),
(HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot)
};
public static void Render(Camera camera, Animator animator, Color color, float thickness = 1.2f)
{
if (animator == null || !animator.isHuman) return;
// Cache bone screen positions to avoid duplicate projections
Dictionary<HumanBodyBones, Vector2> boneScreenMap = new Dictionary<HumanBodyBones, Vector2>();
foreach (var pair in s_BonePairs)
{
if (!TryGetBoneScreenPos(camera, animator, pair.Item1, boneScreenMap, out Vector2 posA))
continue;
if (!TryGetBoneScreenPos(camera, animator, pair.Item2, boneScreenMap, out Vector2 posB))
continue;
RenderHelper.DrawLine(posA, posB, color, thickness);
}
// Draw Head marker
if (TryGetBoneScreenPos(camera, animator, HumanBodyBones.Head, boneScreenMap, out Vector2 headScreen))
{
float headRadius = 4f;
Rect headRect = new Rect(headScreen.x - headRadius, headScreen.y - headRadius, headRadius * 2f, headRadius * 2f);
RenderHelper.DrawBox(headRect, color, 1f);
}
}
private static bool TryGetBoneScreenPos(
Camera camera,
Animator animator,
HumanBodyBones bone,
Dictionary<HumanBodyBones, Vector2> cache,
out Vector2 screenPos)
{
if (cache.TryGetValue(bone, out screenPos))
{
return true;
}
Transform t = animator.GetBoneTransform(bone);
if (t == null)
{
screenPos = Vector2.zero;
return false;
}
if (MathUtils.WorldToScreen(camera, t.position, out screenPos))
{
cache[bone] = screenPos;
return true;
}
return false;
}
}
}