Unity3d根据布线,自动生成碰撞墙
发表于2018-09-12
大多数游戏的地图是有范围限制的,怎么限制玩家在这个区域内去移动,如果手动去设置一个个collider感觉会很麻烦,且耗时间,于是就通过工具,画好路径,一键生成碰撞体,这就完美解决问题了。
先看效果:
这是绘制路径:
这是生成碰撞墙的效果:
看着感觉还不错,比用手去摆方便,下面是代码:
using UnityEngine; using System; public class FenceWall : MonoBehaviour { /// <summary> /// 尺寸 x:宽度 y高度 /// </summary> public Vector2 Size = new Vector2(1, 10); /// <summary> /// 补漏 /// </summary> public float BareSize = 0.5f; /// <summary> /// 路径 /// </summary> public Transform PathParent; /// <summary> /// 是否闭合路径 /// </summary> public bool IsClose = false; /// <summary> /// 是否绘制路径 /// </summary> public bool IsGizmos = false; /// <summary> /// 创建碰撞墙 /// </summary> public void CreateFenceWall() { if (PathParent == null) return; //查找已生成碰撞墙 Transform target = transform.Find("FenceWall"); if (target != null) { DestroyImmediate(target.gameObject); } //生成新的碰撞墙 GameObject parent = new GameObject("FenceWall"); parent.transform.localPosition = Vector3.zero; parent.transform.localScale = Vector3.one; //遍历路径 TraversePath(delegate(Transform trans1,Transform trans2) { CreateWall(trans1, trans2, delegate (GameObject go) { go.transform.parent = parent.transform; }); }); parent.transform.parent = transform; } /// <summary> /// 生成碰撞墙 /// </summary> /// <param name="pos1"></param> /// <param name="pos2"></param> /// <param name="onCreate"></param> private void CreateWall(Transform pos1, Transform pos2,Action<GameObject> onCreate) { GameObject go = new GameObject(pos1.name+"->"+pos2.name); float dis = Vector3.Distance(pos1.position, pos2.position); BoxCollider bc =go.AddComponent<BoxCollider>(); bc.size = new Vector3(dis+ BareSize, Size.y , Size.x); bc.center = new Vector3(0,Size.y/2,0); go.transform.parent = transform; go.layer = 1<<LayerMask.GetMask("Wall"); //计算坐标 go.transform.position = pos1.position + (pos2.position - pos1.position).normalized*(dis*0.5f); //计算旋转 float z = pos1.position.z - pos2.position.z; float angle = Mathf.Asin(z/dis)*Mathf.Rad2Deg; //计算旋转朝向 float dir = pos1.position.x - pos2.position.x > 0 ? -1 : 1; go.transform.rotation = Quaternion.Euler(new Vector3(0,angle* dir, 0)); if (onCreate != null) onCreate(go); } /// <summary> /// 遍历路径 /// </summary> /// <param name="onTraverse"></param> void TraversePath(Action<Transform, Transform> onTraverse) { int childCount = PathParent.childCount; if (childCount > 2) { for (int i = 0; i < childCount; i++) { Transform child1 = PathParent.GetChild(i); Transform child2 = null; if (i == childCount - 1) { if (IsClose) child2 = PathParent.GetChild(0); else break; } else child2 = PathParent.GetChild(i + 1); if (onTraverse != null) onTraverse(child1,child2); } } } /// <summary> /// 绘制路径 /// </summary> void OnDrawGizmos() { if (!IsGizmos) return; if (PathParent == null) return; TraversePath(delegate (Transform trans1, Transform trans2) { Gizmos.DrawLine(trans1.position, trans1.position); }); } }
编辑器类(就是加了一个按钮):
using UnityEngine; using UnityEditor; [CustomEditor(typeof(FenceWall))] public class FenceWallInspector : Editor { public override void OnInspectorGUI() { base.OnInspectorGUI(); FenceWall fw = (FenceWall)target; if (GUILayout.Button("Create Wall")) { fw.CreateFenceWall(); } } }
面板属性:
将此脚本挂载到GameObject上,设置路径,最后点击CreateWall按钮即可。
最后在场景中的应用:
来自:https://blog.csdn.net/qq_18192161/article/details/79228268