今天给大家伙儿唠唠嗑,说说我最近搞的这个“饥饿的克劳舒克”小项目,名字听着挺唬人,就是用Unity整了个简单的生存模拟器。
我是瞅着Asset Store里头有个免费的村庄素材包,觉得场景挺符合我想象中的那种破败、萧条的感觉。然后我就寻思,要不搞个村民因为天灾啥的,闹饥荒,然后玩家得想办法带着大家伙儿活下去的故事?
说干就干,我先是把场景搭起来,房子、树木、小路啥的,一股脑儿拖进去。我就开始琢磨这个“饥饿”的机制。
我新建了一个`Villager`(村民)类,里面加了个`hunger`(饥饿度)变量,初始值设为100。然后,每隔一段时间,`hunger`值就下降,模拟村民消耗体力。这部分我用了`InvokeRepeating`函数,简单粗暴,效果还行。
csharp
public class Villager : MonoBehaviour
public float hunger = 100f;
public float hungerDecreaseRate = 5f; // 每隔多久降低一次饥饿度
public float hungerDecreaseAmount = 1f; // 每次降低多少饥饿度
void Start()
InvokeRepeating("DecreaseHunger", hungerDecreaseRate, hungerDecreaseRate);
void DecreaseHunger()
hunger -= hungerDecreaseAmount;
hunger = *(hunger, 0f, 100f); // 限制饥饿度在0-100之间
if (hunger <= 0)
// 饥饿至死,后续可以添加死亡逻辑
*(* + " 饿死了!");
有了饥饿度,就得有食物来源。我加了个`FoodSource`(食物来源)类,可以理解为村庄附近的野果树、小动物啥的。玩家可以通过采集这些食物来增加村民的饥饿度。
采集食物这块儿,我用了Unity的`OnMouseDown`事件,玩家点击食物来源后,就可以增加村民的`hunger`值。
csharp
public class FoodSource : MonoBehaviour
public float foodAmount = 20f; // 食物量
void OnMouseDown()
// 找到所有村民
Villager[] villagers = FindObjectsOfType
// 随机选择一个村民喂食
if (* > 0)
int randomIndex = *(0, *);
Villager chosenVillager = villagers[randomIndex];
// 喂食
* += foodAmount;
* = *(*, 0f, 100f);
*("给 " + * + " 增加了 " + foodAmount + " 点饥饿度");
// 食物来源减少
foodAmount -= 5f;
foodAmount = *(foodAmount, 0f, 20f);
if(foodAmount <= 0)
//食物吃完
Destroy(gameObject);
光有饥饿和食物还不够,还得有个UI界面来显示村民的饥饿度。我新建了一个简单的Canvas,用`Text`组件来显示`Villager`类中的`hunger`变量。
csharp
using UnityEngine;
using *;
public class HungerUI : MonoBehaviour
public Villager villager;
public Text hungerText;
void Update()
* = "饥饿度: " + *("F1"); // 显示一位小数
把这些组件都挂到对应的GameObject上,跑起来一看,还真有点意思了。村民的饥饿度开始慢慢下降,我点击食物来源,村民的饥饿度又能涨上去。
但是,问题也来了。村民是随机选择的,有时候会重复喂同一个村民,导致有的村民饿死,有的村民撑死。食物来源是无限的,点击一次就能一直喂,这不符合实际情况。
为了解决这些问题,我对代码进行了一些改进。
村民选择机制: 我增加了一个`VillagerManager`(村民管理器)类,用来管理所有的村民。每次喂食的时候,`VillagerManager`会选择饥饿度最低的村民进行喂食。
食物来源限制: 我给`FoodSource`类增加了一个`foodAmount`变量,表示食物的剩余量。每次点击后,`foodAmount`会减少,当`foodAmount`降到0时,食物来源就消失。
csharp
// VillagerManager
public class VillagerManager : MonoBehaviour
public Villager[] villagers;
public Villager GetHungriestVillager()
Villager hungriestVillager = null;
float minHunger = 100f;
foreach (Villager villager in villagers)
if (* < minHunger)
minHunger = *;
hungriestVillager = villager;
return hungriestVillager;
csharp
// FoodSource 修改OnMouseDown
void OnMouseDown()
//找到村民管理器
VillagerManager vm = FindObjectOfType
// 找到饥饿度最低的村民喂食
if (vm != null)
Villager chosenVillager = *();
if (chosenVillager != null)
// 喂食
* += foodAmount;
* = *(*, 0f, 100f);
*("给 " + * + " 增加了 " + foodAmount + " 点饥饿度");
// 食物来源减少
foodAmount -= 5f;
foodAmount = *(foodAmount, 0f, 20f);
if (foodAmount <= 0)
//食物吃完
Destroy(gameObject);
改完之后,效果就好多了。村民不会重复喂食了,食物来源也会逐渐减少。
这个项目还很简单,有很多可以改进的地方。比如:
可以增加更多的食物来源,比如农田、渔场啥的。
可以增加更多的村民行为,比如睡觉、工作啥的。
可以增加更多的事件,比如疾病、战争啥的。
可以加入死亡动画,加入更多美术效果
这回的“饥饿的克劳舒克”小项目,让我对Unity的开发流程有了更深入的了解。虽然还有很多不足之处,但我相信,只要坚持学习,不断实践,就能做出更好的游戏!这回的实践就分享到这儿,下次再见!