Unity3d 根據佈線,自動生成碰撞牆

在自己製作項目的時候,限制玩家可移動範圍,需要手動去擺一個一個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按鈕即可。

最後看看我的場景中的應用:
這裏寫圖片描述

省事還規整

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章