做得有些复杂,但好在还没卡。目前只实现了基本的网格建造功能,像一些道路、城墙这种能拼接的建筑还不能做,到时候每个建筑自身写个类试一下。

关于建造类的代码就先到这,用PlayerPrefs做的这个类只是实现了基本思路,后面要做的话我觉得可能还是会用JSON

遗留下来的问题大致有三个,一是这个Update有些占资源,但是又没法删掉(因为后续要做的功能可能会很大,希望在合适的时间打开这个功能)。第二是没能做到区分两次点击,而是暂时用左右键来区分(毕竟玩家习惯于点击左键操作,而且最好将右键作为取消键)。第三是铲除建筑的时候鼠标必须点到建筑上,而点到建筑所在的地面块时并不会让建筑消失,只能让存档中的该建筑消失(如果这样的话,就会要求美工为建筑加一个薄薄的底座以覆盖地面网格,需要花时间调整尺寸,还占用资源,而且不美观,显然很麻烦)。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;///-----------------------------------------------------------------------------------------
///   Founction:
///   InvolvingKnowledge:
///   Author:                   AttouchAusturo
///   LatestReviseTime:
///-----------------------------------------------------------------------------------------public class PreventBuildFunction : MonoBehaviour
{//建筑的代号 /唯一标识 可表示建筑本身 建筑尺寸 /最多达到99 /编码中该位置为0表示杂草,整串编码只有一个0表示空地 /99表示被占用的土地public int buildingID;//建筑预制件 /提前指定public GameObject followTestPrefab; //建造预览物体预制件 /暂定:小圆球public GameObject preventPrefab; //阻止建造物体预制件 /暂定:大方块public GameObject tentPrefab; //帐篷public GameObject materialsPrefab; //物资public GameObject manorPrefab; //庄园public GameObject warehousePrefab; //仓库//要建造的建筑和建筑实例 /非提前指定private GameObject objectToBuild; //衔接选择建筑与建造private GameObject objectToReBuild; //衔接选择建筑与重建private GameObject buildings; //建造物实例化private GameObject virtualBuilding; //预览建造物//便于取出编码信息public int positionX, positionZ, newBuildingID, newPositionX, newPositionZ;//建筑码 /编码为建筑属性public int allCode;//建筑码存储地址 /编码后转字符串 /地址为网格属性public int theAddress, theNewAddress;public string strTheAddress;//射线获取坐标public Vector3 target;//鼠标点击位置的世界坐标public Ray ray; public RaycastHit hit; //一个类 用于存储发射射线后产生的碰撞信息 常用的成员变量collider distance normal point //坐标转换public int offset; //偏移public Vector3 groundArea;public Vector3 recGroundArea;//判断 /是否仍被选中 /未点击建造public int beSelected = 0;//判断 /是否有障碍public int beOccupied = 0;private void OnGUI(){GUILayout.BeginHorizontal("box");GUILayout.Label("选择建筑");if (GUILayout.Button("小帐篷")) { buildingID = 1; beSelected = 1; } //边长1if (GUILayout.Button("物资")) { buildingID = 2; beSelected = 1; } //边长1if (GUILayout.Button("庄园")) { buildingID = 3; beSelected = 1; } //边长3 if (GUILayout.Button("仓库")) { buildingID = 4; beSelected = 1; } //边长2 if (GUILayout.Button("铲除")) { buildingID = 0; }GUILayout.EndHorizontal();}private void Start(){buildingID = 99;//ClearAllBuildings(); //清除存档内容为xxxx00TryingMyRebuildMethodWithPlayerPrefs(); //重现存档中建筑}private void Update(){CreateBuilding(); //建造功能函数 /目前包含功能 射线检测 坐标取整 生成建筑 生成编码并保存 建造中实时预览 多网格建造 阻止重复建造UpRoot(); //拆除 /目前}//建造功能private void CreateBuilding(){//如何区分两个因果关系的点击为两次点击 /暂时方案:区分左右键if ((buildingID != 99) && (buildingID != 0)){//如果未决定建造 /预览if (beSelected != 0){//射线 /得到格子信息hit和targetRayCheckGroundArea();//区分建筑尺寸 /根据建筑ID发生偏移 /由ID计算groundAreaDistinguishDifferentSizeBuildings();//如果groundArea发生改变 if (groundArea != recGroundArea){//摧毁上一个位置的对象Destroy(virtualBuilding, 0);//恢复 重新检测beOccupied = 0;//编写地址theAddress = 10000 + ((int)target.x / 10 + 1) * 100 + ((int)target.z / 10 + 1);//以所持有建筑ID为依据 决定要检测的格数 /每格单独检测switch (buildingID){case 1:case 2:strTheAddress = theAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++; break;case 3:strTheAddress = theAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 1; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 2; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 100; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 101; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 102; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 200; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 201; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 202; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++; break; //3*3case 4:strTheAddress = theAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 1; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 100; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++;theNewAddress = theAddress + 101; strTheAddress = theNewAddress.ToString(); allCode = PlayerPrefs.GetInt(strTheAddress); if (allCode != 0) beOccupied++; break; //2*2}//生成圆球if (beOccupied == 0) virtualBuilding = Instantiate(followTestPrefab, groundArea, Quaternion.identity) as GameObject;//生成方块else virtualBuilding = Instantiate(preventPrefab, groundArea, Quaternion.identity) as GameObject;}//记录鼠标位置变化recGroundArea = groundArea;}//预览//当点击鼠标右键时 /决定建造if (Input.GetMouseButtonDown(1)){//如果无障碍if (beOccupied == 0){//删除最后残留的预览物体Destroy(virtualBuilding, 0);//射线RayCheckGroundArea();//取消预览beSelected = 0;//区分建筑尺寸DistinguishDifferentSizeBuildings();//在格子中央生成该物体buildings = Instantiate(objectToBuild, groundArea, Quaternion.identity) as GameObject;//将新建筑编码并保存CodingNewBuildings();buildingID = 99;} }//决定建造}}//建造功能//射线检测坐标private void RayCheckGroundArea(){//鼠标在屏幕的位置Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out hit)) //Physics.Raycast(ray, out hit) 该方法中hit变量会携带检测物体的相关信息 如transform {//绘制出一条从相机射出的红色射线Debug.DrawLine(Camera.main.transform.position, hit.point, Color.red);}//获取点击位置的世界坐标target = hit.point;}//射线检测坐标//铲除private void UpRoot(){//手动铲除建筑 /难点:由建筑获取其地址if (buildingID == 0){//确定铲除对象if (Input.GetMouseButtonDown(1)){//射线RayCheckGroundArea();//取出该地址存储的codetheAddress = 10000 + ((int)target.x / 10 + 1) * 100 + ((int)target.z / 10 + 1);strTheAddress = theAddress.ToString();allCode = PlayerPrefs.GetInt(strTheAddress);//解码 取地址positionX = allCode / 10000 - 1;positionZ = allCode % 10000 / 100 - 1;//在存档中将所有相同地址的网格改为0 /替代原数据for (int i = 1; i < 21; i++){for (int j = 1; j < 21; j++){theAddress = 10000 + (i * 100) + j;strTheAddress = theAddress.ToString();allCode = PlayerPrefs.GetInt(strTheAddress);newPositionX = allCode / 10000 - 1;newPositionZ = allCode % 10000 / 100 - 1;if ((positionX == newPositionX) && (positionZ == newPositionZ)){PlayerPrefs.SetInt(strTheAddress, 0);}}}//暂时替代方案:移走这个模型 /这样既可以实现消失的效果 又不用担心点到地面hit.transform.position = new Vector3(-200, -5, -200);//结束buildingID = 99;}}}//铲除//区分建筑尺寸 /在决定建造前被调用 /根据建筑ID发生偏移private void DistinguishDifferentSizeBuildings(){switch (buildingID){case 1: offset = 5; objectToBuild = tentPrefab; break;case 2: offset = 5; objectToBuild = materialsPrefab; break;case 3: offset = 15; objectToBuild = manorPrefab; break;case 4: offset = 10; objectToBuild = warehousePrefab; break;}groundArea = new Vector3((int)target.x / 10 * 10 + offset, 0, (int)target.z / 10 * 10 + offset);}//区分建筑尺寸//将新建筑编码 /仅在决定建造时被调用private void CodingNewBuildings(){//编码allCode = ((int)target.x / 10 + 1) * 10000 + (((int)target.z / 10 + 1) * 100) + buildingID;//保存TryingMyNewSavingMethodWithPlayerPrefs();//在存档中将多余网格数据改为xxxx99 /99即占用 /99前表示其占有者的位置 /如果包含99的code中存储的是自身位置 将没有意义 /只有一个位置将生成物体时 位置才有意义switch (buildingID){case 1: break;case 2: break;case 3:allCode = ((int)target.x / 10 + 1) * 10000 + (((int)target.z / 10 + 1) * 100) + 99;theAddress = 10000 + (((int)target.x / 10 + 1) * 100) + ((int)target.z / 10 + 2); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 1) * 100) + ((int)target.z / 10 + 3); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 2) * 100) + ((int)target.z / 10 + 1); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 2) * 100) + ((int)target.z / 10 + 2); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 2) * 100) + ((int)target.z / 10 + 3); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 3) * 100) + ((int)target.z / 10 + 1); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 3) * 100) + ((int)target.z / 10 + 2); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 3) * 100) + ((int)target.z / 10 + 3); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);break; //3*3case 4:allCode = ((int)target.x / 10 + 1) * 10000 + (((int)target.z / 10 + 1) * 100) + 99;theAddress = 10000 + (((int)target.x / 10 + 1) * 100) + ((int)target.z / 10 + 2); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 2) * 100) + ((int)target.z / 10 + 2); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);theAddress = 10000 + (((int)target.x / 10 + 2) * 100) + ((int)target.z / 10 + 1); strTheAddress = theAddress.ToString(); PlayerPrefs.SetInt(strTheAddress, allCode);break; //2*2}}//将新建筑编码 //清除所有建筑private void ClearAllBuildings(){for (int i = 1; i < 21; i++){for (int j = 1; j < 21; j++){allCode = i * 10000 + (j * 100); //xxxx00theAddress = 10000 + (i * 100) + j;strTheAddress = theAddress.ToString();PlayerPrefs.SetInt(strTheAddress, allCode);}}}//清除所有建筑//保存建筑private void TryingMyNewSavingMethodWithPlayerPrefs(){positionX = allCode / 10000 - 1;positionZ = allCode % 10000 / 100 - 1;if ((positionX > -1 && positionX < 20) && (positionZ > -1 && positionZ < 20)) //范围限制:世界中心正20*20格{theAddress = 10000 + ((positionX + 1) * 100) + (positionZ + 1);strTheAddress = theAddress.ToString();PlayerPrefs.SetInt(strTheAddress, allCode);}}//保存建筑//重现存档中建筑 /取出所有地址中的值,赋给Code并进行解码private void TryingMyRebuildMethodWithPlayerPrefs(){for (int i = 1; i < 21; i++){for (int j = 1; j < 21; j++){theAddress = 10000 + (i * 100) + j;strTheAddress = theAddress.ToString();allCode = PlayerPrefs.GetInt(strTheAddress);AnalyzeCode();//解码}}}//重现存档中建筑//解码 并生成建筑 /根据建筑ID发生偏移private void AnalyzeCode(){if (allCode != 0) //若为0则什么也不做{positionX = allCode / 10000 - 1;positionZ = allCode % 10000 / 100 - 1;newBuildingID = allCode % 100;switch (newBuildingID){case 0: offset = 5; objectToReBuild = tentPrefab; break; //改为杂草case 1: offset = 5; objectToReBuild = tentPrefab; break;case 2: offset = 5; objectToReBuild = materialsPrefab; break;case 3: offset = 15; objectToReBuild = manorPrefab; break;case 4: offset = 10; objectToReBuild = warehousePrefab; break;case 99: offset = 0; break;}if (offset != 0) buildings = Instantiate(objectToReBuild, new Vector3(positionX * 10 + offset, 0, positionZ * 10 + offset), Quaternion.identity) as GameObject;}}//解码 并生成建筑}

C#笔记12//建造游戏8/阻止重复建造相关推荐

  1. rust沙河游戏_十款特别好玩的沙盒建造游戏,喜欢生存建造的朋友千万不要错过...

    原标题:十款特别好玩的沙盒建造游戏,喜欢生存建造的朋友千万不要错过 各位上期在文章里我把鬼泣(ACT)弄到RPG游戏里,非常的抱歉,希望大家给我多多提建议,我会做的更好,喜欢的朋友可以关注我一下,毕竟 ...

  2. 笔记12 SQL优化

    笔记12 性能与SQL优化 1.性能优化 复习一下什么是性能: DB/SQL 优化是业务系统性能优化的核心 2.关系数据库 MySQL 什么是关系数据库 数据库设计范式 常见关系数据库 SQL 语言 ...

  3. 【Visual C++】游戏开发笔记十五 游戏人工智能(一) 运动型游戏AI

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...

  4. 【转】【Visual C++】游戏开发笔记十五 游戏人工智能(一) 运动型游戏AI

    原文连接:http://www.cnblogs.com/dyllove98/archive/2012/04/07/2461865.html#commentform 我们常常听闻AI(Artificia ...

  5. 【Visual C++】游戏开发笔记十五 游戏人工智能(一) 运动型游戏AI .

    本系列文章由zhmxy555编写,转载请注明出处.  http://blog.csdn.net/zhmxy555/article/details/7434317 作者:毛星云    邮箱: happy ...

  6. [原]【Visual C++】游戏开发笔记十五 游戏人工智能(一) 运动型游戏AI

    本系列文章由zhmxy555编写,转载请注明出处.  http://blog.csdn.net/zhmxy555/article/details/7434317 作者:毛星云    邮箱: happy ...

  7. 游戏开发笔记十五 游戏人工智能(一) 运动型游戏AI

    我们常常听闻AI(Artificial Intelligence人工智能)这个名词,比如Dota里面的AI地图.写这篇文章的时候,最新版的Dota AI是6.72f,估计过几天6.73的AI也要出来了 ...

  8. 台大李宏毅Machine Learning 2017Fall学习笔记 (12)Why Deep?

    台大李宏毅Machine Learning 2017Fall学习笔记 (12)Why Deep? 本博客整理自: http://blog.csdn.net/xzy_thu/article/detail ...

  9. DirectX 12 3D 游戏开发与实战第五章内容

    渲染流水线 学习目标: 了解用于在2D图像中表现出场景立体感和空间深度感等真实效果的关键因素 探索如何用Direct3D表示3D对象 学习如何建立虚拟摄像机 理解渲染流水线,根据给定的3D场景的几何描 ...

最新文章

  1. MYSQL注入天书之服务器(两层)架构
  2. 047_Divider分割线
  3. 【特征工程】特征分箱
  4. String转Double
  5. java小细节_为什么我喜欢Java的细节
  6. 使用ActionTrail Python SDK
  7. python—列表、字典生成式
  8. 如何测试Nginx的高性能
  9. 函数式编程(Functional Programming)
  10. IT人的爱情生活散记
  11. 如何用EasyRecovery找回删除的文档(附注册机下载地址)
  12. VC2005-应用程序正常初始化失败-0xc0150002
  13. 上海域格CLM920 JC3(JC5)模组安卓系统下会显示以太网图标的处理
  14. HTML标签和说明属性
  15. 立创EDA的元件库导入AD
  16. docker bind source path does not exist: /etc/timezone“
  17. Java代码走查审查规范总结
  18. 转载标明出处用英语_公众号转载文章时应当注明出处
  19. 如何有效进行项目集管理?
  20. Dubbo解析及原理浅析

热门文章

  1. 大道至简之五:透过现象看本质
  2. 创意油彩杂志风年终总结PPT模板-优页文档
  3. 仿小蚂蚁门户网站 php,仿小蚂蚁大气地方门户模版Discuz! X2.5
  4. 漏洞复现-永恒之蓝(MS17-010)
  5. 渗透测试中网站代码漏洞审计服务
  6. javaScript 双感叹号用法
  7. el-upload 限制上传数量,然后隐藏加号
  8. 2022年高压电工特种作业证考试题库模拟考试平台操作
  9. 史蒂夫·鲍尔默清华大学演讲实录 1
  10. 重新理解pandas.DataFrame.ewm