告诉另一个GameObject做某事(Unity2D)?

时间:2014-07-13 16:03:23

标签: unity3d gameobject

我有一个简单的触摸/鼠标点击脚本附加到GameObject作为一种"主脚本"即GameObject是不可见的,除了在游戏运行时持有此Touch脚本时,它不会做任何事情。

如何告诉在运行时生成的其他命名游戏对象执行以下操作:触摸/点击此主脚本时突出显示?

突出显示的脚本似乎是:renderer.material.color = colorRed;

但我不确定如何告诉点击的GameObject从主脚本中突出显示。

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

3 个答案:

答案 0 :(得分: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“经理”的问题

我会做两种选择之一。 之一:

// 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";

OR

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))

解决:

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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

您可以通过实现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();
    }
}

所以说你有几个不同的选择,你希望他们在选择时做不同的事情。这是你这样做的方式。您的一些可选择组件将具有一个选择组件,而其他组件将具有另一个组件。执行选择的逻辑驻留在主脚本中,而必须执行的操作位于附加到游戏对象的特定脚本中。

您可以进一步在这些可选项中添加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;
}

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

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