【问题标题】:Combining two instantiate scripts (Unity 3D)结合两个实例化脚本(Unity 3D)
【发布时间】:2020-02-11 08:38:28
【问题描述】:

我需要将以下脚本组合成一个包含两个函数的脚本,一个实例化数组中的下一个预制件,另一个实例化数组中的前一个预制件(它是一个虚拟旅游应用程序)。两者都应该销毁当前的预制件。然后我可以通过事件触发器调用这些函数。

我有这个“下一个预制”脚本的代码。

public GameObject[] Spheres;
    int currentIndex = 0;
    GameObject currentObject;
    public Camera MainCamera;

    void OnMouseDown()
    {
        if (Input.GetMouseButtonDown(0))
            if (gameObject.tag == "ArrowNEXT")
        {
            Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
            RaycastHit hit;

            if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
            {
                if (hit.collider != null)
                {
                    {
                            Destroy(currentObject);
                            currentIndex++;
                            if (currentIndex > Spheres.Length - 1) currentIndex = 0;
                            currentObject = Instantiate(Spheres[currentIndex]);
                    }
                }
            }


        }

    }

我需要将它与以下内容结合起来:

using UnityEngine;


public class RayCastPrevFIX: MonoBehaviour
{
    public GameObject[] Spheres;
    int currentIndex = 0;
    GameObject currentObject;
    public Camera MainCamera;

    void OnMouseDown()
    {
        if (Input.GetMouseButtonDown(0))
            if (gameObject.tag == "ArrowPREV")
            {
            Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
            RaycastHit hit;

            if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
            {
                if (hit.collider != null)
                {
                    {
                            Destroy(currentObject);
                            currentIndex--;
                            if (currentIndex < 0) currentIndex = Spheres.Length - 1;
                            currentObject = Instantiate(Spheres[currentIndex]);
                    }
                }
            }


        }

    }
}

我该怎么做呢?非常感谢任何帮助。到目前为止我有这个:

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

public class SphereSwap : MonoBehaviour
{ 
   public GameObject[] Spheres;
   int currentIndex = 0;
   GameObject currentObject;
   public Camera MainCamera;

   void Next()
   {
       Destroy(currentObject);
       currentIndex++;
       if (currentIndex > Spheres.Length - 1) currentIndex = 0;
       currentObject = Instantiate(Spheres[currentIndex]);
   }

   void Previous()
   {
       Destroy(currentObject);
       currentIndex--;
       if (currentIndex < 0) currentIndex = Spheres.Length - 1;
       currentObject = Instantiate(Spheres[currentIndex]);
   }
}

【问题讨论】:

    标签: arrays unity3d instantiation destroy virtual-tour


    【解决方案1】:

    您走在正确的道路上,但您可以缩短代码并在两种情况下使用一个函数来避免样板:

    using UnityEngine;
    public class SphereSwap : MonoBehaviour
    {
        public GameObject[] Spheres;
        int currentIndex = 0;
        GameObject currentObject;
        public Camera MainCamera;
    
        const string ArrowPrevTag = "ArrowPREV";
        const string ArrowNextTag = "ArrowNEXT";
    
    
        private void HandleClick(bool next)
        {
            if(Spheres == null || Spheres.Length == 0)
            {
                Debug.Log($"Spheres list is empty, nothing to swap.");
                return;
            }
    
            Vector3 rayOrigin = MainCamera.ViewportToWorldPoint(new Vector3(0.1f, 0.1f, 0));
            RaycastHit hit;
            if (Physics.Raycast(rayOrigin, MainCamera.transform.forward, out hit))
            {
                if (hit.collider != null)
                {
                    // destroy current sphere.
                    Destroy(currentObject);
                    // go next or previous.
                    currentIndex += next ? 1 : -1;
    
                    // circular clamp if overflow
                    if (currentIndex < 0)
                        currentIndex = Spheres.Length - 1;
                    else if (currentIndex >= Spheres.Length)
                        currentIndex = 0;
                    // finally do instantiate.
                    currentObject = Instantiate(Spheres[currentIndex]);
                }
            }
    
        }
        private void OnMouseDown()
        {
            if (Input.GetMouseButtonDown(0))
            {
                // 'CompareTag' is more efficient than gameobject.tag == "sometag"
                if (gameObject.CompareTag(ArrowNextTag))
                    HandleClick(true);
                else if (gameObject.CompareTag(ArrowPrevTag))
                    HandleClick(false);
            }
        }
    }
    

    【讨论】:

    • 哦,哇,我没想到。我是一名游戏美术师,所以我边走边学。两个问题: 1.) 我收到“数组外的索引”错误,突出显示 currentObject = Instantiate(Spheres[currentIndex]);第 32 行。 2.) 比较标签是否更有效,因为我的方式类似于查找(它必须在哪里追踪标签?)你避免使用事件触发器很好,这很好。
    • 啊,常量值更有效,因为它是一个未更改的字符串,所以不必在内存管理中“检查”它,对吧?
    • @JWolf 我添加了一个额外的检查,在交换之前检查您的“球体”列表是否为空,从而防止错误“数组外的索引”,你还明白吗?关于常量,在今天的计算中,2个字符串对内存的影响并不大,它只是一种编码约定,阻止了我们所说的魔术字符串,所以如果你要在其他地方使用标签,你不需要关心它的拼写,只要使用变量,当你需要编辑它时,你只能在它被赋值的地方编辑一次。
    • 是的,我刚刚发现 ;) 像往常一样,当艺术家学习编程时,错误生成器位于椅子和键盘之间。谢谢。如果我将此脚本附加到场景中的正向和反向箭头对象,它如何知道要销毁哪个对象(在运行的两个脚本之间)?有趣的是标签,这几乎就像创建一个引用原始代码的引用,因此您不必一遍又一遍地编写它。
    • 使用这些脚本中的两个附加到不同的对象(正向和反向箭头)会导致一些问题。在向前箭头对象之后单击反向箭头对象不会破坏由向前箭头实例化的最后一个球体。反向箭头实例化一个新球体,现在场景中有两个球体。有没有办法通过数组索引来跟踪这些球体,允许每个箭头脚本的删除函数在实例化一个新球体时删除场景中的所有球体?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多