在自己制作项目的时候,限制玩家可移动范围,需要手动去摆一个一个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按钮即可。
最后看看我的场景中的应用:
省事还规整
文章来源: Unity3d 根据布线,自动生成碰撞墙
原文链接: https://blog.csdn.net/qq_18192161/article/details/79228268