12.4 模拟经营游戏


文档摘要

12.4 模拟经营游戏 十二、实战项目:模拟经营游戏开发 12.4 模拟经营游戏章节 模拟经营游戏是一种非常受欢迎的游戏类型,它允许玩家扮演管理者或经营者的角色,在一个虚拟世界中建立、发展和管理各种事物,例如城市、农场、公司、主题公园等等。这类游戏通常强调策略、规划、资源管理和长期发展,能够带给玩家成就感和沉浸式的游戏体验。 本章节将深入探讨如何在Unity3D引擎中开发一款基础的模拟经营游戏。我们将从游戏的核心机制入手,逐步讲解资源管理、建筑系统、生产系统、以及简单的用户界面设计。通过代码实践和详细的解释,帮助您掌握模拟经营游戏开发的关键技术和思路。 12.4.1 模拟经营游戏的核心机制 模拟经营游戏的核心乐趣在于玩家通过自己的决策和操作,逐步扩大经营规模,提升效率,最终达成游戏目标。

12.4 模拟经营游戏

十二、实战项目:模拟经营游戏开发

12.4 模拟经营游戏章节

模拟经营游戏是一种非常受欢迎的游戏类型,它允许玩家扮演管理者或经营者的角色,在一个虚拟世界中建立、发展和管理各种事物,例如城市、农场、公司、主题公园等等。这类游戏通常强调策略、规划、资源管理和长期发展,能够带给玩家成就感和沉浸式的游戏体验。

本章节将深入探讨如何在Unity3D引擎中开发一款基础的模拟经营游戏。我们将从游戏的核心机制入手,逐步讲解资源管理、建筑系统、生产系统、以及简单的用户界面设计。通过代码实践和详细的解释,帮助您掌握模拟经营游戏开发的关键技术和思路。

12.4.1 模拟经营游戏的核心机制

模拟经营游戏的核心乐趣在于玩家通过自己的决策和操作,逐步扩大经营规模,提升效率,最终达成游戏目标。为了实现这一目标,通常需要以下核心机制:

  • 资源管理: 这是模拟经营游戏的基础。玩家需要收集、生产、消耗和交易各种资源,例如金钱、原材料、能源、人力等等。合理的资源管理是游戏成功的关键。

  • 建筑系统: 玩家可以在游戏世界中建造各种建筑,例如房屋、工厂、商店、基础设施等等。不同的建筑具有不同的功能,例如生产资源、提供服务、提升人口等等。

  • 生产系统: 建筑可以进行生产活动,将原材料转化为产品或服务。生产过程通常需要消耗资源和时间,并产生新的资源或价值。

  • 经济系统: 游戏世界中通常会存在一个简单的经济系统,资源和产品的价格会受到供需关系的影响。玩家可以通过买卖资源和产品来获取利润。

  • 目标与挑战: 游戏需要设定明确的目标和挑战,引导玩家进行游戏。例如,发展城市人口、提升公司利润、完成特定的任务等等。

这些核心机制相互关联,共同构建了模拟经营游戏的游戏循环。玩家需要不断地做出决策,平衡各种资源,才能有效地发展自己的经营帝国。

12.4.2 项目准备与场景搭建

首先,我们需要创建一个新的Unity3D项目,并进行一些基础的场景搭建。

  1. 创建Unity项目: 打开Unity Hub,创建一个新的3D项目,命名为 "SimulationGame"。

  2. 导入资源: 为了简化开发流程,我们可以使用Unity Asset Store中的一些免费资源包,例如:

    • Standard Assets: 包含一些常用的脚本、模型、材质等。

    • ProBuilder: 用于快速创建简单的3D模型。

    • TextMeshPro: 用于创建高质量的文本显示。

    将这些资源包导入到项目中。

  3. 创建场景: 在 "Scenes" 文件夹下创建一个新的场景,命名为 "MainScene"。

  4. 场景基础设置:

    • 在场景中创建一个 Plane 对象作为地面。调整其Scale属性,使其足够大,例如 (10, 1, 10)。

    • 创建一个 Directional Light 对象作为主光源。调整其位置和旋转,使场景光照效果良好。

    • 创建一个 Camera 对象作为主摄像机。调整其位置和角度,使其能够俯瞰整个场景。

    你可以根据自己的喜好调整场景的颜色和风格。例如,你可以为地面Plane添加一个绿色的材质,模拟草地效果。

12.4.3 资源管理系统

资源管理是模拟经营游戏的核心。我们需要创建一个资源管理系统来跟踪和管理游戏中的各种资源。

代码实践:ResourceManager.cs

创建一个新的C#脚本,命名为 "ResourceManager.cs",并将其添加到场景中的一个空GameObject上(例如,创建一个名为 "GameManager" 的空GameObject)。

using System.Collections.Generic; using UnityEngine; public class ResourceManager : MonoBehaviour { // 使用字典存储资源,键为资源名称,值为资源数量 private Dictionary<string, float> resources = new Dictionary<string, float>(); // 静态实例,方便全局访问 public static ResourceManager Instance { get; private set; } private void Awake() { if (Instance == null) { Instance = this; } else { Destroy(gameObject); // 确保只有一个ResourceManager实例 } } // 初始化资源 public void InitializeResource(string resourceName, float initialAmount) { resources.Add(resourceName, initialAmount); Debug.Log($"初始化资源 {resourceName}: {initialAmount}"); } // 获取资源数量 public float GetResource(string resourceName) { if (resources.ContainsKey(resourceName)) { return resources[resourceName]; } else { Debug.LogError($"资源 {resourceName} 不存在!"); return 0f; // 返回0,并输出错误信息 } } // 增加资源 public void AddResource(string resourceName, float amount) { if (resources.ContainsKey(resourceName)) { resources[resourceName] += amount; Debug.Log($"增加资源 {resourceName}: {amount},当前数量: {resources[resourceName]}"); } else { Debug.LogError($"资源 {resourceName} 不存在!"); } } // 消耗资源 public bool ConsumeResource(string resourceName, float amount) { if (resources.ContainsKey(resourceName)) { if (resources[resourceName] >= amount) { resources[resourceName] -= amount; Debug.Log($"消耗资源 {resourceName}: {amount},当前数量: {resources[resourceName]}"); return true; // 消耗成功 } else { Debug.LogWarning($"资源 {resourceName} 不足,无法消耗 {amount},当前数量: {resources[resourceName]}"); return false; // 资源不足,消耗失败 } } else { Debug.LogError($"资源 {resourceName} 不存在!"); return false; // 资源不存在,消耗失败 } } }

代码详解:

  • Dictionary<string, float> resources: 使用字典来存储资源,键为资源名称 (string),值为资源数量 (float)。使用字典可以方便地通过资源名称来访问和管理资源。

  • static ResourceManager Instance: 使用单例模式,确保在整个游戏中只有一个 ResourceManager 实例,方便全局访问资源管理系统。

  • InitializeResource(string resourceName, float initialAmount): 初始化资源,添加新的资源类型并设置初始数量。

  • GetResource(string resourceName): 获取指定资源名称的资源数量。

  • AddResource(string resourceName, float amount): 增加指定资源的数量。

  • ConsumeResource(string resourceName, float amount): 消耗指定资源的数量。如果资源不足,则消耗失败并返回 false

使用ResourceManager:

在其他脚本中,可以通过 ResourceManager.Instance 来访问资源管理系统。例如,在游戏开始时初始化资源:

public class GameManager : MonoBehaviour { void Start() { ResourceManager.Instance.InitializeResource("Gold", 1000f); // 初始化金币 ResourceManager.Instance.InitializeResource("Wood", 500f); // 初始化木材 } void Update() { if (Input.GetKeyDown(KeyCode.Space)) // 按下空格键消耗金币 { if (ResourceManager.Instance.ConsumeResource("Gold", 100f)) { Debug.Log("成功消耗100金币!"); } else { Debug.Log("金币不足,无法消耗!"); } } if (Input.GetKeyDown(KeyCode.G)) // 按下G键获取当前金币数量 { Debug.Log($"当前金币数量: {ResourceManager.Instance.GetResource("Gold")}"); } } }

将上述代码添加到场景中的 "GameManager" GameObject上。运行游戏,按下空格键和G键,观察控制台输出,测试资源管理系统。

12.4.4 建筑系统

建筑系统是模拟经营游戏的核心组成部分。我们需要创建一个建筑系统,允许玩家在游戏世界中建造各种建筑。

代码实践:BuildingManager.cs 和 Building.cs

创建两个新的C#脚本,分别命名为 "BuildingManager.cs" 和 "Building.cs"。

Building.cs: 定义建筑的基本属性。

using UnityEngine; public class Building : MonoBehaviour { public string buildingName; // 建筑名称 public float costGold; // 建造所需金币 public float costWood; // 建造所需木材 public GameObject prefab; // 建筑Prefab // 可以添加更多建筑属性,例如生产效率、人口容量等 }

BuildingManager.cs: 管理建筑的建造和放置逻辑。

using UnityEngine; public class BuildingManager : MonoBehaviour { public Building[] buildingPrefabs; // 可建造的建筑Prefab数组 public Transform buildingsParent; // 建筑物的父物体,用于组织场景 private Building selectedBuildingPrefab; // 当前选中的建筑Prefab private GameObject previewBuilding; // 预览建筑GameObject // 静态实例 public static BuildingManager Instance { get; private set; } private void Awake() { if (Instance == null) { Instance = this; } else { Destroy(gameObject); } } void Update() { if (selectedBuildingPrefab != null) { // 预览建筑跟随鼠标位置 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // 将预览建筑放置在射线击中的地面位置 Vector3 placementPosition = hit.point; placementPosition.y = 0.1f; // 稍微抬高,避免与地面Z-fighting previewBuilding.transform.position = placementPosition; // 检测鼠标左键点击,进行建造 if (Input.GetMouseButtonDown(0)) { BuildBuilding(); } } } } // 选择建筑Prefab public void SelectBuildingPrefab(int index) { if (index >= 0 && index < buildingPrefabs.Length) { selectedBuildingPrefab = buildingPrefabs[index]; CreatePreviewBuilding(); // 创建预览建筑 } else { Debug.LogError("建筑Prefab索引超出范围!"); } } // 创建预览建筑 private void CreatePreviewBuilding() { if (selectedBuildingPrefab != null) { previewBuilding = Instantiate(selectedBuildingPrefab.prefab); // 可以为预览建筑添加半透明材质,表示预览状态 Renderer[] renderers = previewBuilding.GetComponentsInChildren<Renderer>(); foreach (Renderer renderer in renderers) { Material[] materials = renderer.materials; for (int i = 0; i < materials.Length; i++) { materials[i].color = new Color(materials[i].color.r, materials[i].color.g, materials[i].color.b, 0.5f); // 设置Alpha通道为0.5,半透明 } renderer.materials = materials; } } } // 建造建筑 private void BuildBuilding() { if (selectedBuildingPrefab != null && previewBuilding != null) { // 检查资源是否足够 if (ResourceManager.Instance.ConsumeResource("Gold", selectedBuildingPrefab.costGold) && ResourceManager.Instance.ConsumeResource("Wood", selectedBuildingPrefab.costWood)) { // 资源足够,正式建造 GameObject newBuilding = Instantiate(selectedBuildingPrefab.prefab, previewBuilding.transform.position, Quaternion.identity, buildingsParent); Destroy(previewBuilding); // 销毁预览建筑 previewBuilding = null; selectedBuildingPrefab = null; Debug.Log($"成功建造 {selectedBuildingPrefab.buildingName}!"); } else { Debug.LogWarning($"资源不足,无法建造 {selectedBuildingPrefab.buildingName}!"); // 可以添加UI提示,告知玩家资源不足 } } } // 取消建造模式 public void CancelBuildingMode() { selectedBuildingPrefab = null; if (previewBuilding != null) { Destroy(previewBuilding); previewBuilding = null; } } }

代码详解:

  • Building.cs:

    • buildingName, costGold, costWood, prefab: 定义了建筑的基本属性,包括名称、建造所需资源和Prefab。
  • BuildingManager.cs:

    • buildingPrefabs: 存储可建造的建筑Prefab数组。在Unity编辑器中,你需要将预先创建好的建筑Prefab拖拽到这个数组中。

    • buildingsParent: 指定所有建造出来的建筑物的父物体,用于在场景中组织建筑。

    • selectedBuildingPrefab: 当前选中的建筑Prefab,用于预览和建造。

    • previewBuilding: 预览建筑的GameObject,在建造前显示建筑的放置位置。

    • Update(): 在每一帧中检测鼠标位置,更新预览建筑的位置,并检测鼠标左键点击进行建造。

    • SelectBuildingPrefab(int index): 选择指定索引的建筑Prefab,创建预览建筑。

    • CreatePreviewBuilding(): 创建预览建筑,使用Instantiate实例化选中的Prefab,并将其材质设置为半透明,表示预览状态。

    • BuildBuilding(): 进行建造操作。首先检查资源是否足够,如果足够,则正式实例化建筑,消耗资源,销毁预览建筑,并清除选中状态。

    • CancelBuildingMode(): 取消建造模式,清除选中状态和预览建筑。

使用BuildingManager:

  1. 创建建筑Prefab: 在Unity编辑器中,创建几个简单的3D模型作为建筑Prefab,例如立方体、圆柱体等。为每个Prefab添加一个 Building.cs 脚本,并设置 buildingName, costGold, costWoodprefab 属性。

  2. 配置BuildingManager:BuildingManager.cs 脚本添加到 "GameManager" GameObject上。在Inspector面板中,将创建好的建筑Prefab拖拽到 Building Prefabs 数组中。创建一个空的GameObject作为 Buildings Parent,并将其拖拽到 Buildings Parent 属性中。

  3. 创建UI按钮: 创建一个简单的UI系统,例如使用Unity UI的Button组件,为每个建筑Prefab创建一个按钮。在按钮的OnClick事件中,调用 BuildingManager.Instance.SelectBuildingPrefab(index),传入建筑Prefab在数组中的索引。

示例UI按钮代码:

public class UIButtonBuilding : MonoBehaviour { public int buildingIndex; // 建筑Prefab索引 public void OnButtonClick() { BuildingManager.Instance.SelectBuildingPrefab(buildingIndex); } }

将此脚本添加到每个UI按钮上,并设置 buildingIndex 属性为对应的建筑Prefab索引。

运行游戏,点击UI按钮,选择建筑,然后在场景中点击鼠标左键进行建造。

12.4.5 生产系统 (简易)

为了使游戏更具互动性,我们可以添加一个简单的生产系统。例如,建造 "伐木场" 可以生产 "木材" 资源。

修改 Building.cs:

Building.cs 中添加生产相关的属性和方法。

using UnityEngine; public class Building : MonoBehaviour { public string buildingName; public float costGold; public float costWood; public GameObject prefab; public bool isProducer = false; // 是否是生产者建筑 public string producedResourceName; // 生产的资源名称 public float productionRate = 1f; // 生产速率 (每秒生产多少资源) private float productionTimer = 0f; // 生产计时器 void Update() { if (isProducer) { productionTimer += Time.deltaTime; if (productionTimer >= 1f) // 每秒生产一次 { productionTimer = 0f; ProduceResource(); } } } // 生产资源 private void ProduceResource() { ResourceManager.Instance.AddResource(producedResourceName, productionRate); Debug.Log($"{buildingName} 生产了 {productionRate} {producedResourceName}"); } }

代码详解:

  • isProducer: 标记建筑是否是生产者。

  • producedResourceName: 生产者建筑生产的资源名称。

  • productionRate: 生产速率,每秒生产多少资源。

  • productionTimer: 生产计时器,用于控制生产频率。

  • Update(): 如果建筑是生产者,则每秒调用 ProduceResource() 方法。

  • ProduceResource(): 调用 ResourceManager.Instance.AddResource() 方法,增加生产的资源。

配置建筑Prefab:

在Unity编辑器中,选择 "伐木场" 建筑Prefab,勾选 Is Producer 属性,设置 Produced Resource Name 为 "Wood",Production Rate 为 2。

运行游戏,建造 "伐木场",观察控制台输出,可以看到 "伐木场" 每秒生产2个 "木材" 资源。

12.4.6 简单的用户界面 (UI)

为了更好地展示游戏信息和操作,我们需要创建一个简单的用户界面。

  1. 创建Canvas: 在场景中创建一个 Canvas 对象。将 Render Mode 设置为 "Screen Space - Overlay"。

  2. 创建资源显示UI: 在 Canvas 下创建两个 TextMeshProUGUI 组件,分别用于显示 "金币" 和 "木材" 资源数量。

  3. 创建建筑按钮UI: 在 Canvas 下创建多个 Button 组件,每个按钮对应一个可建造的建筑Prefab。

代码实践:UIManager.cs

创建一个新的C#脚本,命名为 "UIManager.cs",用于管理UI显示。

using UnityEngine; using TMPro; public class UIManager : MonoBehaviour { public TextMeshProUGUI goldText; // 金币文本 public TextMeshProUGUI woodText; // 木材文本 // 静态实例 public static UIManager Instance { get; private set; } private void Awake() { if (Instance == null) { Instance = this; } else { Destroy(gameObject); } } void Update() { // 每帧更新资源显示 UpdateResourceUI(); } // 更新资源UI显示 private void UpdateResourceUI() { if (goldText != null) { goldText.text = $"金币: {ResourceManager.Instance.GetResource("Gold")}"; } if (woodText != null) { woodText.text = $"木材: {ResourceManager.Instance.GetResource("Wood")}"; } } }

代码详解:

  • goldText, woodText: TextMeshProUGUI 组件,用于显示金币和木材数量。在Unity编辑器中,将UI文本组件拖拽到这些属性中。

  • UpdateResourceUI(): 每帧更新UI文本显示,从 ResourceManager.Instance 获取资源数量并更新UI文本。

配置UIManager:

  1. UIManager.cs 脚本添加到 "GameManager" GameObject上。

  2. 在Inspector面板中,将创建好的UI文本组件拖拽到 Gold TextWood Text 属性中。

运行游戏,可以看到UI界面显示了金币和木材的数量,并且数量会随着游戏进程实时更新。

12.4.7 游戏循环与扩展方向

至此,我们已经完成了一个基础的模拟经营游戏框架,包括资源管理、建筑系统、简易生产系统和基本UI。

游戏循环流程图 (mermaid graph TD):

扩展方向:

  • 更复杂的资源类型和生产链: 增加更多种类的资源,例如食物、电力、人口、科技点等等,构建更复杂的生产链和经济系统。

  • 更丰富的建筑类型和功能: 添加更多不同功能的建筑,例如住宅、商店、工厂、科技建筑、防御建筑等等。

  • 人口管理系统: 引入人口概念,管理人口的增长、幸福度、需求等等。

  • 科技研发系统: 允许玩家研发科技,解锁新的建筑、升级和功能。

  • 任务系统和目标: 添加任务和目标,引导玩家进行游戏,增加游戏乐趣和挑战性。

  • 更精美的画面和音效: 优化游戏画面,添加音效和背景音乐,提升游戏体验。

  • AI系统: 引入AI对手或NPC角色,增加游戏的复杂性和挑战性。

  • 存档和读档功能: 允许玩家保存和加载游戏进度。

总结

本章节我们从零开始,使用Unity3D引擎,一步步构建了一个基础的模拟经营游戏框架。我们学习了如何创建资源管理系统、建筑系统、简易生产系统和基本UI。通过代码实践和详细的解释,相信您已经对模拟经营游戏的开发有了更深入的理解。

模拟经营游戏的开发是一个充满挑战和乐趣的过程。希望本章节的内容能够帮助您入门,并激发您进一步探索和创造更精彩的模拟经营游戏作品!

请记住,这只是一个基础框架,真正的模拟经营游戏开发需要投入更多的时间和精力进行完善和扩展。继续学习和实践,你一定可以创造出令人惊叹的游戏!


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U