主题
06 重复种植与变异
先让一块地能反复种(还原状态 + parent 的特性),再给果实加上变异——偶尔结出变异的。
你将做出什么
两件事:一块地能反复种(种完还原、还能再种),以及偶尔结出一颗变异果实(带特效、分数翻倍)。

1. 先让田地能反复种:现在它是"一次性"的
第 03 课结尾留了个问题:结果实之后 plant:Destroy() 把种子销毁了,所以一块地只能种一次。
要能反复种,就得改成"用完还原":
text
现在是: 种子 → 结果实 → 销毁种子 (一次性)
要改成: 种子 → 结果实 → 种子复位, 互动还回去 → 又能种2. 先弄清一个特性:parent = nil
第 02 课就是这样防重复种的:
lua
plot:SetAttribute("种植互动", interact) -- 先把它存起来
interact.Parent = nil -- 再把它从地块上"摘下来"Parent = nil 是什么意思? 物件从场景树上被摘下来了——它不在场景里了(不会显示、不会响应),但它还在内存里、你手里还捏着它的引用。所以之后还能把它装回去:
lua
picked.Parent = plot -- 装回地块下 → 互动按钮又出现了记住这个用法:
Parent = nil是"收起来",不是"删掉"。想彻底不要了才用:Destroy()。
父子关系与查找的完整讲法:专题「找到场景对象并管理父子关系」
两种"用完怎么办":销毁 vs 还原
上一课的结果实结尾是销毁:
lua
plant:Destroy() -- 种子没了, 地也就不能再种了那是当时的选择:先把"一颗种子长出一颗果实"跑通。代价是这块地只能用一次。
要想反复种,就得把"销毁"换成"还原"——把用过的种子恢复成没种过的样子。两件事的差别就一句话:
| 做法 | 种子 | 互动按钮 | 结果 |
|---|---|---|---|
| 销毁 | 没了 | 不还 | 一块地只能种一次 |
| 还原 | 复位(缩回原大、回地底) | 装回去 | 一块地能反复种 |
3. 改 PlantGrow 的收尾:还原而不是销毁
- 文件:
server/main.lua操作:改spawnFruit的收尾(其余不动)
lua
local function spawnFruit(plant, plot) -- 参数顺序和第 03 课一致
-- ① 用预设创建果实(第 03 课学的)
local fruit = World:CreateAsset(FRUIT_PRESET)
fruit[1].Position = plant.Position
fruit[1].OnLiftedBegin:Connect(function(liftunit)
fruit[1]:SetAttribute("持有者", liftunit)
print("[农场][server] 果实被拿起:", liftunit)
end)
fruit[1].OnLiftedEnd:Connect(function()
fruit[1]:SetAttribute("持有者", nil)
end)
-- ② 本课改动: 不再销毁, 而是把这块地还原成"能再种"
local picked = plot:GetAttribute("种植互动")
if picked then picked.Parent = plot end -- 互动装回去(parent = nil 的逆操作)
plant.Size = Vector3.New(0.5, 1, 0.5) -- 种子缩回原大小
plant.Position = plant.Position + Vector3.New(0, -1, 0) -- 回到地底
plot:SetAttribute("stage", "empty") -- 记一笔: 空地
print("[农场][server] 果实长出来了 · 这块地可以再种")
end(第 03 课的收尾原来是一行 plant:Destroy(),本课把它换掉——函数的参数和调用位置都不变。)
还原一共四步,正好把第 02 课摘掉的东西一件件放回去:
| 要还原的 | 怎么还原 |
|---|---|
| 互动按钮 | 从属性里取回来,Parent 装回地块 |
| 种子大小 | Size 改回 0.5, 1, 0.5 |
| 种子位置 | 往下移 1 格,回到地底 |
| 地块状态 | 属性写成 "empty" |
4. 每次都一样,有点无聊:给它加个概率
现在每颗果实都长一个样,而且每颗都一样值分——太稳了,没什么惊喜。
先加意外:偶尔结出不一样的果实。数值照旧进配置表:
- 文件:
common/config.lua(新建) 操作:写入并保存
lua
-- common/config.lua —— 全课程的数值都在这儿改
return {
GROW_TIME = 3, -- 多久后结果实(第 03 课用的)
MUTATE_RATE = 5, -- 突变率(百分比): 每 100 颗大约出 5 颗特殊果实
MUTATE_MULT = 3, -- 特殊果实的分数倍率
}服务端顶部加一行:local CFG = require("common.config"),然后在结果实的地方掷一次骰子:
配置与数据组织:专题「数据 · 配置 · 资产」
lua
-- 掷一次骰子: 中了才给它加身特效
local lucky = math.random(1, 100) <= CFG.MUTATE_RATE骰子必须在服务端掷。 客户端掷的话,每个人看到的都不一样,算分时谁也说不清。
5. 中了之后,给果实加点效果
效果不一定要换模型——可以给它挂一个特效。先到特效预设里挑一个看着好看的,用它的预设 id 来创建:
lua
local effect = World:CreateAsset("official://preset/6158") -- 特效预设的 id(挑一个你喜欢的)
effect[1].Parent = fruit[1] -- 挂在果实身上
effect[1].Scale = Vector3.New(3, 3, 3) -- 放大一点, 更醒目
特效的特性:挂在谁身上,就跟着谁的位置。 所以把它挂到果实下(
Parent = fruit[1]),果实掉到哪、被搬到哪,特效都跟着走——不需要每帧去同步位置。
特效与声音:专题「声音与特效」
把上面的骰子和特效接进 spawnFruit:
lua
if lucky then
fruit[1]:SetAttribute("变异", true) -- 记住它是特殊的
local fx = World:CreateAsset("official://preset/6158")
fx[1].Parent = fruit[1]
fx[1].Scale = Vector3.New(3, 3, 3)
print("[农场][server] 变异果实!")
end变化的办法不止一种:除了挂特效,还能改它的大小(
Scale)、换个颜色、或者换一套模型——只要看得出来不一样都行。想给更多惊喜,可以准备几种,随机挑一个。
第 05 课尚未给果实挂变异特效。本课把创建特效的代码放进
if lucky then … end,使它只在掷骰命中时出现。想让它每次都出现,可以把MUTATE_RATE临时调成 100。
6. 结算时按标记翻倍
回到第 05 课的放置区物件脚本,先在顶部加入 local CFG = require("common.config"),再把原来的固定加分改为按标记结算(分数仍记在玩家属性上):
lua
local gain = SCORE_PER_FRUIT
if otherUnit:GetAttribute("变异") then
gain = gain * CFG.MUTATE_MULT -- 变异果实: 分数翻三倍
end
local score = (player:GetAttribute("score") or 0) + gain
player:SetAttribute("score", score) -- 分数记在玩家身上
RemoteEvent.sell:FireClient(player, { score = gain }) -- 飘字显示"这次涨了多少"text
结果实时掷骰 → 中了就挂特效 + 打"变异"标记 → 搬进放置区 → 按标记翻倍结算为什么标记打在果实身上? 因为它描述的是这一颗果实——特效跟着它、分数也按它算;果实被收走,标记自然一起消失。这就是第 05 课那句判据:这份数据的生命周期跟谁走。
运行并核对
- 把
MUTATE_RATE临时改成 50,种几株 → 频繁出现带特效的果实;改回 5。 - 带特效的果实搬进放置区 → 分数跳一大截(普通 3 分,变异 9 分)。
- 掷骰命中的那一刻,日志里出现
[农场][server] 变异果实!。
现象 → 可能原因:
- 概率改了没变化 → 改的是不是
common/config.lua;改完同步了吗 - 变异搬进去分数没翻倍 → 果实的
变异标记有没有打上;结算那行有没有读它 - 特效不跟着果实走 → 特效的
Parent有没有挂到果实上
拓展点 / 自己改一处
- 加第二档稀有度:1% 出"彩虹"(另一个特效 + 更大的倍率)
- 还原那四步里,给"种子回地底"加个 0.2 秒的小动画(提示:
TweenService) - 想想:如果忘了把互动装回去,这块地会怎样?(这正是模块一那句"
Parent = nil是收起来,不是删掉"的意义)
保存进度
- 下一步:正式内容到这里就结束了。想继续练手,看 07 拓展与回顾——里面有天气和一整片田两个可选练习。
- 通过标准:还原四步到位、可反复种;变异判定在服务端;结算按标记翻倍。
- 恢复兜底:互动被摘坏了就从属性里拖回地块下;数值改乱就把
common/config.lua恢复成课文里的版本。
API:Unit、AssetService、World。
