- Home /
Avoid retyping code?
Hi, I am having a question.
Let's say i have 2 gameObject. They have Collider2D (isTrigger on) so that when player enter the collider, and press 'e' they gameObject would call a function (which I name interact() ).
Most of the script would be the same, the only different is interact() function.
What should I do to avoid retyping code?
Answer by Mr-Men · Mar 22, 2017 at 09:42 AM
There are a few ways to achieve this. I'd consider using inheritance:
Make a base script, inheriting from MonoBehaviour, with all the common methods coded in it and an abstract Interact() method. Then create a script for each gameObject, inheriting from your base script, and override the interact() method.
oh thank you, it works fine now although I have to attach both of them to the same gameobject. I thought it would be impossible since I am not truely familiar with Component structure of Unity. OOP is weird here :)
Please use the "Add Comment" button when you want to post a comment. "Answers" should answer the question. I converted your answer into a comment.
Answer by Bunny83 · Mar 22, 2017 at 10:17 AM
Inheritance is one way (as Mr-Men said), using SendMessage is another. SendMessage uses Unity's messaging system and is more suited for component based design. So you simply create two scripts. The first one has an OnTriggerStay2D method where you can check if a certain key is pressed while the player is inside that trigger. If so you simply send a message to "Interact". Another script can simply implement an "Interact" method which will be called automatically.
public class TriggerActivator : MonoBehaviour
{
public KeyCode key = KeyCode.E;
public string activationTag = "Player";
void OnTriggerStay2D(Collider2D aOther)
{
if (aOther.gameObject.CompareTag(activationTag) && Input.GetKeyDown(key))
SendMessage("OnInteract",aOther.gameObject, SendMessageOptions.DontRequireReceiver);
}
}
This script, when attached to an object in the scene will send an "OnInteract" message to other scripts on the same object. So if you attach another script like this:
public class AmmoContainer : MonoBehaviour
{
public void OnInteract(GameObject aOther)
{
Debug.Log("object '"+aOther.name+"' has interacted with this AmmoContainer at " + transform.position);
}
}
Usually the passed gameobject will be the player object since by default we check for the tag "Player".
Another way is to reverse the logic which is often the better way. So you would have the TriggerActivator on the player object and have it send a message to objects the player collides with. For this you would have to change the class slightly and of course attach it to the player instead of the actual object:
public class TriggerActivator : MonoBehaviour
{
public KeyCode key = KeyCode.E;
void OnTriggerStay2D(Collider2D aOther)
{
if (Input.GetKeyDown(key))
aOther.gameObject.SendMessage("OnInteract",gameObject, SendMessageOptions.DontRequireReceiver);
}
}
This has the advantage that you only need one instance of the TriggerActivator on the player. Every time you press the button "e" it will simply send a message to all objects that are current touching / overlapping with the player.
Instead of "messages" you could also use interfaces. Using interfaces has the advantage that you can't misspell the "message name". However it would require to use GetComponent on the target object to aquire that interface.
Example:
public interface IInteractable
{
void Interact(GameObject aOther);
}
public class TriggerActivator : MonoBehaviour
{
public KeyCode key = KeyCode.E;
void OnTriggerStay2D(Collider2D aOther)
{
if (Input.GetKeyDown(key))
{
var interactable = aOther.GetComponent<IInteratable>();
if (interactable != null)
interactable.Interact(gameObject);
}
}
}
A script on the other object can now implement that interface:
public class AmmoContainer : MonoBehaviour, IInteractable
{
public void Interact(GameObject aOther)
{
Debug.Log("object '"+aOther.name+"' has interacted with this AmmoContainer at " + transform.position);
}
}
This will automatically call the Interact method on any class that implements that interface.
Your answer
Follow this Question
Related Questions
Help In Making a SphereCast for 3D Tire! Working RayCast Script included! 0 Answers
Interacting with a button by colliding with it 1 Answer
Protected/private, KeyCode, Colliders and Large map Questions 2 Answers
How to change first person controller input when passing through a collider? 1 Answer
OnMouseDown and iPhone 1 Answer