RTS游戏关于建筑物放置的测试Demo(Unity)

2023-10-18 16:59

本文主要是介绍RTS游戏关于建筑物放置的测试Demo(Unity),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.准备一个建筑物

1,创建一个立方体Cube,改名为Mesh

2,创建一个空物体,起名叫Building

3,将Mesh放到Building下,将Mesh的BoxCollider组件删除,在Building的组件中新加BoxCollider和Rigidbody组件

4,创建Building.cs,将脚本挂载到Building下

 

 

注意点:因为BoxCollider没有挂载到Mesh上,所以在调整碰撞器大小时,应该调整到和Mesh原来BoxCollider大小位置一样 (使用导入资源如果涉及到旋转等,注意做好调整)

5,在Assets创建Resources文件夹,在Resources文件夹下创建Prefabs文件夹,在Prefabs文件夹下创建Buildings文件夹,将Building拖入保存为预制件

 

二.配置环境

1,创建一个地形Terrain(Layer为第八层,可以自己设置,不过在Globals 里面自己改)

2,创建一个空物体,改名为Game,创建一个BuildingPlacer.cs,将脚本挂载到Game上

3,在Resources文件夹下创建Materials文件夹,然后创建2个Material,将名字改为下面的,然后将颜色改一下

三.创建建筑物数据和脚本

public class BuildingData
{private string _name;private int _hp;public BuildingData(string name, int hp){_name = name;_hp = hp;}public string Name { get { return _name; } }public int HP { get { return _hp; } }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BuildingPlacer : MonoBehaviour
{//作为建筑放置类,手里必须拿着建筑private Building _building;private Ray _ray;private RaycastHit _raycastHit;//这个点的作用主要就是为了判断是否鼠标发生了移动,这个时候就可以更改值了private Vector3 SavePoint;private void Start(){_prepareBuilding(0);}private void Update(){if (_building != null){//如果按下esc就取消建筑物if (Input.GetKeyDown(KeyCode.Escape)){_cancelBuilding();return;}_ray = Camera.main.ScreenPointToRay(Input.mousePosition);if(Physics.Raycast(_ray,out _raycastHit, 1000f, Globals.TERRAIN_LAYER_MASK)){_building.gameObject.transform.position = _raycastHit.point;//只要一动就检查建筑的状态,随时进行切换if(SavePoint != _raycastHit.point){_building.ChangeState();}SavePoint = _raycastHit.point;if (_building.HasValidPlace && Input.GetMouseButtonDown(0)){_PlaceBuilding();}}}}/// <summary>/// 准备建筑物/// </summary>public void _prepareBuilding(int index){if(_building != null){Destroy(_building.gameObject);}else{GameObject _gameObject = (GameObject)GameObject.Instantiate(Resources.Load($"Prefabs/Buildings/{Globals.buildingDatas[index].Name}"));_building = _gameObject.GetComponent<Building>();_building.setvaults(Globals.buildingDatas[index]);}SavePoint = Vector3.zero;}/// <summary>/// 取消建筑物/// </summary>void _cancelBuilding(){Destroy(_building.gameObject);_building = null;}/// <summary>/// 放置建筑物/// </summary>void _PlaceBuilding(){_building.place();_building = null;_prepareBuilding(0);}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public enum BuildingPlacementState
{VALID,INVALID,FIXED
};[RequireComponent(typeof(BoxCollider))]
public class Building : MonoBehaviour
{private BuildingData _buildingData;private int currentHp;   private BuildingPlacementState _state;private List<Material> _materials;private int _nCollisions = 0;public void setvaults(BuildingData buildingData){this._buildingData = buildingData;this.currentHp = buildingData.HP;}public string Name { get { return _buildingData.Name; } }public int CurrentHp { get { return currentHp; } }public int Hp { get { return _buildingData.HP; } }public int DataIndex{get{for (int i = 0; i < Globals.buildingDatas.Length; i++){if (Globals.buildingDatas[i].Name == _buildingData.Name){return i;}}return -1;}}private void Awake(){_materials = new List<Material>();_state = BuildingPlacementState.VALID;foreach (Material material in gameObject.transform.Find("Mesh").GetComponent<Renderer>().materials){_materials.Add(new Material(material));}SetMaterials(_state);}/// <summary>/// 根据状态改变颜色/// </summary>/// <param name="buildingState"></param>public void SetMaterials(BuildingPlacementState buildingState){List<Material> materials;if (buildingState == BuildingPlacementState.VALID){materials = new List<Material>();for (int i = 0; i < _materials.Count; i++){materials.Add(Globals.Valid);}}else if (buildingState == BuildingPlacementState.INVALID){materials = new List<Material>();for (int i = 0; i < _materials.Count; i++){materials.Add(Globals.Invalid);}}else if (buildingState == BuildingPlacementState.FIXED){materials = _materials;}else{return;}gameObject.transform.Find("Mesh").GetComponent<Renderer>().materials = materials.ToArray();}/// <summary>/// 触发进入/// </summary>/// <param name="other"></param>private void OnTriggerEnter(Collider other){if (other.tag == "Terrain") return;_nCollisions++;ChangeState();}/// <summary>/// 触发离开/// </summary>/// <param name="other"></param>private void OnTriggerExit(Collider other){if (other.tag == "Terrain") return;_nCollisions--;ChangeState();}/// <summary>/// 根据自身的触发检测来改变状态/// </summary>public void ChangeState(){if (_state == BuildingPlacementState.FIXED){return;};if (_nCollisions > 0){_state = BuildingPlacementState.INVALID;SetMaterials(_state);}else{_state = BuildingPlacementState.VALID;SetMaterials(_state);}}/// <summary>/// 放置建筑物,改变建筑物状态和恢复颜色/// </summary>public void place(){_state = BuildingPlacementState.FIXED;SetMaterials(_state);gameObject.GetComponent<BoxCollider>().isTrigger = false;}public bool HasValidPlace{ get => _state == BuildingPlacementState.VALID; }}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Globals : MonoBehaviour
{public static BuildingData[] buildingDatas = new BuildingData[]{new BuildingData("Building",100)};//这里只保留地面的检测public static int TERRAIN_LAYER_MASK = 1 << 8;public static Material Valid = Resources.Load("Materials/Valid") as Material;public static Material Invalid = Resources.Load("Materials/Invalid") as Material;
}

4.总结

项目运行起来后,就可以进行Building实体的放置了,当放置时碰到已经放置的实体时会显示红色,点击鼠标左键也是没有效果的,如果是绿色,则可以直接左键放置。本博客只是一个小Demo,只是提供一个学习思路。

这篇关于RTS游戏关于建筑物放置的测试Demo(Unity)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/233943

相关文章

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @

国产游戏行业的崛起与挑战:技术创新引领未来

国产游戏行业的崛起与挑战:技术创新引领未来 近年来,国产游戏行业蓬勃发展,技术水平不断提升,许多优秀作品在国际市场上崭露头角。从画面渲染到物理引擎,从AI技术到服务器架构,国产游戏已实现质的飞跃。然而,面对全球游戏市场的激烈竞争,国产游戏技术仍然面临诸多挑战。本文将探讨这些挑战,并展望未来的机遇,深入分析IT技术的创新将如何推动行业发展。 国产游戏技术现状 国产游戏在画面渲染、物理引擎、AI

Verybot之OpenCV应用一:安装与图像采集测试

在Verybot上安装OpenCV是很简单的,只需要执行:         sudo apt-get update         sudo apt-get install libopencv-dev         sudo apt-get install python-opencv         下面就对安装好的OpenCV进行一下测试,编写一个通过USB摄像头采