栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 游戏开发 > Unity3D

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

Unity3D 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • 我的个人博客
  • QQ群:1040082875

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新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 m_Child;//所有子对象
    private List m_InitPoint = new List();//初始位置

    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();
        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 GetChild(Transform obj)
    {
        List tempArrayobj = new List();
        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 m_Child;//所有子对象
    private List m_InitPoint = new List();//初始位置

    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 GetChild(Transform obj)
    {
        List tempArrayobj = new List();
        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 m_Child;//所有子对象
    private List m_InitPoint = new List();//初始位置

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

    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 GetChild(Transform obj)
    {
        List tempArrayobj = new List();
        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和坑,让后来人可以有些参考。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/897669.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号