验证环境
本页示例已使用 Build 740622 对应的本机 Managed DLL 完成编译检查;尚未在游戏内完成运行验证。
新增物品与食物
物品是最适合入门的实体:它可以掉在地上、被拾取、被储存,也可以继续扩展成食物、材料、装备或带自定义逻辑的特殊道具。
这一章对应 examples/ItemAndFood/ 示例项目。示例里有两个重点:
ItemConfig:普通掉落物。FoodConfig:可以吃的食物。
文件结构
ItemAndFood/
├── ItemAndFood.csproj
├── Mod.cs
├── ItemConfig.cs
├── FoodConfig.cs
├── STRINGS.cs
├── mod.yaml
└── mod_info.yaml示例项目复用了游戏内已有的 squirrel_kanim 动画,因此不需要额外提交动画资源。发布自己的实体时,应把动画和其他资源一起复制到 Mod 输出目录。
推荐的实现顺序
先做普通物品,再扩展成食物:
- 给物品确定唯一 ID 和默认文本。
- 用
CreateLooseEntity()创建能掉落、能拾取的实体。 - 在调试菜单中生成它,确认动画、质量和储存标签正确。
- 再用
ExtendEntityToFood()增加食物数据。 - 最后接入配方和本地化文件。
物品能生成但配方找不到,通常不是实体配置的问题,而是配方中的输入、输出 Tag 没有分别匹配对应实体的 PrefabTag。先把两个问题分开测试。
基础物品
ItemConfig.cs 负责注册普通掉落物。完整可编译示例位于 examples/ItemAndFood/ItemConfig.cs:
using System.Collections.Generic;
using UnityEngine;
namespace ONITutorial.ItemAndFood
{
public sealed class ItemConfig : IEntityConfig
{
public const string ID = "ONITutorialItem";
public GameObject CreatePrefab()
{
GameObject go = EntityTemplates.CreateLooseEntity(
ID,
global::ONITutorial.ItemAndFood.STRINGS.ITEM.NAME,
global::ONITutorial.ItemAndFood.STRINGS.ITEM.DESC,
5f,
true,
Assets.GetAnim("squirrel_kanim"),
"object",
Grid.SceneLayer.Front,
EntityTemplates.CollisionShape.RECTANGLE,
0.6f,
0.6f,
true,
0,
SimHashes.Creature,
new List<Tag> { GameTags.IndustrialIngredient });
return go;
}
public void OnPrefabInit(GameObject inst) { }
public void OnSpawn(GameObject inst) { }
}
}CreateLooseEntity() 里几个参数最容易写错:
ID:全局唯一,后面找预制体、配方、储存过滤都会用它。mass:物品质量,单位是千克。Assets.GetAnim():动画文件名,要带_kanim。"object":动画状态名。掉落物通常用这个。SimHashes.Creature:实体的默认元素。很多非材料类掉落物都会先用它。GameTags.IndustrialIngredient:决定它能被哪些储存、配方或建筑识别。
示例不声明 DLC 限制,因此不实现 GetDlcIds()。如果内容只适用于特定 DLC,应使用当前 DLL 的 IHasDlcRestrictions 接口声明 GetRequiredDlcIds() 或 GetForbiddenDlcIds()。
示例里的 ItemConfig 和 FoodConfig 是两个独立的 IEntityConfig。修改其中一个时,不要忘记同步 STRINGS.cs 和 .csproj 的 <Compile Include>。
自定义组件
如果物品需要额外行为,可以在 CreatePrefab() 中通过 AddOrGet<T>() 添加自定义 KMonoBehaviour。组件应单独放在示例项目中,并针对当前 DLL 编译后再写入教程;本页的最小示例暂不添加额外组件。
Buff 扩展
Buff 注册涉及 Effect、AttributeModifier 和 ModifierSet 的组合。当前示例项目先聚焦于物品和食物实体,不提供未经当前 DLL 编译验证的 Buff 代码;需要添加 Buff 时,应以本机 DLL 的构造函数和 Db.Initialize 生命周期重新建立独立示例。
Mod 入口
Mod 入口和统一的本地化初始化流程见 examples/ItemAndFood/Mod.cs 和本地化示例。如果项目包含自定义 LocString,必须同时完成注册、key 创建和翻译文件加载。
食物物品
FoodConfig.cs 使用 EntityTemplates.ExtendEntityToFood() 把掉落物扩展成食物。完整可编译示例位于 examples/ItemAndFood/FoodConfig.cs:
using System.Collections.Generic;
using UnityEngine;
namespace ONITutorial.ItemAndFood
{
public sealed class FoodConfig : IEntityConfig
{
public const string ID = "ONITutorialFood";
public GameObject CreatePrefab()
{
GameObject go = EntityTemplates.CreateLooseEntity(
ID,
global::ONITutorial.ItemAndFood.STRINGS.FOOD.NAME,
global::ONITutorial.ItemAndFood.STRINGS.FOOD.DESC,
1f,
false,
Assets.GetAnim("squirrel_kanim"),
"object",
Grid.SceneLayer.Front,
EntityTemplates.CollisionShape.RECTANGLE,
0.8f,
0.5f,
true,
0,
SimHashes.Creature,
new List<Tag>());
EdiblesManager.FoodInfo foodInfo = new EdiblesManager.FoodInfo(
ID,
1000f * 1000f,
1,
255.15f,
277.15f,
4800f,
true
);
return EntityTemplates.ExtendEntityToFood(go, foodInfo);
}
public void OnPrefabInit(GameObject inst) { }
public void OnSpawn(GameObject inst) { }
}
}1000f * 1000f 是 1000 千卡。后面的 1 是品质,温度仍然是开尔文。
当前示例使用本机 DLL 中已确认的 FoodInfo 构造函数;旧文章里的 AddEffects() 重载不作为本页示例。
本地化文本
STRINGS.cs 里集中放普通物品和食物文本。完整可编译示例位于 examples/ItemAndFood/STRINGS.cs:
namespace ONITutorial.ItemAndFood
{
public static class STRINGS
{
public static class ITEM
{
public static LocString NAME = "ONI Tutorial Item";
public static LocString DESC = "An item from the tutorial example.";
}
public static class FOOD
{
public static LocString NAME = "ONI Tutorial Food";
public static LocString DESC = "A food from the tutorial example.";
}
}
}如果后续加入 Buff,再把对应的 LocString 放在独立的 DUPLICANTS.MODIFIERS 路径中。
生成测试
进入开发模式后,可以用调试菜单生成 ONITutorialItem 和 ONITutorialFood。如果代码里找不到它,先检查几件事:
IEntityConfig类是不是public。.csproj里有没有把新增.cs文件加进<Compile Include="..." />。ID有没有和别的实体重复。- 动画文件名和动画状态名是不是存在。
能生成食物以后,让复制人吃掉它,再看复制人属性面板里有没有“吃得很开心”这个效果。