Beginner's Guide: Creating an ESP for Unity Games on Android with LGL Mod Menu
linkPart 1: Adding Overlay in Menu
linkDownload Links and More
Part 1: Adding Overlay in Menu
In this part, we will add an overlay to the LGL Mod Menu. This overlay will allow us to draw lines, text, and other elements on the screen. Before proceeding, ensure you have basic knowledge of setting up a mod menu, including installing AIDE and compiling the mod menu source. If you're new to this, visit this tutorial page by clicking here.
If you're ready, follow these steps:
- Download and Set Up the Mod Menu:
- Download the LGL Mod Menu v4.0 source zip file by clicking here.
- Extract the source file and open it in AIDE.
- If you're following this tutorial exactly, remove
arm64-v8a
fromApplication.mk
to compile only forarmeabi-v7a
. This is because we're creating ESP for a 32-bit game. If you're working on a 64-bit game, you don't need to remove it. - Create the ESPView.java File:
- Navigate to the
java/com/android/support
folder. - Create a new file named
ESPView.java
. - Paste the following code into
ESPView.java
: - Modify Menu.java:
- Open
Menu.java
and create an instance variable forESPView
: - Instantiate
espview
: - Create a static native
Draw
function: - Add
espview
to theWindowManager
and create layout parameters for it: - Add code to remove
espview
when the menu is minimized or destroyed: - Create Header Files in the JNI Folder:
- Navigate to the
jni
folder and create a new folder namedDrawESP
. - Inside
DrawESP
, create two header files:DrawingManager.h
andAadilTypes.h
. - Paste the following code into
DrawingManager.h
: - Paste the following code into
AadilTypes.h
: - Modify Setup.h and main.cpp:
- Rename
Setup.cpp
toSetup.h
in thejni/Menu
folder. - Remove the line referencing
Setup.cpp
inAndroid.mk
. - Include
Setup.h
inmain.cpp
: - Include
DrawingManager.h
inSetup.h
and create a variable forAadilDrawing
: - Create the JNI
Draw
function: - Register the
Draw
function inRegisterMenu
: - Add Features and Test:
- Add the following features list to show toggles and seekbars in the menu:
- Add switch cases to change variable values using views:
- Compile the menu and check if the line appears correctly in the overlay.
package com.android.support;
import android.view.View;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.graphics.Color;
import android.graphics.PorterDuff;
public class ESPView extends View {
private Paint strokePaint;
private int FrameDelay = 33;
public ESPView(Context context) {
super(context);
strokePaint = new Paint();
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setAntiAlias(true);
setFocusableInTouchMode(false);
final Handler framehandler = new Handler();
framehandler.postDelayed(new Runnable() {
@Override
public void run() {
invalidate();
framehandler.postDelayed(this, FrameDelay);
}
}, FrameDelay);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
Menu.Draw(this, canvas);
}
public void DrawLine(Canvas cvs, int a, int r, int g, int b, float strokewidth, float fromX, float fromY, float toX, float toY) {
strokePaint.setColor(Color.argb(a,r,g,b));
strokePaint.setStrokeWidth(strokewidth);
cvs.drawLine(fromX, fromY, toX, toY, strokePaint);
}
}
ESPView espview;
espview = new ESPView(context);
static native void Draw(ESPView espv, Canvas canvas);
mWindowManager = (WindowManager) getContext.getSystemService(getContext.WINDOW_SERVICE);
WindowManager.LayoutParams espparams = new WindowManager.LayoutParams(MATCH_PARENT, MATCH_PARENT,
iparams, (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE), -3);
mWindowManager.addView(espview, espparams);
mWindowManager.addView(rootFrame, vmParams);
public void setVisibility(int view) {
if (rootFrame != null) {
rootFrame.setVisibility(view);
}
if (espview != null) {
espview.setVisibility(view);
}
}
public void onDestroy() {
if (rootFrame != null) {
mWindowManager.removeView(rootFrame);
}
if (espview != null) {
mWindowManager.removeView(espview);
}
}
#include "AadilTypes.h"
bool EnableESP, ESPLine;
int StartPos, EndPos;
void DrawESP(AadilDrawing esp, int width, int height) {
if (!EnableESP) return;
if (ESPLine) {
esp.DrawLine({255,0,0,255}, 2.0f, {StartPos, 0}, {EndPos, 1000});
}
}
#include <jni.h>
struct Vector2 {
float x,y;
};
struct Color {
float r,g,b,a;
};
class AadilDrawing {
private:
JNIEnv *jnienv;
jobject espview;
jobject canvas;
public:
AadilDrawing() {
jnienv = nullptr;
espview = nullptr;
canvas = nullptr;
}
AadilDrawing(JNIEnv *env, jobject esp, jobject cvs) {
this->jnienv = env;
this->espview = esp;
this->canvas = cvs;
}
bool isValid() const {
return (jnienv && espview && canvas);
}
int getWidth() const {
if (isValid()) {
jclass cvs = jnienv->GetObjectClass(canvas);
jmethodID width = jnienv->GetMethodID(cvs, "getWidth", "()I");
return jnienv->CallIntMethod(canvas, width);
}
}
int getHeight() const {
if (isValid()) {
jclass cvs = jnienv->GetObjectClass(canvas);
jmethodID height = jnienv->GetMethodID(cvs, "getHeight", "()I");
return jnienv->CallIntMethod(canvas, height);
}
}
void DrawLine(Color color, float thickness, Vector2 from, Vector2 to) {
if (isValid()) {
jclass cvs = jnienv->GetObjectClass(espview);
jmethodID drawline = jnienv->GetMethodID(cvs, "DrawLine", "(Landroid/graphics/Canvas;IIIIFFFFF)V");
jnienv->CallVoidMethod(espview, drawline, canvas, (int)color.a, (int)color.r, (int)color.g, (int)color.b,
thickness, from.x, from.y, to.x, to.y);
}
}
};
#include "Menu/Setup.h"
#include "DrawESP/DrawingManager.h"
AadilDrawing aadildrawing;
void Draw(JNIEnv *env, jobject cls, jobject espview, jobject cvs) {
aadildrawing = AadilDrawing(env, espview, cvs);
if (aadildrawing.isValid()) DrawESP(aadildrawing, aadildrawing.getWidth(), aadildrawing.getHeight());
}
{OBFUSCATE("Draw"), OBFUSCATE("(Lcom/android/support/ESPView;Landroid/graphics/Canvas;)V"), reinterpret_cast(Draw)},
const char *features[] = {
OBFUSCATE("10_Toggle_Enable ESP"),
OBFUSCATE("20_Toggle_ESP Line"),
OBFUSCATE("30_SeekBar_Start Pos_0_2000"),
OBFUSCATE("40_SeekBar_End Pos_0_2000"),
};
switch (featNum) {
case 10:
EnableESP = boolean;
break;
case 20:
ESPLine = boolean;
break;
case 30:
StartPos = value;
break;
case 40:
EndPos = value;
break;
}
You can download the modified source file by clicking here.
Download Links and More
- Download Tutorial
- Original
- Part 1 (Added Overlay Only)
- Others
Comments