I am curious if this is possible.
Basically I don’t want to define physics methods on each game object with collider directly.
I would rather have a global physics manager where I will pick all of my game objects with colliders and I will define their behavior there.
Sure, you can do it either way by having a script on the GO register itself with the “physics manager” (preferred) or have the “physics manager” know about all the collider GOs (not preferred as it the manager shouldn’t know about all the colliders).
The following code just uses UnityEvents on a GO and allows you to register things to be called. Whilst this isn’t what you want exactly, it should give you an idea of how you can set it up. In your case you’d want the script when it becomes active/inactive to register/register itself with your central physics manager for all collision/trigger events (or whatever you want).
I’m not sure doing it all centrally is better but it’s totally your choice. Using UnityEvents means you can visually assign the callback in the inspector but also you don’t need to use even this, you can just call the physics manager directly.
using System;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// Exposes 2D physics 'OnCollisionXXX2D' and `OnTriggerXXX2D' callbacks as events.
/// </summary>
public class PhysicsEvents : MonoBehaviour
{
[Serializable]
public class CollisionEnterEvent : UnityEvent<Collision2D> { }
[Serializable]
public class CollisionStayEvent : UnityEvent<Collision2D> { }
[Serializable]
public class CollisionExitEvent : UnityEvent<Collision2D> { }
[Serializable]
public class TriggerEnterEvent : UnityEvent<Collider2D> { }
[Serializable]
public class TriggerStayEvent : UnityEvent<Collider2D> { }
[Serializable]
public class TriggerExitEvent : UnityEvent<Collider2D> { }
[SerializeField]
private CollisionEnterEvent m_OnCollisionEnter = new CollisionEnterEvent ();
[SerializeField]
private CollisionStayEvent m_OnCollisionStay = new CollisionStayEvent ();
[SerializeField]
private CollisionExitEvent m_OnCollisionExit = new CollisionExitEvent ();
[SerializeField]
private TriggerEnterEvent m_OnTriggerEnter = new TriggerEnterEvent ();
[SerializeField]
private TriggerStayEvent m_OnTriggerStay = new TriggerStayEvent ();
[SerializeField]
private TriggerExitEvent m_OnTriggerExit = new TriggerExitEvent ();
public CollisionEnterEvent OnCollisionEnterEvent
{
get { return m_OnCollisionEnter; }
set { m_OnCollisionEnter = value; }
}
public CollisionStayEvent OnCollisionStayEvent
{
get { return m_OnCollisionStay; }
set { m_OnCollisionStay = value; }
}
public CollisionExitEvent OnCollisionExitEvent
{
get { return m_OnCollisionExit; }
set { m_OnCollisionExit = value; }
}
public TriggerEnterEvent OnTriggerEnterEvent
{
get { return m_OnTriggerEnter; }
set { m_OnTriggerEnter = value; }
}
public TriggerStayEvent OnTriggerStayEvent
{
get { return m_OnTriggerStay; }
set { m_OnTriggerStay = value; }
}
public TriggerExitEvent OnTriggerExitEvent
{
get { return m_OnTriggerExit; }
set { m_OnTriggerExit = value; }
}
void OnCollisionEnter2D (Collision2D col)
{
m_OnCollisionEnter.Invoke (col);
}
void OnCollisionStay2D (Collision2D col)
{
m_OnCollisionStay.Invoke (col);
}
void OnCollisionExit2D (Collision2D col)
{
m_OnCollisionExit.Invoke (col);
}
void OnTriggerEnter2D (Collider2D col)
{
m_OnTriggerEnter.Invoke (col);
}
void OnTriggerStay2D (Collider2D col)
{
m_OnTriggerStay.Invoke (col);
}
void OnTriggerExit2D (Collider2D col)
{
m_OnTriggerExit.Invoke (col);
}
}
Thanks Melv this is cool but it looks like I still need to touch the gameobjects with colliders and adding your script on them.
What I would like is to provide only gameobject or collider reference to PhysicManager (by drag and drop inside inspector), and inside PhysicManager, I would like to define physics events for each important colider (or gameobject with colider)
And I dont know if this is possible.
Basically I would like to have a centralized solution for all of my physics, without any other code on gameobjecs with colliders.
It isn’t possible directly on colliders as they don’t expose events you can hook into, they explicitly invoke the script callbacks OnCollision/OnTrigger.
That said, the UnityEvent code posted does something similar in that it exposes a public event which your physics manager can see and hook into. Instead of Collider. += xxx you have ColliderEventScript..AddListener(xxx) i.e. Unity - Scripting API: Events.UnityEvent.AddListener
In other words, instead of dragging the colliders, you’ll be dragging a reference to the event-script. You can then conifigure it however you like. Same thing but not on the colliders and it isn’t hard to add a script. You also don’t need to add it to every collider, just add it to the GO that has the Rigidbody2D on it. All collider contacts happen on the attached Rigidbody2D too.
I would say however that you don’t want a single physics manager to have to somehow know about all colliders. You’d want colliders to hook into the physics manager and pass its callback info to it.