MR开发实战Hololens项目之汽车构造与组装(基于Vuforia物体识别)

一、框架视图

二、关键代码

CarBodyWork

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using UnityEngine.UIElements;
using Microsoft.MixedReality.Toolkit.UI;
using Microsoft.MixedReality.Toolkit.Input;

public class CarBodyWork : MonoBehaviour
{

    private bool isInstall;

    private Vector3 pos;
    private Quaternion qua;
    private ManipulationHandler manipulationHandler;
    private NearInteractionGrabbable nearInteractionGrabbable;
    private void Awake()
    {
        EventCenter.AddListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.AddListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
        gameObject.SetActive(false);

        pos = transform.localPosition;
        qua = transform.localRotation;
        manipulationHandler = transform.GetComponent<ManipulationHandler>();

        nearInteractionGrabbable = transform.GetComponent<NearInteractionGrabbable>();
    }

    private void FinshBtnClickHandle()
    {

        transform.SetParent(transform.parent.parent);
        manipulationHandler.enabled = true;
        nearInteractionGrabbable.enabled = true;
        transform.localPosition = pos;
        transform.localRotation = qua;
        transform.localScale = Vector3.one * 0.3f;//0730
        isInstall = false;
        gameObject.SetActive(false);
    }
    void Start()
    {
       
    }


    private void OnEnable()
    {
    
    }




    private void PartBtnClickHandle(string partName)
    {
        if (isInstall) return;

        if (partName==this.name)
            gameObject.SetActive(true); 
        else
            gameObject.SetActive(false);


    }

    void Update()
    {
        
    }


    private void OnTriggerEnter(Collider collider)
    {
        if (collider.name==Tags.InstallPoint)
        {
            //Todo

            transform.GetComponent<ManipulationHandler>().enabled = false;
            transform.GetComponent<NearInteractionGrabbable>().enabled = false;
            transform.SetParent(collider.transform);
            transform.GetComponent<AudioSource>().Play();
            transform.DOScale(Vector3.one, 2f);
            transform.DOLocalRotate(Vector3.zero, 2f);
            transform.DOLocalMove(Vector3.zero, 2f).OnComplete(()=> {
           
                UIManager.Instance.partId++;
                if (UIManager.Instance.partId==4)
                {
                    UIManager.Instance.ShowFinshPanel();
                }
            });
            UIManager.Instance.isPartsClick = true;
            isInstall = true;
        }
    }



    private void OnDestroy()
    {
        EventCenter.RemoveListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.RemoveListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
    }
}



CarShell

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using Microsoft.MixedReality.Toolkit.UI;
using Microsoft.MixedReality.Toolkit.Input;
public class CarShell : MonoBehaviour
{
    public Text text;

    private bool isInstall;
    private Vector3 pos;
    private Quaternion qua;
    private ManipulationHandler manipulationHandler;
    private NearInteractionGrabbable nearInteractionGrabbable;
    private void Awake()
    {
        pos = transform.localPosition;
        qua = transform.localRotation;
        EventCenter.AddListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.AddListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
        gameObject.SetActive(false);
        manipulationHandler = transform.GetComponent<ManipulationHandler>();

        nearInteractionGrabbable = transform.GetComponent<NearInteractionGrabbable>();
    }

    private void FinshBtnClickHandle()
    {
        transform.SetParent(transform.parent.parent);

        manipulationHandler.enabled = true;
        nearInteractionGrabbable.enabled = true;
        transform.localPosition = pos;
        transform.localRotation = qua;
        transform.localScale = Vector3.one * 0.3f;//0730
        isInstall = false;
        gameObject.SetActive(false);
    }

    void Start()
    {
       
    }
    private void OnEnable()
    {
   
      
    }

    private void PartBtnClickHandle(string partName)
    {
        if (isInstall) return;
        if (partName==this.name)
            gameObject.SetActive(true);
        else
            gameObject.SetActive(false);
    }

    void Update()
    {
        
    }


    private void OnTriggerEnter(Collider collider)
    {
        if (collider.name==Tags.InstallPoint)
        {

            transform.GetComponent<ManipulationHandler>().enabled = false;
            transform.GetComponent<NearInteractionGrabbable>().enabled = false;
            transform.SetParent(collider.transform);
            transform.GetComponent<AudioSource>().Play();
            transform.DOScale(Vector3.one, 2f);
            transform.DOLocalRotate(Vector3.zero, 2f);
            transform.DOLocalMove(Vector3.zero, 2f).OnComplete(() => {
      
                UIManager.Instance.partId++;
                if (UIManager.Instance.partId == 4)
                {
                    UIManager.Instance.ShowFinshPanel();
                }
            }); ;
            UIManager.Instance.isPartsClick = true;
            isInstall = true;
        }
    }



    private void OnDestroy()
    {
        EventCenter.RemoveListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.RemoveListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
    }
}



Engine

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using Microsoft.MixedReality.Toolkit.UI;
using Microsoft.MixedReality.Toolkit.Input;
public class Engine : MonoBehaviour
{

    private bool isInstall;

    private Vector3 pos;
    private Quaternion qua;

    private ManipulationHandler manipulationHandler;
    private NearInteractionGrabbable nearInteractionGrabbable;
    private void Awake()
    {
        pos = transform.localPosition;
        qua = transform.localRotation;
        EventCenter.AddListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.AddListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
        gameObject.SetActive(false);

        manipulationHandler = transform.GetComponent<ManipulationHandler>();

        nearInteractionGrabbable = transform.GetComponent<NearInteractionGrabbable>();
    }
    private void FinshBtnClickHandle()
    {
        transform.SetParent(transform.parent.parent);
      
        manipulationHandler.enabled = true;
        nearInteractionGrabbable.enabled = true;
        transform.localPosition = pos;
        transform.localRotation = qua;
        transform.localScale = Vector3.one* 0.3f;//0730
        isInstall = false;
        gameObject.SetActive(false);
    }
    void Start()
    {
       
    }

    private void OnEnable()
    {
      
       

    }

    private void PartBtnClickHandle(string partName)
    {
        if (isInstall) return;
        if (partName==this.name)
            gameObject.SetActive(true);
        else
            gameObject.SetActive(false);
    }

    void Update()
    {
        
    }


    private void OnTriggerEnter(Collider collider)
    {
        if (collider.name==Tags.InstallPoint)
        {

            transform.GetComponent<ManipulationHandler>().enabled = false;
            transform.GetComponent<NearInteractionGrabbable>().enabled = false;
            transform.SetParent(collider.transform);
            transform.GetComponent<AudioSource>().Play();
            transform.DOLocalRotate(Vector3.zero, 2f);
            transform.DOScale(0.2f, 2f);
           // transform.DOLocalMove(Vector3.zero, 2f).OnComplete(() => {
            transform.DOLocalMove(new Vector3(-0.2f,-0.08f,0), 2f).OnComplete(() => {
               // transform.localScale = Vector3.zero; //0730
                
                UIManager.Instance.partId++;
                if (UIManager.Instance.partId == 4)
                {
                    UIManager.Instance.ShowFinshPanel();
                }
            }); ;
            UIManager.Instance.isPartsClick = true;
            isInstall = true;
        }
    }



    private void OnDestroy()
    {
        EventCenter.RemoveListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.RemoveListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
    }
}



Wheel

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using Microsoft.MixedReality.Toolkit.UI;
using Microsoft.MixedReality.Toolkit.Input;

public class Wheel : MonoBehaviour
{
    public Text text;
    private bool isInstall;
    private Vector3 pos;
    private Quaternion qua;
    private ManipulationHandler manipulationHandler;
    private NearInteractionGrabbable nearInteractionGrabbable;
    private void Awake()
    {
        EventCenter.AddListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.AddListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
        gameObject.SetActive(false);
        pos = transform.localPosition;
        qua = transform.localRotation;
        manipulationHandler = transform.GetComponent<ManipulationHandler>();

        nearInteractionGrabbable = transform.GetComponent<NearInteractionGrabbable>();
    }
    private void FinshBtnClickHandle()
    {
        transform.SetParent(transform.parent.parent);
      
        manipulationHandler.enabled = true;
        nearInteractionGrabbable.enabled = true;
        transform.localPosition = pos;
        transform.localRotation = qua;
        transform.localScale = Vector3.one * 0.3f;//0730
        isInstall = false;
        gameObject.SetActive(false);
    }
    void Start()
    {
      
    }
    private void OnEnable()
    {
      
    }

    private void PartBtnClickHandle(string partName)
    {
        if (isInstall) return;
        if (partName==this.name)
            gameObject.SetActive(true);
        else
            gameObject.SetActive(false);
    }

    void Update()
    {
        
    }


    private void OnTriggerEnter(Collider collider)
    {
        if (collider.name==Tags.InstallPoint)
        {

            transform.GetComponent<ManipulationHandler>().enabled = false;
            transform.GetComponent<NearInteractionGrabbable>().enabled = false;
            transform.SetParent(collider.transform);
            transform.GetComponent<AudioSource>().Play();
            transform.DOScale(Vector3.one, 2f);
            transform.DOLocalRotate(Vector3.zero,2f);
            transform.DOLocalMove(Vector3.zero,2f).OnComplete(() => {
               
                UIManager.Instance.partId++;
                if (UIManager.Instance.partId == 4)
                {
                    UIManager.Instance.ShowFinshPanel();
                }
            }); ;
            UIManager.Instance.isPartsClick = true;
            isInstall = true;
        }
    }



    private void OnDestroy()
    {
        EventCenter.RemoveListener<string>(EventDefine.PartsBtnClick, PartBtnClickHandle);
        EventCenter.RemoveListener(EventDefine.FinshBtnClick, FinshBtnClickHandle);
    }
}



ArManager

using Microsoft.MixedReality.Toolkit.Experimental.Utilities;
using Microsoft.MixedReality.Toolkit.Utilities.Solvers;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;

public class ArManager : UnitySingleton<ArManager>
{
    public VuforiaBehaviour vuforia;

    public GameObject SceneRoot;

    public GameObject Follow; //扫描

  //  public GameObject CarEngine;
    private  Animator animator;
    private bool isRemove;

    

    void Start()
    {
     //   animator = CarEngine.transform.GetComponent<Animator>();
    }

    
    void Update()
    {
        
    }


    /// <summary>
    /// 脱卡控制
    /// </summary>
    public void OffCardCtrl() {

        vuforia.enabled = false;

        //广播发送脱卡事件码
        EventCenter.Broadcast(EventDefine.OffCard);

        //  SceneRoot.transform.localRotation = vuforia.transform.localRotation; //0721

       

        StartCoroutine(DelayHandle());

  
    }


    IEnumerator DelayHandle() {
        yield return new WaitForSeconds(0.2f);
        SceneRoot.transform.SetParent(null);
        SceneRoot.transform.localRotation = Quaternion.Euler(Vector3.zero);
    }


    public void OnAninatorCtrl() {

        if (!isRemove)
        {
            animator.SetBool("Remove", true);
            animator.SetBool("Install", false);
        }
        else
        {
            animator.SetBool("Install", true);
            animator.SetBool("Remove", false);
        }
        isRemove = !isRemove;
    }


    public void StartScan() {

        vuforia.enabled = true;
        
       // Follow.transform.localScale = new Vector3(4,4,4);

        Follow.transform.GetComponent<Follow>().enabled = false;
        Follow.transform.GetComponent<SolverHandler>().enabled = false;
        Follow.transform.SetParent(vuforia.transform);
        Follow.transform.localEulerAngles = Vector3.zero;
        Follow.transform.localScale = Vector3.one*6;
        Follow.transform.localPosition = new Vector3(0, -0.002f, 1.8f);
    }


    public void StructurenBtnClick() {
        Follow.transform.SetParent(null);
        Follow.transform.GetComponent<Follow>().enabled = true;
        Follow.transform.GetComponent<SolverHandler>().enabled = true;
        Follow.transform.localEulerAngles = Vector3.zero;
        Follow.transform.localScale = Vector3.one * 3;
        Follow.transform.localPosition = new Vector3(0, -0.08f, 1.2f);
    }


}


ButtonsHandler

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

public class ButtonsHandler : MonoBehaviour
{

    private void Awake()
    {
        
    }

    private void Start()
    {

    }

    private void OnEnable()
    {
        transform.GetComponent<Button>().onClick.AddListener(() => {
            OnButtonClicked();
        });

    }
    private void OnDisable()
    {
        
    }
    public void OnButtonClicked()
    {

        if (!UIManager.Instance.isPartsClick) return;

        AudioManager.Instance.PlayClick();
        Button btnName = transform.GetComponent<Button>();
        switch (btnName.name)
        {
            case Tags.CarShellBtn:
                EventCenter.Broadcast(EventDefine.PartsBtnClick,Tags.CarShell);
                break;
            case Tags.BodyWorkBtn:
                EventCenter.Broadcast(EventDefine.PartsBtnClick, Tags.CarBodyWork);
                break;
            case Tags.EngineBtn:
                EventCenter.Broadcast(EventDefine.PartsBtnClick, Tags.Engine);
                break;
            case Tags.WheelBtn:
                EventCenter.Broadcast(EventDefine.PartsBtnClick, Tags.Wheel);
                break;
            default:
                break;
        }

        Debug.Log("btnName.name:::"+btnName.name);
        UIManager.Instance.isPartsClick = false;
    }
    }

Car

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


public class Car : MonoBehaviour
{
    public float wheelSpeed;
    public GameObject[] Wheels;
    public ParticleSystem[] wheelSmokes;
    public ParticleSystem[] bodySmokes;

    public AudioClip audioClipShow;
    public AudioClip audioClipRunForeward;
    public AudioClip audioClipRunBack;

    private  bool isDriving;
    private AudioSource mAudioSource;
    void Start()
    {
     
        EventCenter.AddListener(EventDefine.OffCard,OffCardCtrl); //脱卡
        EventCenter.AddListener(EventDefine.FinshBtnClick, StartDriving);
        Init();
    }

    private void Init() {
        isDriving = false;
        mAudioSource = transform.GetComponent<AudioSource>();
        transform.localScale = Vector3.zero;
        StopWheelEffect();
    }


    private void OnEnable()
    {
        StopWheelEffect();
    }

    private void OffCardCtrl()
    {
        //0805
        transform.localPosition = Vector3.zero;
        transform.DOLocalMove(new Vector3(0, 0.086f, 0),6f);
        transform.DOScale(0.5f, 6f).OnComplete(()=> {
           // transform.DOScale(0.5f, 4f);
        });
       
        mAudioSource.clip = audioClipShow;
        mAudioSource.Play();
       // AudioManager.Instance.PlayShow();
    }

    // Update is called once per frame
    void Update()
    {
        if (isDriving)
        {
            for (int i = 0; i < Wheels.Length; i++)
            {
                Wheels[i].transform.Rotate(Vector3.right * wheelSpeed, Space.Self);
            }
        }
       
    }


    /// <summary>
    /// 开始车轮烟雾
    /// </summary>
    public void StartWheelEffect() {

        for (int i = 0; i < wheelSmokes.Length; i++)
        {
            wheelSmokes[i].Play();
        }
       
    }

    /// <summary>
    /// 停止车轮烟雾
    /// </summary>
    public void StopWheelEffect()
    {
        for (int i = 0; i < wheelSmokes.Length; i++)
        {
            wheelSmokes[i].Stop();
        }

        for (int i = 0; i < bodySmokes.Length; i++)
        {
            bodySmokes[i].Stop();
        }
    }


    public void StartDriving() {

        StartCoroutine(StartDriving_IE());
    
    }

    IEnumerator StartDriving_IE() {
        mAudioSource.clip = audioClipRunForeward;
        mAudioSource.Play();
        yield return new WaitForSeconds(0.5f);
        bodySmokes[0].Play();
        isDriving = true;
        yield return new WaitForSeconds(0.6f);
        bodySmokes[1].Play();
        yield return new WaitForSeconds(0.2f);
        StartWheelEffect(); //车烟
        yield return new WaitForSeconds(0.2f);
        // wheelSpeed= Mathf.Lerp(5f,10f,1f); //差值运算
        bodySmokes[0].Play();
        wheelSpeed =15f; 
        yield return new WaitForSeconds(0.5f);
        bodySmokes[1].Play();
        wheelSpeed = 20f;
        CarRun();
    }


    public void CarRun() {

        transform.DOLocalMoveX(-8,6).SetEase(Ease.InQuart);
        transform.DOScale(0, 6).SetEase(Ease.InQuart).OnComplete(()=> {
            transform.localPosition = new Vector3(8.043f, transform.localPosition.y, transform.localPosition.z);
            mAudioSource.clip = audioClipRunBack;
            mAudioSource.Play();
            transform.DOLocalMoveX(0f, 7).OnComplete(() =>
            {
                StopWheelEffect();
                wheelSpeed = 5f;
                wheelSpeed = Mathf.Lerp(5f, 1f, 0.1f);//差值运算
                // CacleLoopWheelEffect();
            }); ;
            transform.DOScale(0.5f, 8f).OnComplete(()=> {
                isDriving = false;
                UIManager.Instance.ShowHomePage();
                
            });
        }); ;
    }

   
    //public void CacleLoopWheelEffect() {

    //    for (int i = 0; i < wheelSmokes.Length; i++)
    //    {
    //        wheelSmokes[i].main.loop = false;
    //    }

    //}


    private void OnDestroy()
    {
        EventCenter.RemoveListener(EventDefine.OffCard, OffCardCtrl);
    }


}

Magnifier

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

public class Magnifier : MonoBehaviour
{
    /// 定义一个最大、bai最小的随机范围
    private float MinXYZ = -30F;
    private float MaxXYZ = 30F;

    private float MinX = -150F;
    private float MaxX = 150F;
    // 定义间du隔时间
    private float IntervalTime = 0.5F;
    // 要移动的物体
    private Transform Target;
    void Awake()
    {
       
        Target = transform;
    }

    private void Start()
    {
        EventCenter.AddListener(EventDefine.OffCard, StopScan);
    }



    private void Update()
    {
        //if (Input.GetMouseButtonDown(0))
        //{
        //    StopScan();
        //}
    }


    private void OnDestroy()
    {
        EventCenter.RemoveListener(EventDefine.OffCard, StopScan);
    }


    public void StartScan()
    {

        StartCoroutine(RandomCoordinate());
        transform.GetComponent<AudioSource>().Play();
        // AudioManager.Instance.PlayMagnifier();
    }

    public void StopScan()
    {
       
        StopAllCoroutines();
        //隐藏自己
        gameObject.transform.parent.gameObject.SetActive(false);
        transform.GetComponent<AudioSource>().Stop();
        // AudioManager.Instance.StopMagnifier();
    }
    IEnumerator RandomCoordinate()
    {
        // Target.localPosition = new Vector3(Random.Range(MinXYZ, MaxXYZ), Random.Range(MinXYZ, MaxXYZ), Random.Range(MinXYZ, MaxXYZ));
        Vector3 pos = new Vector3(Random.Range(MinX, MaxX), Random.Range(MinXYZ, MaxXYZ), Random.Range(MinXYZ, MaxXYZ));
        Target.DOLocalMove(pos, IntervalTime);
        // 等待时间重新随机位dao置
        yield return new WaitForSeconds(IntervalTime);

        StartCoroutine(RandomCoordinate());
    }
}

MyTrackableEventHandler

/*==============================================================================
Copyright (c) 2019 PTC Inc. All Rights Reserved.

Copyright (c) 2010-2014 Qualcomm Connected Experiences, Inc.
All Rights Reserved.
Confidential and Proprietary - Protected under copyright and other laws.
==============================================================================*/

using UnityEngine;
using Vuforia;

/// <summary>
/// A custom handler that implements the ITrackableEventHandler interface.
///
/// Changes made to this file could be overwritten when upgrading the Vuforia version.
/// When implementing custom event handler behavior, consider inheriting from this class instead.
/// </summary>
public class MyTrackableEventHandler : MonoBehaviour, ITrackableEventHandler
{
    #region PROTECTED_MEMBER_VARIABLES

    protected TrackableBehaviour mTrackableBehaviour;
    protected TrackableBehaviour.Status m_PreviousStatus;
    protected TrackableBehaviour.Status m_NewStatus;

    #endregion // PROTECTED_MEMBER_VARIABLES

    #region UNITY_MONOBEHAVIOUR_METHODS

    protected virtual void Start()
    {
        mTrackableBehaviour = GetComponent<TrackableBehaviour>();
        if (mTrackableBehaviour)
            mTrackableBehaviour.RegisterTrackableEventHandler(this);
    }

    protected virtual void OnDestroy()
    {
        if (mTrackableBehaviour)
            mTrackableBehaviour.UnregisterTrackableEventHandler(this);
    }

    #endregion // UNITY_MONOBEHAVIOUR_METHODS

    #region PUBLIC_METHODS

    /// <summary>
    ///     Implementation of the ITrackableEventHandler function called when the
    ///     tracking state changes.
    /// </summary>
    public void OnTrackableStateChanged(
        TrackableBehaviour.Status previousStatus,
        TrackableBehaviour.Status newStatus)
    {
        m_PreviousStatus = previousStatus;
        m_NewStatus = newStatus;
        
        Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + 
                  " " + mTrackableBehaviour.CurrentStatus +
                  " -- " + mTrackableBehaviour.CurrentStatusInfo);

        if (newStatus == TrackableBehaviour.Status.DETECTED ||
            newStatus == TrackableBehaviour.Status.TRACKED ||
            newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
        {
            OnTrackingFound();
        }
        else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
                 newStatus == TrackableBehaviour.Status.NO_POSE)
        {
            OnTrackingLost();
        }
        else
        {
            // For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
            // Vuforia is starting, but tracking has not been lost or found yet
            // Call OnTrackingLost() to hide the augmentations
            OnTrackingLost();
        }
    }

    #endregion // PUBLIC_METHODS

    #region PROTECTED_METHODS

    protected virtual void OnTrackingFound()
    {

        //0721
        ArManager.Instance.OffCardCtrl();


        if (mTrackableBehaviour)
        {
            var rendererComponents = mTrackableBehaviour.GetComponentsInChildren<Renderer>(true);
            var colliderComponents = mTrackableBehaviour.GetComponentsInChildren<Collider>(true);
            var canvasComponents = mTrackableBehaviour.GetComponentsInChildren<Canvas>(true);

            // Enable rendering:
            foreach (var component in rendererComponents)
                component.enabled = true;

            // Enable colliders:
            foreach (var component in colliderComponents)
                component.enabled = true;

            // Enable canvas':
            foreach (var component in canvasComponents)
                component.enabled = true;
        }
    }


    protected virtual void OnTrackingLost()
    {
        //0721
        if (mTrackableBehaviour)
        {
            var rendererComponents = mTrackableBehaviour.GetComponentsInChildren<Renderer>(true);
            var colliderComponents = mTrackableBehaviour.GetComponentsInChildren<Collider>(true);
            var canvasComponents = mTrackableBehaviour.GetComponentsInChildren<Canvas>(true);

            // Disable rendering:
            foreach (var component in rendererComponents)
                component.enabled = false;

            // Disable colliders:
            foreach (var component in colliderComponents)
                component.enabled = false;

            // Disable canvas':
            foreach (var component in canvasComponents)
                component.enabled = false;
        }
    }

    #endregion // PROTECTED_METHODS
}

StructurenCar

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

public class StructurenCar : MonoBehaviour
{
    
    

    void Start()
    {
        
    }


    private void OnEnable()
    {


        transform.GetChild(0).DOLocalMove(new Vector3(-0.695f, 0.485f, 0.68f),0.5f);
        transform.GetChild(1).DOLocalMove(new Vector3(0.473f, 0.607f, 0.605f), 0.5f);
        transform.GetChild(2).DOLocalMove(new Vector3(-0.872f, 0f, 0), 0.5f);
        transform.GetChild(3).DOLocalMove(new Vector3(0.555f, 0, 0), 0.5f).OnComplete(()=> {

            EventCenter.Broadcast(EventDefine.StructureDescriptionPanel,true);
        });

        transform.GetComponent<AudioSource>().Play();
    }



    private void OnDisable()
    {
        transform.GetChild(0).DOLocalMove(Vector3.zero,0);
        transform.GetChild(1).DOLocalMove(Vector3.zero, 0);
        transform.GetChild(2).DOLocalMove(Vector3.zero, 0);
        transform.GetChild(3).DOLocalMove(Vector3.zero, 0).OnComplete(() => {

            EventCenter.Broadcast(EventDefine.StructureDescriptionPanel, false);
        }); ;

    }


    void Update()
    {
        //if (Input.GetMouseButtonDown(0))
        //{
        //    transform.GetChild(0).DOLocalMove(new Vector3(-0.695f, 0.485f, 0), 2f);
        //    transform.GetChild(1).DOLocalMove(new Vector3(0.473f, 0.485f, 0), 2f);
        //    transform.GetChild(2).DOLocalMove(new Vector3(-0.824f, 0, 0), 2f);
        //    transform.GetChild(3).DOLocalMove(new Vector3(0.555f, 0, 0), 2f).OnComplete(() => {

        //        EventCenter.Broadcast(EventDefine.StructureDescriptionPanel, true);
        //    });
        //}
    }
}

三、效果展示