Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Unity3D:从变换中唯一可用的脚本访问方法_C#_Unity3d - Fatal编程技术网

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

C# Unity3D:从变换中唯一可用的脚本访问方法,c#,unity3d,C#,Unity3d,情景: 我在一个场景中有10个对象。每个对象都附加了一个唯一的类。单击一个对象时,需要调用两个方法 附加到单击的游戏对象的脚本中的方法。启用新单击的对象的UI 来自先前单击的游戏对象的方法。禁用以前单击的对象的UI 我所做的: 在这里,我尝试使用字符串访问脚本,因为脚本是以游戏对象本身命名的。名为Show_status的方法可用于所有类。上面的代码产生下面的错误 UnityEngine.Component'不包含的定义 `显示您的状态 此外,如果我尝试的方法不可能做到这一点,那么提及一些其他简单

情景:

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

附加到单击的游戏对象的脚本中的方法。启用新单击的对象的UI 来自先前单击的游戏对象的方法。禁用以前单击的对象的UI 我所做的:

在这里,我尝试使用字符串访问脚本,因为脚本是以游戏对象本身命名的。名为Show_status的方法可用于所有类。上面的代码产生下面的错误

UnityEngine.Component'不包含的定义 `显示您的状态


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

错误会准确地告诉您问题所在,Unity类没有名为Show\u status的方法

必须将GetComponent返回的组件强制转换为自定义类。例如:

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

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

请参阅:

错误会准确地告诉您错误所在,Unity类没有名为Show\u status的方法

必须将GetComponent返回的组件强制转换为自定义类。例如:

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

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

请参阅:

您需要将GetComponent的结果强制转换为类以访问其方法-但在您的情况下,您不知道哪个脚本附加到正在单击的游戏对象

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

因此,您的基类可能如下所示:

public class StatusTracker : MonoBehaviour {
    public virtual void Show_status(bool status){
        // Status-changing code
    }
}
然后,作为组件实际附加到游戏对象的类将继承自StatusTracker,并具有以下形式:

public class SpecializedStatusTracker : StatusTracker {
    public override void Show_status(bool status){
        // Alternative status-changing code
    }
}
注意:如果您的类实现的Show_status与泛型Show_status不同,您只需要重写Show_status,否则,您甚至不需要在子类中定义该方法

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


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

您需要将GetComponent的结果强制转换到类以访问其方法-但在您的情况下,您不知道哪个脚本附加到正在单击的游戏对象

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

因此,您的基类可能如下所示:

public class StatusTracker : MonoBehaviour {
    public virtual void Show_status(bool status){
        // Status-changing code
    }
}
然后,作为组件实际附加到游戏对象的类将继承自StatusTracker,并具有以下形式:

public class SpecializedStatusTracker : StatusTracker {
    public override void Show_status(bool status){
        // Alternative status-changing code
    }
}
注意:如果您的类实现的Show_status与泛型Show_status不同,您只需要重写Show_status,否则,您甚至不需要在子类中定义该方法

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


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

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

如果我现在尝试的方式不可能做到这一点,那将是很有帮助的 提到解决该场景的其他一些简单方法

这可以通过一个接口轻松完成

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

您的10个ScriptsImplement可在每个脚本中单击:

Script1调用了ObjectToClick1

Script2称为ObjectToClick2

Script3称为ObjectToClick3

现在,对于单击部分和检测单击的对象:

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;
                }
            }
        }
    }
}

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

按名称访问游戏对象的速度很慢。hit.transform.name速度较慢,每次调用时都会分配内存。按字符串名称获取组件GetComponentString也很慢

如果我现在尝试的方式不可能做到这一点,那将是很有帮助的 提到解决该场景的其他一些简单方法

这可以通过一个接口轻松完成

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

您的10个ScriptsImplement可在每个脚本中单击:

Script1调用了ObjectToClick1

Script2称为ObjectToClick2

Script3称为ObjectToClick3

现在,对于单击部分和检测单击的对象:

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;
                }
            }
        }
    }
}

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

GetComponent有一个为您执行施法的表单,即myGameObject.GetComponentGetComponent有一个为您执行施法的表单,即myGameObject.GetComponent在玩家单击游戏对象之前,CustomClass是未知的。我们可以将每一个可能的类存储在某个地方,并检查它们。但是我正在为这个问题寻找一个更简单的解决方案。然后这就归结为项目中的设计/架构问题。你真的需要10个完全唯一的类,每个对象一个吗?看起来它们至少都有相同的Show_状态,所以您可以将相同的特性组合到父类中。然后将组件强制转换为父类,然后根据状态或任何其他条件,将其强制转换为子唯一实现。如果不了解更多关于整体设计的信息,就很难说最好的策略是什么,这超出了这个问题的范围。在玩家单击游戏对象之前,CustomClass是未知的。我们可以将每一个可能的类存储在某个地方,并检查它们。但是我正在为这个问题寻找一个更简单的解决方案。然后这就归结为项目中的设计/架构问题。你真的需要10个完全唯一的类,每个对象一个吗?看起来它们至少都有相同的Show_状态,所以您可以将相同的特性组合到父类中。然后将组件强制转换为父类,然后根据状态或任何其他条件,将其强制转换为子唯一实现。如果不了解更多关于总体设计的信息,就很难说什么是最佳策略,这超出了这个问题的范围。
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;
                }
            }
        }
    }
}