Говорить другому GameObject что-то делать (Unity2D)?

У меня есть простой сценарий касания/щелчка мыши, прикрепленный к GameObject как своего рода «основной сценарий», т.е. GameObject невидим и ничего не делает, кроме как удерживает этот сценарий касания, когда игра запущена.

Как сообщить другим именованным объектам GameObject, созданным во время выполнения, что-то делать, например. выделить при прикосновении/нажатии из этого мастер-скрипта?

Скрипт для выделения выглядит так: renderer.material.color= colorRed;

Но я не уверен, как сказать, что GameObject, на который нажали, стал выделенным из основного сценария.

Пожалуйста помоги! (программирую на С#) Спасибо!


person user3699296    schedule 13.07.2014    source источник


Ответы (3)


Итак, вы захотите использовать ray cast, если вы не делаете это в графическом интерфейсе. Ознакомьтесь с Unity Ray Casting, а затем используйте

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

У вас может быть переключатель, похожий на:

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

Используйте ScreenPointToRay или ScreenPointToWorld в зависимости от того, что вы делаете.

Для касания должно выглядеть так:

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

Чтобы ответить на ваш вопрос о пинге «менеджера»

Я бы сделал один из двух вариантов. Либо:

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

Я немного детализирую это в другом из моих ответов ЗДЕСЬ

Для щелчков мышью я бы проверил функции 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 нет. Имейте теги у всех объектов, которые вы создаете, используйте приведение лучей из мастер-файла к игровому объекту. Когда это игровой объект с этим тегом, поменяйте местами цвета и извлеките логическое значение из основного файла. Вероятно, лучше сделать это внутри мастер-файла. (Все зависит от того, что вы делаете)

person iSkore    schedule 20.05.2015
comment
вопросы имеют теги, а не ответы - person Flexo; 08.02.2016

Если вы знаете, каким будет имя GameObjects во время выполнения, вы можете использовать GameObject.Find("") и сохранить его в переменной GameObject. Затем вы можете установить средство визуализации этого GameObject на все, что вам нравится (при условии, что средство визуализации связано с этим GameObject).

person Rahin    schedule 18.08.2014
comment
Эээ, вы действительно не хотите использовать .Find. Рахин прав насчет кэширования, но если вы выполняете включение-выключение выбора с обратными вызовами или чем-то еще для менеджера и с тем фактом, что игровые объекты созданы, вы будете использовать это более чем необходимо для поиска каждый раз, когда вы создаете экземпляр что-нибудь. Unity говорит: Из соображений производительности рекомендуется не использовать эту функцию в каждом кадре... а затем рассказывается о кэшировании здесь: Справочник по API GameObject.Find - person iSkore; 20.05.2015

Самый очевидный способ сделать это — использовать префабы и слои или теги. Вы можете добавить тег к своему префабу (скажем, «Выбираемый») или переместить префаб на какой-нибудь «Выбираемый» слой, а затем написать свой код вокруг этого, зная, что все выбираемые элементы находятся на этом слое/имеют этот тег.

Другой способ сделать это (и, на мой взгляд, также лучший способ) - реализовать ваш собственный компонент «Выбираемый». Вы будете искать этот компонент в выбранном элементе, а затем выполнять выбор, если вы нашли этот компонент. Этот способ лучше, потому что вы можете добавить дополнительную логику выбора в этот компонент, который в противном случае находился бы в вашем основном сценарии выбора (изобразите размер вашего сценария после того, как вы добавили пару выбираемых).

Вы можете сделать это, реализовав скрипт 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() в эти Selectables:

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

И мы только что добавили логику отмены выбора.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Это просто набор фрагментов. Если вы просто скопируете и вставите их, они, вероятно, не будут работать сразу.

person MarengoHue    schedule 08.02.2016