mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
2037 字
5 分钟
Mixin基础教程
2026-05-27

参考文献#

FabricMC 的 mixin 介绍

前言#

很多人在刚接触 Minecraft 模组开发时,第一次看到 Mixin 都会觉得它像“黑魔法”

它确实和普通的继承、接口、事件监听不太一样,因为它做的事情是:在类加载时,直接把你的逻辑插进目标类的方法里

但换个角度看,它其实没有那么神秘 对初学者来说,Mixin 最重要的不是高级技巧,而是先搞清楚下面三件事:

  1. 你要改哪个类
  2. 你要改哪个方法
  3. 你要把代码插到哪里

只要这三件事清楚了,Mixin 的基础用法就已经掌握了一大半


快速理解 Mixin#

可以先把 Mixin 理解成一句话:

找到目标类,找到目标方法,选择注入点,把你的代码放进去

它最大的价值是:
当你没有办法优雅地继承或覆盖 Minecraft 原版代码时,你仍然可以在指定位置插入自己的逻辑

这也是为什么它在 Fabric、Sponge 以及很多 Minecraft 模组开发场景里都非常常见


Mixin 能做什么#

Mixin 常见用途包括:

  • 在方法开头插入逻辑
  • 在方法结束后追加逻辑
  • 在返回前修改返回值
  • 读取或修改目标类里的字段
  • 拦截某次特定的方法调用
  • 在某些条件下取消原方法继续执行

如果你只是刚入门,其实先掌握前三种就已经够用了

(Mixin 同时也适用于其它 mod,比如 sodium extra )


先记住三个核心概念#

1. 目标类#

目标类就是你要修改的那个类 比如某个实体类、某个屏幕类、某个方块类,或者原版里的世界逻辑类

2. 目标方法#

目标方法就是你真正想插逻辑的方法 比如 tickrenderinteractcanUse 这类方法

3. 注入点#

注入点决定你的代码在方法中的哪个位置执行 是方法刚开始执行时,还是执行结束后,还是在返回前,又或者是在某次具体调用附近


最常见的几个注解#

注解作用可以怎么理解
@Mixin声明要修改哪个目标类我要改谁
@Inject把方法注入到目标方法里我要插代码
@At指定注入位置插在哪里
@Shadow引用目标类已有成员借用原版字段或方法
@Unique给 Mixin 添加自己的成员这是我自己的变量
@Redirect重定向某个具体调用把某一步换掉
@ModifyArg修改一次调用的参数改传进去的值
@ModifyVariable修改局部变量改中间过程的值

对新手来说,最先要会的是:

  • @Mixin
  • @Inject
  • @At
  • CallbackInfo

先把这几个吃透,比一开始就学高级写法更重要


最小可用示例#

先看一个最基础、最典型的例子

下面这段代码表示:
给目标类的 tick 方法做一个头部注入,也就是目标方法一开始执行,你的逻辑就先运行

@Mixin(TargetClass.class)
public class TargetClassMixin {
@Inject(method = "tick", at = @At("HEAD"))
private void onTick(CallbackInfo ci) {
// 这里写你的逻辑
}
}

这段代码可以拆成四部分来理解:

  1. @Mixin(TargetClass.class):说明你想修改 TargetClass
  2. method = "tick":说明你要改的方法是 tick
  3. @At("HEAD"):说明你要插在方法开头
  4. CallbackInfo ci:这是当前注入过程的上下文对象

如果你第一次写 Mixin,建议先从这种最简单的 HEAD 注入开始


常见注入点#

@At("HEAD")#

表示在方法刚开始执行时注入

适合用来做:

  • 日志输出
  • 预处理
  • 条件判断
  • 提前取消原逻辑

@At("TAIL")#

表示在方法主体执行完成后再注入

适合用来做:

  • 收尾逻辑
  • 追加效果
  • 在原逻辑后再补充处理

@At("RETURN")#

表示在方法即将返回之前注入

适合用来做:

  • 观察返回值
  • 修改返回值

@At(value = "INVOKE", target = "...")#

表示注入到某次具体的方法调用附近

这类写法更精确,但也更脆弱 Minecraft 内部实现一改,注入点就可能失效

如果你是新手,优先学会 HEADTAILRETURN 等你已经能稳定读懂目标方法的执行流程,再去碰 INVOKEFIELDRedirect 这类精细写法


如何取消原方法执行#

如果你希望某个方法不要继续往下运行,就需要使用 cancellable = true

例如:

@Inject(method = "canUse", at = @At("HEAD"), cancellable = true)
private void beforeCanUse(CallbackInfoReturnable<Boolean> cir) {
boolean forceResult = true;
if (forceResult) {
cir.setReturnValue(true);
}
}

这里要注意两点:

1. 有返回值的方法要用 CallbackInfoReturnable<T>#

因为 canUse 这类方法会返回结果,所以这里不能再用普通的 CallbackInfo

2. setReturnValue 通常就足够了#

调用 setReturnValue(true) 后,Mixin 通常会直接把返回值设好,并阻止后续原逻辑继续执行

如果目标方法没有返回值,就使用普通的 CallbackInfo,并在合适的时候调用 ci.cancel()


如何访问目标类里的字段和方法#

很多时候你不只是想插一段代码,你还想读取目标类里面已有的字段,或者调用它内部的方法

这时最常见的工具就是 @Shadow

@Mixin(TargetClass.class)
public abstract class TargetClassMixin {
@Shadow
private int cooldown;
@Unique
private boolean mymod$logged;
}

这里的意思是:

  • @Shadow private int cooldown; 表示这个字段不是新建的,而是目标类本来就有
  • @Unique private boolean mymod$logged; 表示这是你这个 Mixin 自己新增的字段

实践里经常会给 @Unique 成员加上类似 mymod$ 的前缀,这样更不容易和目标类冲突


Mixin 配置文件长什么样#

Mixin 不只有 Java 类,还需要一个配置文件来告诉框架要加载哪些 Mixin

最基础的配置通常像这样:

{
"required": true,
"package": "com.example.mymod.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"TargetClassMixin"
],
"client": [],
"injectors": {
"defaultRequire": 1
}
}

几个关键字段可以这样理解:

  • package:你的 Mixin 类所在包路径
  • mixins:通用 Mixin 列表
  • client:仅客户端使用的 Mixin
  • injectors.defaultRequire:默认要求至少命中多少个注入点

至于这个文件怎么注册进工程,要看你用的加载器
以 Fabric 为例,通常会在 fabric.mod.json 里声明 Mixin 配置文件


新手最容易踩的坑#

方法签名不匹配#

有些方法存在重载
如果你只写方法名,Mixin 可能找不到你真正想注入的那个版本

注入方法参数写错#

你写的注入方法参数必须和目标方法环境匹配,包括:

  • 是否是实例方法或静态方法
  • 原方法参数列表
  • CallbackInfoCallbackInfoReturnable

注入点过于脆弱#

INVOKEFIELD 这种精确定位很强,但 Minecraft 版本一变,目标代码结构可能就不一样了

客户端和服务端类混用#

客户端专用类不要随便写进通用 Mixin,否则很容易在服务端环境崩溃

映射变化#

开发环境里的方法名通常比较可读,但升级版本时,映射和方法签名都可能变化


调试建议#

Mixin 出问题时,不要一上来就怀疑所有东西

更有效的排查顺序是:

  1. 配置文件有没有被正确加载
  2. 目标类是不是你以为的那个类
  3. 方法名和描述符是否正确
  4. 注入点是否真的命中
  5. 注入进去的代码本身是否抛错

一个很实用的策略是:

先写一个最简单的 @At("HEAD") 注入,只输出一条日志 确认这个最小版本生效以后,再逐步增加复杂度

这样调试会轻松很多


推荐学习顺序#

如果你刚开始学,建议按这个顺序来:

  1. @Mixin
  2. @Inject
  3. @At("HEAD")
  4. TAILRETURN
  5. CallbackInfoReturnable
  6. @Shadow
  7. @Unique
  8. @Redirect@ModifyArg@ModifyVariable

这个顺序的好处是:
你会先掌握最稳定、最常用、最容易成功的写法,而不是一开始就陷进复杂注入点里


一句话总结#

Mixin 的基础并不在于“记住多少注解”,而在于你能不能稳定回答下面三个问题:

我要改谁?我要改哪个方法?我要把代码插在哪里?

把这三件事想明白,Minecraft 模组开发里绝大多数基础 Mixin 场景,你就已经能处理了

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Mixin基础教程
https://mizuki-aru.pages.dev/posts/mixin-basic-tutorial/
作者
ANError
发布于
2026-05-27
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00