Unity3D:从变换中唯一可用的脚本访问方法

本文关键字:脚本 访问 方法 唯一 变换 Unity3D | 更新日期: 2023-09-27 18:01:17

场景:

我在一个场景中有10个对象。每个对象都附加了一个唯一的类。单击一个对象时,需要调用两个方法。

  • 附加到单击的gameObject的脚本中的方法。(启用新单击的对象的UI(
  • 以前单击的gameObject中的方法。(禁用以前单击的对象的UI(

我所做的:

if (Physics.Raycast(ray, out hit)) {
hit.transform.GetComponent(hit.transform.name+"").Show_status (true);
current_transform.GetComponent(current_transform.name+"").Show_status(false);
current_transform = hit.transform;
}

在这里,我试图使用字符串访问脚本,因为脚本是以gameObject本身命名的。名为"Show_status(("的方法可用于所有类。上述代码产生以下错误。

"UnityEngine.Component"不包含的定义`显示状态">

此外,如果我尝试的方式不可能做到这一点,那么提到一些其他简单的方法来解决这个场景会很有帮助。

Unity3D:从变换中唯一可用的脚本访问方法

按名称访问GameObject很慢。hit.transform.name速度较慢,每次调用它时都会分配内存。按字符串名称(GetComponent(string)(获取组件的速度也很慢。

如果按照我的尝试方式,这是不可能的,那将是有帮助的更不用说解决该场景的其他一些简单方法了。

这可以用CCD_ 3很容易地完成。

创建一个名为IClickable的简单脚本这不是一个类。它是一个接口

public interface IClickable
{
    void Show_status(bool value);
}

您的10脚本(在每个脚本中实现IClickable(:

Script1称为ObjectToClick1

public class ObjectToClick1 : MonoBehaviour, IClickable
{
    //Implement your interface function
    public void Show_status(bool value)
    {
        //Your implementation here
    }
}

Script2称为ObjectToClick2

public class ObjectToClick2 : MonoBehaviour, IClickable
{
    //Implement your interface function
    public void Show_status(bool value)
    {
        //Your implementation here
    }
}

Script3称为ObjectToClick3

public class ObjectToClick3 : MonoBehaviour, IClickable
{
    //Implement your interface function
    public void Show_status(bool value)
    {
        //Your implementation here
    }
}

现在,对于点击部分和检测哪个对象被点击:

public class ObjectTest : MonoBehaviour
{
    Transform current_transform;
    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //Raycast from mouse cursor pos
            RaycastHit rayCastHit;
            Ray rayCast = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(rayCast, out rayCastHit))
            {
                IClickable tempIClickable = rayCastHit.transform.GetComponent<IClickable>();
                if (tempIClickable != null)
                {
                    tempIClickable.Show_status(true);
                    current_transform.GetComponent<IClickable>().Show_status(false);
                    current_transform = rayCastHit.transform;
                }
            }
        }
    }
}

您可以添加尽可能多的接口。这是非常灵活的,可以用来检测可用的敌人类型。

错误告诉您到底出了什么问题,Unity Component类没有名为Show_status的方法。

必须将GetComponent返回的Component强制转换为自定义类。示例:

CustomClass yourClass = hit.transform.GetComponent(hit.transform.name) as CustomClass;
if(yourClass) {
    yourClass.Show_status(true);
}

参见:GameObject.GetComponent

您需要将GetComponent()的结果强制转换为一个类来访问其方法,但在您的情况下,您不知道哪个脚本附加到正在单击的GameObject。

这是继承提供可能解决方案的情况之一(另一种选择是将状态跟踪完全作为一个单独的组件(。既然您有一个在多个类之间通用的方法,为什么不让它们都从具有该方法的类中继承呢?然后你就不需要区分哪个具体在被点击的游戏对象上。

所以你的基类可能看起来像:

public class StatusTracker : MonoBehaviour {
    public virtual void Show_status(bool status){
        // Status-changing code
    }
}

然后,作为组件实际附加到GameObjects的类将继承自StatusTracker,并具有以下形式:

public class SpecializedStatusTracker : StatusTracker {
    public override void Show_status(bool status){
        // Alternative status-changing code
    }
}

注意:只有当您的类实现Show_status((时,才需要重写它——否则,您甚至不需要在子类中定义方法

相应地调整光线投射代码,然后可以将返回的Component投射到父类StatusTracker(使用GetComponent()的通用变体(,如下所示:

if (Physics.Raycast(ray, out hit)) {
    hit.transform.GetComponent<StatusTracker>().Show_status (true);
    current_transform.GetComponent<StatusTracker>().Show_status(false);
    current_transform = hit.transform;
}

希望这能有所帮助!如果你有任何问题,请告诉我。