新增生物
新增生物是内容扩展里最复杂的一类。它不只是一个会动的实体,还涉及导航、AI、大脑、年龄、繁殖、捕捉、掉落物、动画状态机和牧场系统。
如果这是你第一次写生物,建议不要从零造一个完整生物。更稳的路线是:复制一个原版生物的配置,再逐步改外观、数值和掉落物。这样可以先复用原版已经跑通的 AI 和状态机。
推荐路线
新增生物可以分三步做:
- 先做一个“克隆生物”,能生成、能移动、能保存读取。
- 再改温度、食物、掉落物、繁殖周期等数值。
- 最后再写自定义行为,比如特殊攻击、特殊产物、范围效果。
不要一开始就同时改 AI、动画、繁殖和掉落。生物系统报错时,日志通常很长,拆小一点会好查很多。
文件结构
MyFirstCreature/
├── MyFirstCreatureConfig.cs
├── MyFirstCreaturePatches.cs
├── MyFirstCreature.cs
└── STRINGS.csConfig 负责实体,Patches 负责把它挂进世界生成或调试生成,MyFirstCreature 是你自己的行为组件。
从克隆开始
很多时候不需要手写完整生物模板。可以先在游戏加载后拿到原版预制体,复制一份出来,再改 ID、名称和少量组件。
using HarmonyLib;
using UnityEngine;
namespace MyFirstCreature
{
[HarmonyPatch(typeof(Assets), "OnPrefabInit")]
public static class CreatureClonePatch
{
public static void Postfix()
{
GameObject source = Assets.GetPrefab("Drecko");
if (source == null)
{
Debug.LogError("[MyFirstCreature] Drecko prefab not found");
return;
}
GameObject clone = Object.Instantiate(source);
clone.name = MyFirstCreatureConfig.ID;
KPrefabID prefabId = clone.GetComponent<KPrefabID>();
prefabId.PrefabTag = TagManager.Create(MyFirstCreatureConfig.ID);
clone.AddOrGet<MyFirstCreature>();
Assets.AddPrefab(clone);
}
}
}这种写法适合做原版生物的变体。比如“新的毛鳞壁虎”“新的喷浮飞鱼”,大部分行为沿用原版,只改少量数值。
自定义组件
先把自己的逻辑放进组件里,不要直接塞在 Patch 里:
using UnityEngine;
namespace MyFirstCreature
{
public class MyFirstCreature : KMonoBehaviour
{
protected override void OnSpawn()
{
base.OnSpawn();
Debug.Log("[MyFirstCreature] spawned");
}
}
}等生物能正常生成后,再在这里订阅事件、检查状态、产出物品。
改基础数值
克隆出来以后,可以按需拿组件改数值。比如改选择面板显示、质量或标签:
KSelectable selectable = clone.GetComponent<KSelectable>();
if (selectable != null)
{
selectable.SetName(STRINGS.CREATURES.SPECIES.MYFIRSTCREATURE.NAME);
}
PrimaryElement primary = clone.GetComponent<PrimaryElement>();
if (primary != null)
{
primary.Mass = 100f;
primary.Temperature = 293.15f;
}
KPrefabID prefabId = clone.GetComponent<KPrefabID>();
prefabId.AddTag(GameTags.Creatures.Species, false);这类改动比较安全。涉及 AI 行为树、导航类型、繁殖器时,要先确认原版组件的依赖关系,不要看到组件就直接删。
掉落物和产物
生物掉落通常依赖死亡掉落、排泄、产蛋或特殊状态机。入门时建议先用已有掉落逻辑,不要马上写完整繁殖链。
如果只是周期性产出一个物品,可以写在自己的组件里:
public class MyFirstCreature : KMonoBehaviour, ISim200ms
{
private float timer;
public void Sim200ms(float dt)
{
timer += dt;
if (timer < 600f) return;
timer = 0f;
GameObject prefab = Assets.GetPrefab(MyFirstDropConfig.ID);
if (prefab == null) return;
GameUtil.KInstantiate(prefab, transform.position, Grid.SceneLayer.Ore).SetActive(true);
}
}这不是牧场系统的完整产物链,但很适合先验证“生物能触发自己的逻辑”。
名称和描述
namespace MyFirstCreature
{
public static class STRINGS
{
public static class CREATURES
{
public static class SPECIES
{
public static class MYFIRSTCREATURE
{
public static LocString NAME = "我的第一个生物";
public static LocString DESC = "一个基于原版生物改出来的测试生物。";
}
}
}
}
}生物文本路径比建筑和物品更容易乱。建议先统一放到 CREATURES.SPECIES 下,后面需要蛋、幼体、掉落物时再补子项。
常见问题
生物生成后不动,通常是 Navigator、Brain、ChoreProvider 或状态机依赖坏了。先回退到只改 ID 和名字,确认克隆体能动。
保存读取崩溃,多半是新增组件里有不能序列化的字段,或者 prefab ID/tag 改得不完整。
动画错位或空白,先用原版动画跑通。完全自制生物动画要配好每个状态机需要的动画状态,不然生物会在某个状态突然消失。
完整从零写生物当然可以,但不适合作为第一篇教程。先用克隆路线把链路跑通,再逐步替换系统,成功率会高很多。