繁体   English   中英

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

[英]Unity3D: Accessing a Method from the only script available in a transform

场景:

我在一个场景中有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”不包含“ Show_status”的定义

此外,如果这不是我尝试的方式,则提及解决方案的其他一些简单方法将很有帮助。

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

如果这不是我尝试的方式,那么提及解决方案的其他一些简单方法将很有帮助。

使用Interface可以很容易地做到这一点。

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

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

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

脚本1称为ObjectToClick1

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

脚本2称为ObjectToClick2

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

脚本3称为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 GetComponent为自定义类。 例:

CustomClass yourClass = hit.transform.GetComponent(hit.transform.name) as CustomClass;

if(yourClass) {
    yourClass.Show_status(true);
}

请参阅: GameObject.GetComponent

您需要将GetComponent()的结果GetComponent()为一个类,以访问其方法-但在您所处的情况下,您不知道哪个脚本附加到了要单击的GameObject上。

这是继承提供一种可能的解决方案的情况之一(替代方案是使状态完全跟踪一个单独的组件)。 由于您有一个在多个类之间通用的方法,为什么不让它们全部都继承自具有该方法的类呢? 然后,您无需区分要单击的GameObject上的哪一个。

因此,您的基类可能看起来像:

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

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

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

注意:如果您的类与通用Show_status()的实现方式不同,则只需要重写Show_status()即可;否则,您甚至无需在子类中定义方法!

相应地调整raycast代码,然后可以将返回的Component StatusTracker为父类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;
}

希望这可以帮助! 如果您有任何疑问,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM