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

时间:2016-08-08 18:45:46

标签: c# unity3d

情境:

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

  • 附加到单击的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“

另外,如果我尝试这种方式不可行,那么提一下解决方案的其他简单方法会很有帮助。

3 个答案:

答案 0 :(得分:2)

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

  

如果我尝试它的方式不可行,那将会很有帮助   提到一些解决方案的简单方法。

使用Interface可以轻松完成此操作。

创建一个名为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;
                }
            }
        }
    }
}

您可以添加尽可能多的界面。这非常灵活,可用于检测可用的敌人类型。

答案 1 :(得分:1)

错误告诉您确切的错误,Unity Component类没有名为Show_status的方法。

您必须将Component返回的GetComponent投射到自定义类。例如:

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

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

请参阅:GameObject.GetComponent

答案 2 :(得分:1)

您需要将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()的实现方式不同,您只需要覆盖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;
}

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