Да кажете на друг GameObject да направи нещо (Unity2D)?

Имам прост скрипт за докосване/щракване с мишката, прикрепен към GameObject като нещо като „Главен скрипт“, т.е. GameObject е невидим и не прави нищо, освен да задържа този скрипт за Touch, когато играта работи.

Как да кажа на други именувани GameObjects, които се генерират по време на изпълнение, да правят неща, напр. подчертаване при докосване/щракване от този главен скрипт?

Скриптът за осветяване изглежда е: renderer.material.color= colorRed;

Но не съм сигурен как да разбера GameObject, върху който е щракнато, да стане маркиран от главния скрипт.

Моля помогнете! (програмирам на C#) Благодаря!


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


Отговори (3)


Добре, така че ще искате да използвате ray cast, ако не го правите в GUI. Разгледайте 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))

Резолюция:

Използвайте bool във вашия мениджърски файл true е избрано, false не е. Нека всички обекти, които създавате, имат етикет, използвайте лъча, прехвърлен от главния файл към обекта на играта. Когато това е обектът на играта с този етикет, разменете цветовете и изтрийте bool от главния файл. Вероятно е по-добре да го направите вътрешно от главния файл. (Всичко зависи от това, което правите)

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. Рахин е прав за кеширането, но ако правите превключване за включване и изключване на избор с обратни извиквания или каквото и да е към мениджъра и с факта, че GameObjects са инстанцирани, ще използвате това повече от необходимото за търсене всеки път, когато инстанцирате нещо. 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() в тези избираеми:

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