虚拟仿真Unity3D中拆分模型教程(多种类型模型拆分)

Posted 恬静的小魔龙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了虚拟仿真Unity3D中拆分模型教程(多种类型模型拆分)相关的知识,希望对你有一定的参考价值。

推荐阅读

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

今天有小伙伴在我这篇文章【虚拟仿真】Unity3D对物体进行拆分实现下面问我如何一秒一拆:

虽然我已经给出了思路,但是离实现还是有点思路,正好我对于我这篇文章也是不满意,就解答一下小伙伴的疑惑,然后再将文章内容进行升级。

原文章:【虚拟仿真】Unity3D对物体进行拆分实现 的思路是获取子物体跟父物体之间的距离,然后拆分的时候让子物体移动到跟父物体距离的两倍的位置上,这种方法只能拆分完全对称镜像的模型,比如这样的:

但是,其他类型的,奇奇怪怪的模型估计就不那么好用了,所以本篇文章升级了一下,可以拆分更多模型,快来看看吧。

二、实现一秒一拆

首先,解决小伙伴一秒一拆代码的实现。本小节根据【虚拟仿真】Unity3D对物体进行拆分实现这篇文章基础上进行实现。

新建个项目,模板选3D,我用的是Unity3D版本是Unity 2019.4.7f1

搭建场景,简简单单搭一个十字模型:

DoTween插件导入:

新建脚本SplitTest.cs,双击打开脚本,修改代码:

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SplitTest : MonoBehaviour

    private Transform m_ParObj;//中心点
    private List<GameObject> m_Child;//所有子对象
    private List<Vector3> m_InitPoint = new List<Vector3>();//初始位置

    private int m_IsSplitState = 0;
    private float m_TimeTotal = 0;//总时间
    private float m_Timecurrent = 0;//当前时间
    private int m_TimeDisRe = 0;//时间间隔 记录
    private int IndexCount = 0;//计数

    public int m_TimeDistance = 1;//时间间隔

    void Start()
    
        m_ParObj = GetComponent<Transform>();
        m_Child = GetChild(m_ParObj);
        for (int i = 0; i < m_Child.Count; i++)
        
            m_InitPoint.Add(m_Child[i].transform.position);
        
        m_TimeTotal = m_Child.Count* m_TimeDistance;
    

    //获取所有子对象
    public List<GameObject> GetChild(Transform obj)
    
        List<GameObject> tempArrayobj = new List<GameObject>();
        foreach (Transform child in obj)
        
            tempArrayobj.Add(child.gameObject);
        
        return tempArrayobj;
    

    void Update()
    
        if (Input.GetKeyDown(KeyCode.W))
        
            m_Timecurrent = 0;
            m_TimeDisRe = 0;
            IndexCount = 0;
            m_IsSplitState = 1;
        
        if (Input.GetKeyDown(KeyCode.S))
        
            m_Timecurrent = 0;
            m_TimeDisRe = 0;
            IndexCount = 0;
            m_IsSplitState = 2;
        
        if (m_IsSplitState == 1)
        
            //拆分
            SplitObject();
        
        else if(m_IsSplitState == 2)
        
            //合并
            MergeObject();
        
    

    private void SplitObject()
    
        m_Timecurrent += Time.deltaTime;
        if (m_Timecurrent <= m_TimeTotal && IndexCount< m_Child.Count)
        
            if (Mathf.FloorToInt(m_Timecurrent) == m_TimeDisRe)
            
                m_TimeDisRe += m_TimeDistance;
                Vector3 tempV3 = SplitObjTest(m_ParObj.transform, m_Child[IndexCount].transform);
                m_Child[IndexCount].transform.DOMove(tempV3, 1f, false);
                IndexCount++;
            
        
    

    private void MergeObject()
    
        m_Timecurrent += Time.deltaTime;
        if (m_Timecurrent <= m_TimeTotal && IndexCount < m_Child.Count)
        
            if (Mathf.FloorToInt(m_Timecurrent) == m_TimeDisRe)
            
                m_TimeDisRe += m_TimeDistance;
                m_Child[IndexCount].transform.DOMove(m_InitPoint[IndexCount], 3f, false);
                IndexCount++;
            
        
    

    public Vector3 SplitObjTest(Transform m_ParObj, Transform _TargetObj)
    
        Vector3 tempV3;
        tempV3.x = (_TargetObj.position.x - m_ParObj.position.x) * 2;
        tempV3.y = (_TargetObj.position.y - m_ParObj.position.y) * 2;
        tempV3.z = (_TargetObj.position.z - m_ParObj.position.z) * 2;
        return tempV3;
    

效果图:

三、对称型模型拆分

模型样例:

这种规则的,对称的,镜像的,正方形的,都可以使用下面的代码。

新建脚本SplitCube.cs,修改代码:

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SplitCube : MonoBehaviour

    private Transform m_ParObj;//中心点
    private List<GameObject> m_Child;//所有子对象
    private List<Vector3> m_InitPoint = new List<Vector3>();//初始位置

    private void Start()
    
        m_ParObj = transform;
        m_Child = GetChild(m_ParObj);//获取所有子对象
        for (int i = 0; i < m_Child.Count; i++)
        
            m_InitPoint.Add(m_Child[i].transform.position);
        
    

    //获取所有子对象
    public List<GameObject> GetChild(Transform obj)
    
        List<GameObject> tempArrayobj = new List<GameObject>();
        foreach (Transform child in obj)
        
            tempArrayobj.Add(child.gameObject);
        
        return tempArrayobj;
    

    private void Update()
    
        if (Input.GetKeyDown(KeyCode.W))
        
            //拆分
            SplitObject();
        
        if (Input.GetKeyDown(KeyCode.S))
        
            //合并
            MergeObject();
        
    

    private void SplitObject()
    
        for (int i = 0; i < m_Child.Count; i++)
        
            Vector3 tempV3 = SplitObjTest(m_ParObj, m_Child[i].transform);
            m_Child[i].transform.DOMove(tempV3, 3f, false);
        
    

    private void MergeObject()
    
        for (int i = 0; i < m_InitPoint.Count; i++)
        
            m_Child[i].transform.DOMove(m_InitPoint[i], 3f, false);
        
    

    public Vector3 SplitObjTest(Transform m_ParObj, Transform _TargetObj)
    
        Vector3 tempV3;
        tempV3.x = (_TargetObj.position.x - m_ParObj.position.x) * 2;
        tempV3.y = (_TargetObj.position.y - m_ParObj.position.y) * 2;
        tempV3.z = (_TargetObj.position.z - m_ParObj.position.z) * 2;
        return tempV3;
    

效果图:

四、不规则形状模型拆分

搭建一个不规则的模型:

如果还用原来的代码就会有些问题:

那么就可以使用预先拆分法来拆分模型。

先把原模型复制一份出来,然后将零件移动到想要的位置上:

新建脚本SplitAnomaly.cs,修改脚本:

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SplitAnomaly : MonoBehaviour

    public Transform m_ChildPointParent;//要移动的子对象的父物体
    private List<GameObject> m_Child;//所有子对象
    private List<Vector3> m_InitPoint = new List<Vector3>();//初始位置

    public Transform m_TargetPointParent;//目标点对象的父物体
    private List<GameObject> m_TargetChild;//目标点所有子对象
    private List<Vector3> m_TargetPoint = new List<Vector3>();//要移动的位置

    private void Start()
    
        m_Child = GetChild(transform);//获取所有子对象
        for (int i = 0; i < m_Child.Count; i++)
        
            m_InitPoint.Add(m_Child[i].transform.position);
        

        m_TargetChild = GetChild(m_TargetPointParent);//获取所有目标点子对象
        for (int i = 0; i < m_TargetChild.Count; i++)
        
            m_TargetPoint.Add(m_TargetChild[i].transform.position);
        
    

    //获取所有子对象
    public List<GameObject> GetChild(Transform obj)
    
        List<GameObject> tempArrayobj = new List<GameObject>();
        foreach (Transform child in obj)
        
            tempArrayobj.Add(child.gameObject);
        
        return tempArrayobj;
    

    private void Update()
    
        if (Input.GetKeyDown(KeyCode.W))
        
            //拆分
            SplitObject();
        
        if (Input.GetKeyDown(KeyCode.S))
        
            //合并
            MergeObject();
        
    

    private void SplitObject()
    
        for (int i = 0; i < m_Child.Count; i++)
        
            m_Child[i].transform.DOMove(m_TargetPoint[i], 3f, false);
        
    

    private void MergeObject()
    
        for (int i = 0; i < m_InitPoint.Count; i++)
        
            m_Child[i].transform.DOMove(m_InitPoint[i], 3f, false);
        
    

给任意对象添加上SplitAnomaly 脚本组件,将对象对象拖入卡槽中:

效果图:

五、总结

再来总结一下实现的思路,首先获取到子对象到父对象的距离,将这个距离乘以2,然后将子对象移动到这个位置就实现了拆分。

但是,这在面对复杂模型的时候就不太好用了,这时候就可以使用第二种,不规则形状模型的拆分方法,也就是预拆法,先拆好,然后将子对象移动到要拆分的位置就可以了。

最后:

本篇文章的代码都是博主思考一遍遍调试修改来的,付出了不少心血。

如果这篇文章对你有帮助,受累一键三连。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

以上是关于虚拟仿真Unity3D中拆分模型教程(多种类型模型拆分)的主要内容,如果未能解决你的问题,请参考以下文章

虚拟仿真Unity3D中实现鼠标悬浮模型上显示文字

虚拟仿真Unity3D中模型的渐隐渐现效果实现

虚拟仿真Unity3D中模型的渐隐渐现效果实现

虚拟仿真Unity3D中如何实现让3D模型显示在UI前面

虚拟仿真Unity3D中如何实现让3D模型显示在UI前面

虚拟仿真实现Slider控制模型的从上到下消失