Есть класс (1), в котором содержатся несколько приватных полей (назовем их цена, количество, цвет). Для них уже сделаны геттеры. На сцене имеются несколько UI.Text. Мне нужно, чтобы при появлении этих UI.Text, в них выводилось соответствующее значение полей класса (1). Как это сделать?
У объектов есть метод Find, который находит объект с именем name
и возвращает его. Можно воспользоваться им, как один из вариантов.
Пример
public GameObject hand;
void Example() {
hand = GameObject.Find("Hand");
hand = GameObject.Find("/Hand");
hand = GameObject.Find("/Monster/Arm/Hand");
hand = GameObject.Find("Monster/Arm/Hand");
}
где строка в методе - это путь до объекта в иерархии сцены. Слэш означает искать от корня (то есть будет произведен обход иерархии, как если бы вместо имени был указан путь).
Соответственно, при старте Start()
находите объект через Find
, и даете ему значение, взятое из метода. Что-то типа:
GameObject.Find("/Canvas/MyData/PriceText").GetComponent<Text>().text = GetPrice();
GameObject.Find("/Canvas/MyData/CountText").GetComponent<Text>().text = GetCount();
Вообще, на самом деле, скрипты на UI.Text и прочих UI, которые берут данные откуда-то с другого скрипты вам особо и не нужны. Часто делают Менеджеров (Managers), которые ответственны за некую общую сущность. Например UIManager. Делается один скрипт, который управляет отображением в UI. Он слушает события и в зависимости от них производит нужные действия.
О событиях, о слушателях и рассылках почитайте где-либо, особенно такую вещь как паттерны (шаблоны) проектирования и, в частности, паттерн "наблюдатель (Observer)". Потому что рассылка сообщений основывается именно на данном нём.
Итак, прежде всего нужен скрипт рассылки сообщений, назовём его Messenger.cs
, с помощью методов которого и работает менеджер. Его код можно взять по данной ссылке или посмотреть под спойлером:
using System;
using System.Collections.Generic;
using System.Linq;
public enum MessengerMode {
DONT_REQUIRE_LISTENER,
REQUIRE_LISTENER,
}
static internal class MessengerInternal {
readonly public static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
static public readonly MessengerMode DEFAULT_MODE = MessengerMode.REQUIRE_LISTENER;
static public void AddListener(string eventType, Delegate callback) {
MessengerInternal.OnListenerAdding(eventType, callback);
eventTable[eventType] = Delegate.Combine(eventTable[eventType], callback);
}
static public void RemoveListener(string eventType, Delegate handler) {
MessengerInternal.OnListenerRemoving(eventType, handler);
eventTable[eventType] = Delegate.Remove(eventTable[eventType], handler);
MessengerInternal.OnListenerRemoved(eventType);
}
static public T[] GetInvocationList<T>(string eventType) {
Delegate d;
if(eventTable.TryGetValue(eventType, out d)) {
if(d != null) {
return d.GetInvocationList().Cast<T>().ToArray();
} else {
throw MessengerInternal.CreateBroadcastSignatureException(eventType);
}
}
return null;
}
static public void OnListenerAdding(string eventType, Delegate listenerBeingAdded) {
if (!eventTable.ContainsKey(eventType)) {
eventTable.Add(eventType, null);
}
var d = eventTable[eventType];
if (d != null && d.GetType() != listenerBeingAdded.GetType()) {
throw new ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, d.GetType().Name, listenerBeingAdded.GetType().Name));
}
}
static public void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved) {
if (eventTable.ContainsKey(eventType)) {
var d = eventTable[eventType];
if (d == null) {
throw new ListenerException(string.Format("Attempting to remove listener with for event type {0} but current listener is null.", eventType));
} else if (d.GetType() != listenerBeingRemoved.GetType()) {
throw new ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, d.GetType().Name, listenerBeingRemoved.GetType().Name));
}
} else {
throw new ListenerException(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know about this event type.", eventType));
}
}
static public void OnListenerRemoved(string eventType) {
if (eventTable[eventType] == null) {
eventTable.Remove(eventType);
}
}
static public void OnBroadcasting(string eventType, MessengerMode mode) {
if (mode == MessengerMode.REQUIRE_LISTENER && !eventTable.ContainsKey(eventType)) {
throw new MessengerInternal.BroadcastException(string.Format("Broadcasting message {0} but no listener found.", eventType));
}
}
static public BroadcastException CreateBroadcastSignatureException(string eventType) {
return new BroadcastException(string.Format("Broadcasting message {0} but listeners have a different signature than the broadcaster.", eventType));
}
public class BroadcastException : Exception {
public BroadcastException(string msg)
: base(msg) {
}
}
public class ListenerException : Exception {
public ListenerException(string msg)
: base(msg) {
}
}
}
// No parameters
static public class Messenger {
static public void AddListener(string eventType, Action handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void AddListener<TReturn>(string eventType, Func<TReturn> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void RemoveListener(string eventType, Action handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void RemoveListener<TReturn>(string eventType, Func<TReturn> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void Broadcast(string eventType) {
Broadcast(eventType, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast<TReturn>(string eventType, Action<TReturn> returnCall) {
Broadcast(eventType, returnCall, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast(string eventType, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Action>(eventType);
foreach(var callback in invocationList)
callback.Invoke();
}
static public void Broadcast<TReturn>(string eventType, Action<TReturn> returnCall, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Func<TReturn>>(eventType);
foreach(var result in invocationList.Select(del => del.Invoke()).Cast<TReturn>()) {
returnCall.Invoke(result);
}
}
}
// One parameter
static public class Messenger<T> {
static public void AddListener(string eventType, Action<T> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void AddListener<TReturn>(string eventType, Func<T, TReturn> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void RemoveListener(string eventType, Action<T> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void RemoveListener<TReturn>(string eventType, Func<T, TReturn> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void Broadcast(string eventType, T arg1) {
Broadcast(eventType, arg1, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast<TReturn>(string eventType, T arg1, Action<TReturn> returnCall) {
Broadcast(eventType, arg1, returnCall, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast(string eventType, T arg1, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Action<T>>(eventType);
foreach(var callback in invocationList)
callback.Invoke(arg1);
}
static public void Broadcast<TReturn>(string eventType, T arg1, Action<TReturn> returnCall, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Func<T, TReturn>>(eventType);
foreach(var result in invocationList.Select(del => del.Invoke(arg1)).Cast<TReturn>()) {
returnCall.Invoke(result);
}
}
}
// Two parameters
static public class Messenger<T, U> {
static public void AddListener(string eventType, Action<T, U> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void AddListener<TReturn>(string eventType, Func<T, U, TReturn> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void RemoveListener(string eventType, Action<T, U> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void RemoveListener<TReturn>(string eventType, Func<T, U, TReturn> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void Broadcast(string eventType, T arg1, U arg2) {
Broadcast(eventType, arg1, arg2, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast<TReturn>(string eventType, T arg1, U arg2, Action<TReturn> returnCall) {
Broadcast(eventType, arg1, arg2, returnCall, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast(string eventType, T arg1, U arg2, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Action<T, U>>(eventType);
foreach(var callback in invocationList)
callback.Invoke(arg1, arg2);
}
static public void Broadcast<TReturn>(string eventType, T arg1, U arg2, Action<TReturn> returnCall, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Func<T, U, TReturn>>(eventType);
foreach(var result in invocationList.Select(del => del.Invoke(arg1, arg2)).Cast<TReturn>()) {
returnCall.Invoke(result);
}
}
}
// Three parameters
static public class Messenger<T, U, V> {
static public void AddListener(string eventType, Action<T, U, V> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void AddListener<TReturn>(string eventType, Func<T, U, V, TReturn> handler) {
MessengerInternal.AddListener(eventType, handler);
}
static public void RemoveListener(string eventType, Action<T, U, V> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void RemoveListener<TReturn>(string eventType, Func<T, U, V, TReturn> handler) {
MessengerInternal.RemoveListener(eventType, handler);
}
static public void Broadcast(string eventType, T arg1, U arg2, V arg3) {
Broadcast(eventType, arg1, arg2, arg3, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast<TReturn>(string eventType, T arg1, U arg2, V arg3, Action<TReturn> returnCall) {
Broadcast(eventType, arg1, arg2, arg3, returnCall, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast(string eventType, T arg1, U arg2, V arg3, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Action<T, U, V>>(eventType);
foreach(var callback in invocationList)
callback.Invoke(arg1, arg2, arg3);
}
static public void Broadcast<TReturn>(string eventType, T arg1, U arg2, V arg3, Action<TReturn> returnCall, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
var invocationList = MessengerInternal.GetInvocationList<Func<T, U, V, TReturn>>(eventType);
foreach(var result in invocationList.Select(del => del.Invoke(arg1, arg2, arg3)).Cast<TReturn>()) {
returnCall.Invoke(result);
}
}
}
Еще есть события в игре. Например вспомогательный скрипт GameEvent.cs
будет их в себе содержать:
public static class GameEvent {
public const string GAME_STARTED = "GAME_STARTED";
public const string ITEM_BOUGHT = "ITEM_BOUGHT";
public const string SPEED_CHANGED = "SPEED_CHANGED";
// ... и т.д.
}
В менеджере (UIManager) подписываемся на событие, в данном случае на то, что игра стартовала GAME_STARTED
и , например ITEM_BOUGHT
(когда предмет покупаем, наверняка меняется их количество?).
public class UIManager : MonoBehaviour {
[SerializeField] private Text colorLabel;
[SerializeField] private Text priceLabel;
[SerializeField] private Text countLabel;
private MyDataClass myDataClass;
void Awake() {
// подписываемся на события и указываем методы, которые будут вызваны при возникновение этого события
Messenger.AddListener(GameEvent.GAME_STARTED, OnGameStarted);
Messenger.AddListener(GameEvent.ITEM_BOUGHT, OnItemBought);
}
void OnDestroy() {
Messenger.RemoveListener(GameEvent.GAME_STARTED, OnGameStarted);
Messenger.RemoveListener(GameEvent.ITEM_BOUGHT, OnItemBought);
}
// будет вызван при получении события GAME_STARTED
private void OnGameStarted() {
myDataClass = GameObject.Find("/Canvas/MyData/MyClassObject").gameObject.GetComponent<MyClass>();
colorLabel.text = myDataClass.GetColor().ToString();
priceLabel.text = myDataClass.GetPrice().ToString();
countLabel.text = myDataClass.GetCount().ToString();
}
// будет вызван при получении события ITEM_BOUGHT
private void OnItemBought() {
countLabel.text = myDataClass.GetCount().ToString();
}
}
Скрипт вешается на пустой объект на сцене, который желательно тоже так же назвать: "UIManager". В поля скрипта (которые bv.n атрибут SerializeField
) добавить нужные объекты (в данном случае текстовые объекты UI.Text) и всё.
Теперь в любой момент, на любом нужном скрипте рассылаем сообщения. Например на каком-нибудь главном скрипте Game.cs
public class Game : MonoBehaviour {
void Start() {
// Уведомляем, что игра началась
Messenger.Broadcast(GameEvent.GAME_STARTED);
}
}
Или в каком-то другом скрипте, который ответственен за покупку предметов
public class Inventory : MonoBehaviour {
public void OnPointerDown() {
_count++;
// Уведомляем, что предмет куплен
Messenger.Broadcast(GameEvent.ITEM_BOUGHT);
}
}
Запускаем игру и радуемся...........
Так системка делается-то...
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход