referencing a gameObject from a c# interface event in Unity - c#

I have an event manager in Unity which can handle events sent from scene components. The classes are all a bit abstracted from the standard Unity components. I am successfully able to fire an event from a button, and have that button's parent listen to the event (the onEventReceived you see below).
Using the Unity Debugger extension for VSCode, I can log the sender. If I type sender.gameObject and it returns a correct reference to the GameObject the sender is attached to. However, I cannot reference sender.gameObject within the OnEventReceived function itself - because it is of type ISceneComponent I suppose. How do I get a reference to the game object of the clicked sender?

I have run into your issue myself before.
The fix is quite simple.
Assuming that you created the interface ISceneComponent, add the gameObject field to your Interface
public interface ISceneComponent
{
GameObject gameObject { get; set; }
// ...
}
If the object implementing ISceneComponent also is a monobehaviour, gameObject will automatically be filled and you can reference it easily.

Related

Unity Button doesn’t accept function

I have this problem. I wrote a script with a method when interacting with which the player exits the game, but when I wanted to bind it to the button, and I realised that it didn’t work . In the OnClick() component, I attached my script, but for some reason the method is not attached.How can I attach my method?
Create an empty GameObject, attach your credits.cs to it then assign this gameobject to the OnClick(), then Credits > (Your method).
Make sure your method is public.

Is it possible to add a onClick() Event action(in GameObject dropdown) without adding new script in Unity?

I have an MRTK Slate which comes with Pressable Button to close the slate.
When the close button is pressed, the Slate is disabled but not destroyed. This is because in the Events section>Interactable script> GameObject.SetActive() is set by default as shown in fig:
I want to destroy the slate after clicking close button.
I know I can do this by making a script, attaching the slate prefab to the script(or taking the parent of the button till I get slate as parent game object), calling the function, and using GameObject.Destroy().
But I want to understand how the GameObject dropdown in the Interactable script is getting populated :
I understand that the other dropdowns like Transform, Follow me toggle, Solverhandler, etc are displayed because they are attached to the Slate.
But how does the GameObject option is available? This seems a basic thing, but I would like to be sure about how it is coded.
And if it is possible to add my new action in the Gameobject dropdown, if so, how?
I spent time looking at the scripts of Interactable and others, but I am a beginner in C# and was not able to see where is the code which does this.
Any input will help me.
No you can't because Object.Destroy is static and in UnityEvent (which Interactable.OnClick uses) via the Inspector you can only select instance methods.
You at lest need a minimal component like
public class ObjectDestroyer : MonoBehaviour
{
public void DestroyObject()
{
Destroy(this.gameObject);
}
}
or if you don't want to do it via the Inspector but automatically
public class ObjectDestroyer : MonoBehaviour
{
// store the itneractable reference
[Tootltip("If not provided uses the Interactable on this GameObject")]
[SerialzieField] private Interactable _interactable;
// Optionally provide a different target, otherwise destroys the Interactable
[Tooltip("If not provided destroys the GameObject of the Interactable")]
[SerializeField] private GameObject _targetToDestroy;
private void Awake()
{
// use get component as fallback if no Interactable was provided
if(!_interactable) _interactable = GetComponent<Interactable>();
// attach the callback on runtime (won't appear in the inspector)
_interactable.OnClick.AddListener(DestroyObject);
}
private void DestroyObject()
{
// destroy the object of the interactable if no target was provided
if(!_targetToDestroy) _targetToDestroy = _interactable.gameObject;
Destroy(_targetToDestroy);
}
}

Unity Event for drag operation

I was checking different unity events for dragging by mouse. I found IDragHandler interface provides a method OnDrag which is called when dragging operation occurred for any UI component(please correct me if I'm wrong).
I found another method 'EventTrigger.OnDrag( PointerEventData data )'
In the documentation, it is written that -
"Called by the EventSystem every time the pointer is moved during dragging"
So, I used this in my unity project prescribed by the documentation below
private void Start()
{
//Fetch the Event Trigger component from your GameObject
trigger = GetComponent<EventTrigger>();
//Create a new entry for the Event Trigger
EventTrigger.Entry entry = new EventTrigger.Entry();
//Add a Drag type event to the Event Trigger
entry.eventID = EventTriggerType.Drag;
//call the OnDragDelegate function when the Event System detects dragging
entry.callback.AddListener((data) => OnDragDelegate((PointerEventData) data));
//Add the trigger entry
trigger.triggers.Add(entry);
}
void OnDragDelegate(PointerEventData data)
{
DragToMotion();
}
so, OnDragDelegate() is supposed to be called when any dragging operation happens. I have a cube with a box collider and I drag my mouse over it. I checked in the inspector but found no method being called while dragging, the operations in DragToMotion() are not executed as well.
Please correct me on what I'm doing wrong. What could be the solution for this?
You need some sort of collider on the object as well as a Physics Raycaster on your camera. I'm fairly confident that the EventTriggers are just the inspector version of the drag/pointer interfaces.
Using either should end in the same result. Instead of accessing the event trigger and adding it in code, you can add the component then set a callback on the object similar to an onclick of a button.

Are public delegates declared in a Script sure to be of single instance if multiple GameObjects in the Scene use that Script?

Um.. First thing's first. I must let you know that I don't have core knowledge in C# scripting at all.
Alrighty, so here's my case. :)
Let's say I have a Script named AIEnemy with this snippet:
public delegate void CallbackOnEnemyAttack(int attackDamage);
public static event CallbackOnEnemyAttack OnEnemyAttack;
And I have a GameManager Script that sits on a one-and-only empty GameObject.
The case is... the AIEnemy Script is attached to lots of other GameObjects in the Scene. And I'm left wondering if the delegate AND the event that I declared in the script are of single instance or will be different per AIEnemy component attached to every GameObject.
I'm kind of a neat freak when it comes to game architecture even though I'm a noob. I'm super interested in delegates/events in Unity to design the architecture of my scripts better since I really don't like how Unity doesn't expose public instances of Interfaces in the Inspector that I have to do a "hacky" way to get around it by casting/tightly coupling my scripts together.
The idea of making an event static in Unity is so that you can easily subscribe to it without needing an instance of it. This should be used in a script with one instance and this means it must be attached to one GameObject only.
That delegate and event code should be put in a script called EventManager or somthing similar. This EventManager script is a script that is attached to one empty GameObject. Your enemy and other scripts can subscribe to this EvenetManager when they are spawned and also receive notification when there is an event.
What happens when you attach this multiple GameObjects and now it has
multiple instances?
If you trigger and event, each script you attached to a GameObject will send their own event. If this is attached to 500 enemies and you trigger event, all the 500 enemies will send an event to the subscriber.
In most cases, it is better to make these variables private and expose a function that can be used to subscribe and trigger events on them.
This has been done already. Here is a complete example of EventSystem from Unity that uses Unity's UnityEvent which is slow. Here is the ported version I made that uses delegate and should be used if possible.
Subscribing to an event:
EventManager.StartListening("Spawn", SomeOtherFunction);
Un-Subscribing to an event:
EventManager.StopListening("Spawn", SomeOtherFunction);
Triggering an event:
EventManager.TriggerEvent("Spawn");

NGUI How to know which drop zone my object is over?

I am trying to create an game board by using Unity and NGUI and everything is working ok now. I am using the DragNDrop script on my dragable object and on my fields on the board I am using UIDragDropContainer. But, is there a way I can tell my dragable object which field the object is over or attaching it self to?
I have scouted the net, but have not found an solution.
Any help is appreciated :-)
Use the UICamera.hoveredObject to get the last gameObject (with a collider) that the mouse or touch was last over.
In one of my projects I came across a same issue. What I did was inherit the NGUI's UIDragDropItem script and created a delegate to tell me about the object. I have also added the source:
public class Custom_DragDropItem : UIDragDropItem {
public delegate void DragDropDelegate(GameObject TargetObject);
public DragDropDelegate onDragDrop;
}
All you have to do is use this script instead of UIDragDropItem on your draggable items in the inspector and register to the delegate onDragDrop and it will pass you the target object on which the item is dropped.

Categories

Resources