unity 建造系统

最近项目要整个建造系统类似背包和RTS建造系统那样的:

预制体加载一个脚本(获取类型,检测是否有别的建造物)
预制体记得加载box collider组件,然后layer设置成Prefab

using UnityEngine;

public class PrefabObject : MonoBehaviour
{
    public int objectType;
    public static bool CheckOverlapInLayer(GameObject gameObject)
    {
        Collider collider = gameObject.GetComponent<Collider>();
        if (collider == null)
        {
            // 如果没有Collider组件,返回false
            return false;
        }

        Collider[] colliders = Physics.OverlapBox(collider.bounds.center, collider.bounds.extents);
        foreach (Collider otherCollider in colliders)
        {
            if (otherCollider.gameObject.layer == LayerMask.NameToLayer("Prefab"))
            {
                // 如果发现与指定Layer标签相符的Collider,且不是自身Collider
                if (otherCollider != collider)
                {
                    // 两个Collider重叠
                    return true;
                }
            }
        }
        // 两个Collider不重叠
        return false;
    }
}

主要逻辑脚本, 挂载在一个场景空对象上

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using System.IO;
using System.Linq;

public class PrefabManager : MonoBehaviour
{
    private List<PrefabClass> prefabList = new List<PrefabClass>();
    private List<GameObject> prefabInstances = new List<GameObject>();
    private GameObject currentGameObject; //想要创建的物体
    private int nodeCount = 0;

    public GameObject[] prefabs;
    public Dropdown prefabDropdown;
    public InputField nameField;
    public Button createButton;
    public Button deleteButton;
    public Transform transform;
    public Dropdown dropdown;   

    private void Start()
    {
        if (!File.Exists(Application.streamingAssetsPath + "/SaveData/prefabList.json"))
        {
            ForeachPrefabList(transform);
            SavePrefabList();
        }
        LoadPrefabList();
        RemoveExistingPrefabs();
        RefreshPrefabList();
        UpdateDropDownView();
        prefabDropdown.onValueChanged.AddListener(OnPrefabSelectionChanged);
        dropdown.onValueChanged.AddListener(OnSelectionChanged);
        createButton.onClick.AddListener(CreatePrefab);
        deleteButton.onClick.AddListener(DeletePrefab);
    }

private void Update()
    {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit raycastHit;
            //需要在场景内加一层plane提供meshCollider,否则raycastHit.point会一直为0
            if (Physics.Raycast(ray, out raycastHit))
            {
             Debug.DrawLine(ray.origin, hit.point,Color.green);//在编辑器视图中绘制射线
             if (Input.GetMouseButtonDown(0)) // 左键点击
             {CreatePrefab(raycastHit.point);}             
            }     
    }

    private void RemoveExistingPrefabs()
    {
        // 使用 FindObjectsOfType 方法查找特定类型的子物体
        PrefabObject[] children = GameObject.FindObjectsOfType<PrefabObject>();

        // 遍历子物体,从最后一个开始销毁
        for (int i = children.Length - 1; i >= 0; i--)
        {
            if (children[i].gameObject != gameObject)
            {
                Destroy(children[i].gameObject);
            }
        }
        //记得加个这个否则如果调用transform.childCount会多一倍
        transform.DetachChildren();
    }

    private void RefreshPrefabList()
    {
        foreach (var prefabClass in prefabList)
        {
            switch (prefabClass.type)
            {
                case 0:
                    currentGameObject = Instantiate(prefabs[0], prefabClass.vector3, prefabClass.rotation, transform);
                    break;
                case 1:
                    currentGameObject = Instantiate(prefabs[1], prefabClass.vector3, prefabClass.rotation, transform);
                    break;                
                default:
                    break;
            }
            currentGameObject.name = prefabClass.name;
            prefabInstances.Add(currentGameObject);
            nodeCount++;
        }
    }

    private void UpdateDropDownView()
    {
        //清空下下拉框数据
        dropdown.options.Clear();
        for (int i = 0; i < nodeCount; i++)
        {
            Dropdown.OptionData option = new Dropdown.OptionData();
            option.text = prefabInstances[i].name;
            dropdown.options.Add(option);
        }
    }

    private void OnSelectionChanged(int value)
    {
        if (value >= 0 && value < prefabList.Count)
        {
            MouseOperation.Instance.target.position = prefabList[value].vector3;
            Camera.main.transform.LookAt(prefabList[value].vector3);
        }
    }

    private void OnPrefabSelectionChanged(int value)
    {
        currentGameObject = prefabs[value];
    }

    private void CreatePrefab(Vector3 position)
    {
        switch (prefabDropdown.value)
        {
            case 0:
                currentGameObject = Instantiate(prefabs[0], position, prefabs[0].transform.localRotation, transform);
                break;
            case 1:
                currentGameObject = Instantiate(prefabs[1], position, prefabs[1].transform.localRotation, transform);
                break;
            default:
                break;
        }

        //判断是否重名和重合位置
        bool containsCharacter = prefabList.Any(x => x.name == nameField.text);
        if (PrefabObject.CheckOverlapInLayer(currentGameObject) || containsCharacter)
        {
            Destroy(currentGameObject);
        }
        else
        {
            currentGameObject.name = nameField.text;
            PrefabClass prefabClass = new PrefabClass();
            prefabClass.type = prefabDropdown.value;
            prefabClass.name = currentGameObject.name;
            prefabClass.vector3 = currentGameObject.transform.position;
            prefabClass.rotation = currentGameObject.transform.rotation;
            prefabList.Add(prefabClass);
            prefabInstances.Add(currentGameObject);
            SavePrefabList();
            Dropdown.OptionData newOption = new Dropdown.OptionData(currentGameObject.name);
            dropdown.options.Add(newOption);
            dropdown.RefreshShownValue();
            // 设置新添加选项为当前选中项
            dropdown.value = dropdown.options.Count - 1;
            nodeCount++;            
        }        
    }
    private void DeletePrefab()
    {
        int selectedIndex = dropdown.value;
        Destroy(prefabInstances[selectedIndex]);
        dropdown.options.RemoveAt(selectedIndex);
        dropdown.RefreshShownValue();                
        prefabInstances.RemoveAt(selectedIndex);
        prefabList.RemoveAt(selectedIndex);
        SavePrefabList();
        nodeCount--;
    }
    private void SavePrefabList()
    {
        // 清空之前的保存文件
        string json = JsonUtility.ToJson(new SerializablePrefabList(prefabList));
        File.WriteAllText(Application.streamingAssetsPath + "/SaveData/prefabList.json", json);
    }
    private void LoadPrefabList()
    {      
        string path = Application.streamingAssetsPath + "/SaveData/prefabList.json";
        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            SerializablePrefabList serializedList = JsonUtility.FromJson<SerializablePrefabList>(json);
            prefabList = serializedList.prefabList;
        }
    }
//我的场景本身存在一些预设的预制体,其实就是先存一下,别的项目不用也可以删除.
    private void ForeachPrefabList(Transform parentTransform)
    {
        for (int i = 0; i < parentTransform.childCount; i++)
        {
            GameObject childGameObject = parentTransform.GetChild(i).gameObject;
            PrefabClass prefabClass = new PrefabClass();
            PrefabObject childScript = childGameObject.GetComponent<PrefabObject>();
            prefabClass.type = childScript.objectType;
            prefabClass.name = childGameObject.name;
            prefabClass.vector3 = childGameObject.transform.position;
            prefabClass.rotation = childGameObject.transform.rotation;
            prefabList.Add(prefabClass);
            prefabInstances.Add(childGameObject);
            nodeCount++;
        }       
    }
}

[System.Serializable]
public class SerializablePrefabList
{
    public List<PrefabClass> prefabList;
    public SerializablePrefabList(List<PrefabClass> list)
    {
        prefabList = list;
    }
}

[System.Serializable]
public class PrefabClass
{
    public int type;
    public string name;
    public Vector3 vector3;
    public Quaternion rotation;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值