
[Unity]建造放置系统BuildSystem
发布日期:2021-05-09 11:54:50
浏览次数:2
分类:技术文章
本文共 9708 字,大约阅读时间需要 32 分钟。
Build System
下载完毕,导入。
下面这个脚本,直接挂载到一个空物体,新建一个 3D物体 立方体,将其设置为 BuildGameObject变量的值(如下图所示)。新建一个 按钮button,来触发placeBool函数即可 实现放置基本的物体。
using UnityEngine;using BuildSystem;public class BuildManage : MonoBehaviour { public Material ghostMaterial;//放置物体 时候的 材质 private Material goMaterial; //********************************************************************************************** [Header("Input Settings")] [Tooltip("Key to press to enable the builder mode. This is also used by ObjectSelector")] public KeyCode toggleKey = KeyCode.E; [Tooltip("Key to press to place a item in the scene")] public KeyCode placeKey = KeyCode.Mouse0; [Tooltip("Key to press rotate (forward) the object based on snapRotaionDeg")] public KeyCode positiveRotateKey = KeyCode.Mouse1; [Tooltip("Key to press rotate (backward) the object based on snapRotaionDeg")] public KeyCode negativeRotateKey = KeyCode.None; [Header("More Settings")] [Tooltip("Disable the remover script when placer is active. Note: remover must be next to this script")] public bool shouldToggleRemover = true; [Tooltip("Max distance from camera where you can place objects")] public float maxPlaceDistance = 100f; /**************************************************** * Editor Interface * *************************************************/ [Tooltip("Camera used to raycast and find place position, if empty the script will try to use the main camera")] public Camera cam; public LayerMask movementMask;//设置 LayerMask public GameObject buildGameObject;//建设的物体 /**************************************************** * Variables * *************************************************/ bool isActive = true; bool canPlace = false; bool mouseIsNotOnUI = true; //object rotation float objectSnapCurrentRotaion = 0; //object pivot bool usingFakePivot = false; /**************************************************** * Events * *************************************************/ public delegate void BuildEvent(); public event BuildEvent OnGhostObjectCreation; public event BuildEvent OnGhostObjectDestroy; public event BuildEvent OnGhostObjectPlace; /**************************************************** * Components & references * *************************************************/ Transform ghostObjInstance; Transform myTransform; // Use this for initialization void Start () { if (cam == null) cam = CameraManager.instance.nowCamera; myTransform = transform; } void Update() { //点击鼠标左键 if (Input.GetMouseButtonDown(0) && canPlace == true) { PlaceGhostObject(); } } private void FixedUpdate() { //update ghost object position if (canPlace && ghostObjInstance != null) { MoveGhostObject(); } } //由按钮触发 public void placeBool() { canPlace = true; CreateGhostObject(); } /**************************************************** * Ghost Object Creation & Movement & Place * *************************************************/ ////// Create ghost object /// void CreateGhostObject() { DestroyGhostObject(); /*if (objectToPlace == null) { Debug.LogError("No item to instantiate! Aborting ghost creation."); return; }*/ ghostObjInstance = Instantiate(buildGameObject, myTransform.position, Quaternion.identity).GetComponent(); goMaterial =ghostObjInstance.transform.GetComponent ().material; ghostObjInstance.transform.GetComponent ().material = ghostMaterial; ghostObjInstance.transform.gameObject.layer = 0;//设置 新建物体 时候,的预览 幻影 物体 的层级。使其 不BUG //reset old object rotation //if (resetRotationAfterPlace) // objectSnapCurrentRotaion = 0; //check where is the pivot, if it is not in the base create a fake one usingFakePivot = false; Vector3 pivotOffsetExtra; bool objPivotIsBase = isPivotInBase(ghostObjInstance, out pivotOffsetExtra); //create a fake pivot if the real one is not in base if (!objPivotIsBase) { ghostObjInstance = CreateBasePivot(ghostObjInstance, pivotOffsetExtra); usingFakePivot = true; } if (OnGhostObjectCreation != null) { OnGhostObjectCreation(); } } /// /// Move the ghost object /// void MoveGhostObject() { Ray ray = cam.ScreenPointToRay(Input.mousePosition); RaycastHit hit; //射线只碰撞到 有碰撞体的物体 ,距离为 100 ,并且 LayerMask层级为 Floor的物体 if (Physics.Raycast(ray, out hit, maxPlaceDistance, movementMask)) { //set object position to hit point Vector3 pos = hit.point; ghostObjInstance.transform.position = pos; AlignGhostToSurface(ghostObjInstance, hit.normal); } } ////// Place the object in the scene /// void PlaceGhostObject() { if (ghostObjInstance != null) { Debug.Log("Created: " + ghostObjInstance.name); if (usingFakePivot) // remove fake pivot if using one { ghostObjInstance = ghostObjInstance.GetComponent().DeletePivot(); } //ghostObjInstance.transform.GetComponent ().material = goMaterial; //place real object in scene GameObject go = Instantiate(buildGameObject, ghostObjInstance.position, ghostObjInstance.rotation); go.layer = 8;//设置 物体的层级 //Debug.Log("ghostObjInstance.transform.childCount:"+ ghostObjInstance.transform.childCount); Destroy(ghostObjInstance.gameObject); if (OnGhostObjectPlace != null) { OnGhostObjectPlace(); } //CreateGhostObject(); //create a new ghost object } else Debug.LogError("Unable to spawn object, ghost reference is null!"); canPlace = false; } /// /// Remove ghost object from scene /// void DestroyGhostObject() { if (ghostObjInstance != null) { Destroy(ghostObjInstance.gameObject); /*if (OnGhostObjectDestroy != null) { OnGhostObjectDestroy(); }*/ } } /**************************************************** * Pivot helpers 中心点 * *************************************************/ ////// Create a pivot parent to better place the object /// /// Item to use /// Renderer of the item /// Offset of the pivot ///Transform CreateBasePivot(Transform item, Vector3 pivotOffset) { var normMesh = item.GetComponentInChildren (); var skinMesh = item.GetComponentInChildren (); if (normMesh == null && skinMesh == null) { Debug.LogError("No renderers found!"); return null; } GameObject pivotG = new GameObject("Temp_Ghost_Pivot_Parent"); // create parent Transform pivotT = pivotG.transform; pivotG.AddComponent (); // add helper class to remove the pivot when object is spawned //get mesh center Vector3 meshCenter = (normMesh != null) ? normMesh.bounds.extents : skinMesh.bounds.extents; // apply pivot delta meshCenter.x = pivotOffset.x; meshCenter.z = pivotOffset.z; meshCenter.y += pivotOffset.y; item.SetParent(pivotT); // set the current object as parent item.localPosition = meshCenter; // move the object and leave the parent object in the pivot position return pivotT; } /// /// Check if the object pivot is in center or not. /// This function returns the pivot Offset (can be Vector3.zero) /// /// Item to use /// Renderer attached to the item /// Offset of the pivot to be in base ///bool isPivotInBase(Transform item, out Vector3 pivotOffset) { var normMesh = item.GetComponentInChildren (); var skinMesh = item.GetComponentInChildren (); if (normMesh == null && skinMesh == null) { Debug.LogError("No mesh renderer found!"); pivotOffset = Vector3.zero; return false; } var pivotMargin = (normMesh != null) ? normMesh.bounds.extents.y * 2 / 3 : skinMesh.bounds.extents.y * 2 / 3; //set the base pivot margin. //Its' height must be lower than obj center * 2/3 Vector3 delta = item.position - ((normMesh != null) ? normMesh.bounds.center : skinMesh.bounds.center); if (delta.magnitude >= pivotMargin && delta.y < 0) //delta.y < 0 fix issues that not centerd pivots above the object center were taken as base pivots { pivotOffset = Vector3.zero; return true; } else { pivotOffset = delta; // save pivot delta to use to create a fake pivot return false; } } /**************************************************** * Ghost Object Alignament * *************************************************/ /// /// Align ghost object to surface based on raycast hit normal /// 使得 地板 layer 层级 的物体 ,创建的 时候 可以 避免相互之间 重叠 /// Item to align /// Normal to use to align object void AlignGhostToSurface(Transform itemToAlign, Vector3 hitNormal) { if (itemToAlign == null) return; itemToAlign.rotation = Quaternion.FromToRotation(Vector3.up, hitNormal) * Quaternion.Euler(new Vector3(0, objectSnapCurrentRotaion, 0)); }}
问题:
1.出现 放置物体 重叠 BUG 解决办法
参考资料:
1.
2.
Unity 使用自定义资源(.asset)配置数据
3.
转载地址:https://blog.csdn.net/BuladeMian/article/details/79293408 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2023年09月01日 09时51分25秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
倚靠小红书版“扎眼”,拼多多能否实现高端梦?
2019-03-07
小鹏汽车想“上天”,是太飘了吗?
2019-03-07
淘宝“雪藏“中差评,是对还是错?
2019-03-07
百度推出百度看看,在视频圈内真的“抗打”吗?
2019-03-07
朋友圈偷偷上线“话题标签”,微信也在做“破圈梦”?
2019-03-07
电商SaaS不好做,有赞亏到了末路?
2019-03-07
钱袋宝屡次被罚,美团为何做不好金融?
2019-03-07
两轮电动车,走不出“Tesla“
2019-03-07
豆神教育轻装上阵,搏命“大语文”下能否扭转24亿亏损的乾坤?
2019-03-07
哈啰是好单车,但哈啰出行是好生意吗?
2019-03-07
喜马拉雅的增量市场,AIOT能够承载多少空间?
2019-03-07
为了把pump文件还原进oracle数据库的一些步骤
2019-03-07
Idea配置mavne不生效
2019-03-07
nginx fastdfs 配置后 访问报404
2019-03-07
汇编语言
2019-03-07
java如何实现以数据流的形式下载压缩包到本地?
2019-03-07
汇编 第二章 寄存器(CPU工作原理)
2019-03-07
汇编 第四章 第一个汇编程序
2019-03-07
if判断(新增和编辑)使用模块。
2019-03-07