C# 使用由不同按钮生成的按钮销毁预制的克隆

C# 使用由不同按钮生成的按钮销毁预制的克隆,c#,unity3d,C#,Unity3d,我正在做一个Unity项目,在这个项目中,当从下拉按钮列表中选择时,立方体、球体和圆柱体等3D对象会出现在屏幕中央。实例化脚本工作正常,但所有3个对象都会生成并彼此合并。当其中一个被实例化时,它将销毁另外两个。我面临的问题是,生成的对象是一个克隆,我无法将其销毁。我是一个统一的初学者,并试图学习。我粘贴了下面的代码,为每个按钮创建了3个,并根据对象更改了参数 using System.Collections; using System.Collections.Generic; using Uni

我正在做一个Unity项目,在这个项目中,当从下拉按钮列表中选择时,立方体、球体和圆柱体等3D对象会出现在屏幕中央。实例化脚本工作正常,但所有3个对象都会生成并彼此合并。当其中一个被实例化时,它将销毁另外两个。我面临的问题是,生成的对象是一个克隆,我无法将其销毁。我是一个统一的初学者,并试图学习。我粘贴了下面的代码,为每个按钮创建了3个,并根据对象更改了参数

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

public class Cube_Inst : MonoBehaviour
{
    public GameObject box;
    public Transform pos;
    public bool trigger;
    public Button yourButton;
    public GameObject Sphere_Destroy;
    public GameObject Cylinder_Destroy;



    void Start()
    {
        Button btn = yourButton.GetComponent<Button>();
        btn.onClick.AddListener(TaskOnClick);
    }
    void TaskOnClick()
    {
        trigger = true;
        Destroy(Sphere_Destroy);
        Destroy(Cylinder_Destroy);
    }

    public void Update()
    {
        if (trigger == true)
        {
            Instantiate(box, pos.position, pos.rotation);
            trigger = false;
        }
    }

}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用UnityEngine.UI;
公共类多维数据集研究所:单一行为
{
公共游戏对象盒;
公共转换pos;
公共布尔触发器;
公共按钮你的按钮;
公共游戏对象球_销毁;
公共游戏对象的圆柱体(u)破坏;;
void Start()
{
Button btn=yourButton.GetComponent();
btn.onClick.AddListener(TaskOnClick);
}
void TaskOnClick()
{
触发器=真;
破坏(球体破坏);
破坏(圆柱体破坏);
}
公共无效更新()
{
如果(触发器==真)
{
实例化(框、位置、位置旋转);
触发器=假;
}
}
}

您更应该实现整个事情的集中化(“单一责任模式”)

不要让单独的按钮有单独的脚本,它们之间有大量的交叉引用

而是有一个中央控制器组件,让按钮将不同的参数传递给通用的spawn方法

此外,您还应该执行事件驱动的操作—您已经知道单击按钮的时刻—而不是在
Update
方法中轮询检查标志。 我会用像这样的东西

// Put this on ONE object that is always active in the Scene
public class SpawnController : MonoBehaviour
{
    private GameObject _currentClone;
    private GameObject _currentPrefab;

    public void SetInstance(GameObject prefab, Vector3 position, Quaternion rotation)
    {
        // Was the same prefab passed again? -> Ignore
        if(prefab == _currentPrefab) return;

        _currentPrefab = prefab;

        // Already exists a clone? -> Destroy it
        if(_currentClone) Destroy(_currentClone);

        // Create and store the new clone
        _currentClone = Instantiate (prefab, position, rotation);
    }
}
public class SpawnController : MonoBehaviour
{
    private GameObject _currentClone;
    private Button _lastClickedButton;

    private void Awake()
    {
        SpawnButton.OnSpawnButtonClicked += SetInstance;
    }

    private void SetInstance(Button button, GameObject prefab, Vector3 position, Quaternion rotation)
    {
        // Was the same button pressed again? -> Ignore
        if(button == _lastClickedButton) return;

        _lastClickedButton = button;

        // Already exists a clone? -> Destroy it
        if(_currentClone) Destroy(_currentClone);

        // Create and store the new clone
        _currentClone = Instantiate (prefab, position, rotation);
    }
}
因此,如果调用
SetInstance
,它会自动销毁任何现有实例

然后在每个按钮上都有相同的组件,但只相应地配置它们

public class SpawnButton : MonoBehaviour
{
    // Already reference this via the Inspector if possible
    // If not we will get it on runtime as fallback
    [SerializeField] private Button _button; 

    // For each different button reference a different prefab
    [SerializeField] private GameObject _prefab;  
    // Reference the spawn point
    [SerializeField] private Transform _spawnPoint;

    // Here drag in the SpawnController from the scene if possible
    // if not, we will find it on runtime as fallback
    [SerializeField] private SpawnController _spawnController;

    private void Awake()
    {
        if(!_button) _button = Get component<Button>();

        _button.onClick.AddListener(DoSpawn());

        if(!_spawnController) _spawnController = FindObjectOfType<SpawnController>();
    }

    private void DoSpawn()
    {
        // Only tell the SpawnController to do its thing
        // This button doesn't have to know or care what that means for the Scene

        _spawnController.SetInstance(_prefab, _spawnPoint.position, _spawnPoint.rotation);
    }
}
然后

public class SpawnButton : MonoBehaviour
{
    public static event Action<Button, GameObject, Vector3, Quaternion> OnSpawnButtonClicked;

    // Already reference this via the Inspector if possible
    // If not we will get it on runtime as fallback
    [SerializeField] private Button _button; 

    // For each different button reference a different prefab
    [SerializeField] private GameObject _prefab;  
    // Reference the spawn point
    [SerializeField] private Transform _spawnPoint;

    private void Awake()
    {
        if(!_button) _button = Get component<Button>();

        _button.onClick.AddListener(DoSpawn());
    }

    private void DoSpawn()
    {
        // Only Invoke the event
        // You don't care if or who is listening
        OnSpawnButtonClicked?.Invoke(this, _prefab, _spawnPoint.position, _spawnPoint.rotation);
    }
}
公共类按钮:单行为
{
公共静态事件动作OnSpawnButtonClicked;
//如果可能的话,已经通过检查员参考了这一点
//如果不是,我们将在运行时将其作为回退
[序列化字段]专用按钮\u按钮;
//对于每个不同的按钮参考,使用不同的预设
[SerializeField]私有游戏对象预制;
//参考繁殖点
[SerializeField]专用转换点;
私人空间
{
如果(!\u按钮)\u按钮=获取组件();
_button.onClick.AddListener(DoSpawn());
}
私人银行
{
//只调用事件
//你不在乎是否或谁在听
OnSpawnButtonClicked?.Invoke(这个,_预置,_spawnPoint.position,_spawnPoint.rotation);
}
}

非常感谢您的支持。真的很感激