【问题标题】:Telling another GameObject to do something (Unity2D)?告诉另一个游戏对象做某事(Unity2D)?
【发布时间】:2014-07-13 16:03:22
【问题描述】:

我有一个简单的触摸/鼠标单击脚本作为“主脚本”附加到游戏对象,即游戏对象是不可见的,除了在游戏运行时按住这个触摸脚本之外什么都不做。

我如何告诉在运行时生成的其他命名游戏对象做一些事情,例如从此主脚本中触摸/单击时突出显示?

高亮的脚本好像是:renderer.material.color= colorRed;

但我不确定如何告诉被点击的游戏对象从主脚本中突出显示。

请帮忙! (我用 C# 编程) 谢谢!

【问题讨论】:

    标签: unity3d gameobject


    【解决方案1】:

    好的,所以如果你不在 GUI 中做,你会想要使用光线投射。查看Unity Ray Casting,然后使用

    hit.transform.gameObject.renderer.material.color = red;
    

    你可以有一个这样的开关:

    if (hit.transform.gameObject.CompareTag("tag")) {
        // turn to red;
    } else {
        // turn to white;
    }
    

    根据您的操作使用ScreenPointToRayScreenPointToWorld

    对于触摸,应如下所示:

    void Update () {
        foreach (Touch touch in Input.touches)
        {
            Ray ray = Camera.main.ScreenPointToRay(touch.position);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 1000.0f))
            {
                if (hit.collider.gameObject.CompareTag("tag"))
                {
                    hit.collider.gameObject.renderer.material.color = red;
                }
            }
        }
        // You can also add in a "go back" feature in the update but this will "go back" then when the touch ends or moves off
        // Also not so good to search for Objects in the update function but that's at your discretion.
        GameObject[] gObjs = GameObject.FindGameObjectsWithTag("tag");
        foreach (GameObject go in gObjs) {
            go.renderer.material.color = white;
        }
    }
    

    回答您关于 ping 'manager' 的问题

    我会选择两种选择之一。 要么:

    // Drop the object containing YourManager into the box in the inspector where it says "manage"
    
    public YourManager manage;
    
    // In the update and in the Ray Cast function (right next to your color change line):
    manager.yourCall ();
    // and
    manager.yourString = "cool";
    

    private YourManager manage;
    
    void Awake () {
        manager = GameObject.FindObjectWithTag("manager").GetComponent<YourManager> ();
    }
    
    // In the update and in the Ray Cast function (right next to your color change line):
    
    // In your manager file have "public bool selected;" at the top so you can access that bool from this file like:
    manager.selected = true;
    

    我在另一个答案HERE 中详细说明了这一点

    对于鼠标点击,我会查看他们存储的 MonoDevelop 函数,例如:

    // This file would be on the game object in the scene
    // When the mouse is hovering the GameObject
    void OnMouseEnter () {
        selected = true;
        renderer.material.color = red;
    }
    
    // When the mouse moved out
    void OnMouseExit () {
        selected = false;
        renderer.material.color = white;
    }
    
    // Or you can use the same system as above with the:
    Input.GetMouseButtonDown(0))
    

    分辨率:

    在您的管理器文件中使用布尔值 true 已选中,false 未选中。让您实例化的所有对象都有一个标签,使用从主文件到游戏对象的光线投射。当它是带有该标签的游戏​​对象时,交换颜色并从主文件中删除布尔值。从主文件内部进行可能更好。 (一切都取决于你在做什么)

    【讨论】:

    • 问题有标签而不是答案
    【解决方案2】:

    如果您知道运行时 GameObject 的名称,您可以使用 GameObject.Find("") 并将其存储在 GameObject 变量中。然后,您可以将该游戏对象的渲染器设置为您喜欢的任何内容(假设渲染器链接到该游戏对象)。

    【讨论】:

    • 呃,你真的不想使用.Find。 Rahin 对缓存的看法是正确的,但如果你正在做一个“开关”选择开关,带有回调或任何对经理的回调,并且 GameObjects 是实例化的,那么你每次都将使用它来进行搜索你实例化一些东西。 Unity 说“出于性能原因,建议不要在每一帧都使用此功能......”然后在这里谈论缓存:GameObject.Find API Reference
    【解决方案3】:

    最明显的方法是使用预制件和图层或标签。 您可以在预制件中添加标签(例如“可选”)或将预制件移动到某个“可选”层,然后围绕此编写代码,知道所有可选项目都在该层上/具有此标签。

    执行此操作的另一种方法(在我看来也是一种更好的方法)是实现您的自定义“可选”组件。如果您已找到该组件,您将在单击的项目上搜索此组件,然后执行选择。这种方式更好,因为您可以在此组件中添加一些额外的选择逻辑,否则这些逻辑将驻留在您的选择主脚本中(在您添加几个可选择项后显示脚本的大小)。

    你可以通过实现一个 SelectableItem 脚本(名称是任意的)和它的几个派生来做到这一点:

    public class SelectableItem : MonoBehavior {
    
        public virtual void OnSelected() {
            renderer.material.color = red;  
        }
    }
    
    public class SpecificSelectable : SelectableItem {
    
        public override void OnSelected() {
            //You can do whatever you want in here
            renderer.material.color = green;
        }
    }
    
    //Adding new selectables is easy and doesn't require adding more code to your master script.
    public class AnotherSpecificSelectable : SelectableItem {
    
        public override void OnSelected() {
            renderer.material.color = yellow;
        }
    }
    

    在你的主脚本中:

    // Somewhere in your master selection script
    // These values are arbitrary and this whole mask thing is optional, but would improve your performance when you click around a lot.
    var selectablesLayer = 8;
    var selectablesMask = 1 << selectablesLayer;
    
    //Use layers and layer masks to only raycast agains selectable objects.
    //And avoid unnecessary GetComponent() calls.
    if (Physics.Raycast(ray, out hit, 1000.0f, selectablesMask))
    {
        var selectable = hit.collider.gameObject.GetComponent<SelectableItem>();
        if (selectable) {
            // This one would turn item red or green or yellow depending on which type of SelectableItem this is (which is controlled by which component this GameObject has)
            // This is called polymorphic dispatch and is one of the reasons we love Object Oriented design so much.
            selectable.OnSelected();
        }
    }
    

    假设您有几个不同的可选择项,并且您希望它们在选择时执行不同的操作。这就是你这样做的方式。您的一些可选择项将具有选择组件之一,而其他选项将具有另一个。执行选择的逻辑位于主脚本中,而必须执行的操作位于附加到游戏对象的特定脚本中。

    您可以更进一步,在这些 Selectables 中添加 OnUnselect() 操作:

    public class SelectableItem : MonoBehaviour {
        public virtual void OnSelected() {
            renderer.material.color = red;
        }
    
        public virtual void OnUnselected() {
            renderer.material.color = white;
        }
    }
    

    然后甚至做这样的事情:

    //In your master script:
    private SelectableItem currentSelection;
    
    var selectable = hit.collider.gameObject.GetComponent<SelectableItem>();
    if (selectable) {
        if (currentSelection) currentSelection.OnUnselected();
        selectable.OnSelected();
        CurrentSelection = selectable;
    }
    

    我们刚刚添加了取消选择逻辑。

    免责声明:这些只是一堆 sn-ps。如果您只是复制并粘贴它们,它们可能不会立即起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多