Interacting with one objects activates other objects with similar scripts.
Some context here is that I'm trying to allow the player to interact with an object using an Event System and Raycast. About three different colored cubes are present within the scene and I want each individual cube to return its color in the console when the player interacts with them. The problem is when the player interacts with one cube and gets their color, they also get the color from the other cubes with similar scripts as well as repeats them. I know this is due to each cube having the same script, but I don't know how each script can be separated so they all don't print their color at once. Here is my cube script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cubeScript : MonoBehaviour
{
public string color;
void Start()
{
eventHandler.current.onObjectInteract += onCubeInteract;
}
void onCubeInteract() {
switch(color) {
case "Blue":
Debug.Log("The color is blue.");
break;
case "Red":
Debug.Log("The color is red.");
break;
case "White":
Debug.Log("The color is white.");
break;
default:
Debug.Log("No color.");
break;
}
}
}
Here is my Raycast camera script:
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class playerInteract : MonoBehaviour
{
private Camera camOrigin;
public float rayDist = 100.0f;
void Start()
{
camOrigin = Camera.main;
}
void Update() {
RaycastHit hit;
if (Input.GetKey(KeyCode.E)) {
if (Physics.Raycast(camOrigin.transform.position, camOrigin.transform.forward, out hit, rayDist)) {
if (hit.transform.tag == "Interactable") {
eventHandler.current.objectInteracted();
}
}
}
}
}
And here is my Event Handler script:
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
public class eventHandler : MonoBehaviour
{
public static eventHandler current; // Declare event handler
void Awake()
{
current = this; // Assign current.
}
// Where all events are declared.
public event Action onObjectInteract;
// Where all events are invoked.
public void objectInteracted() {
if (onObjectInteract != null) { // Check if event is null before invoking it.
onObjectInteract();
}
}
}
Thank you in advance, for taking the time to read.
Answer by Hellium · Jul 27, 2021 at 04:33 PM
Why making things so complicated??
public interface IInteractable
{
void Interact();
}
// ----
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeScript : MonoBehaviour, IInteractable
{
public string color;
public void Interact()
{
switch(color) {
case "Blue":
Debug.Log("The color is blue.");
break;
case "Red":
Debug.Log("The color is red.");
break;
case "White":
Debug.Log("The color is white.");
break;
default:
Debug.Log("No color.");
break;
}
}
}
// ----
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class PlayerInteract : MonoBehaviour
{
private Camera camOrigin;
public float rayDist = 100.0f;
void Start()
{
camOrigin = Camera.main;
}
void Update() {
RaycastHit hit;
if (Input.GetKey(KeyCode.E)) {
if (Physics.Raycast(camOrigin.transform.position, camOrigin.transform.forward, out hit, rayDist)) {
if (hit.transform.TryGetComponent(out IInteractable interactable)) {
interactable.Interact();
}
}
}
}
}
But if you really want to go the complicated way:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeScript : MonoBehaviour
{
public string color;
void Start()
{
EventHandler.current.onObjectInteract += OnCubeInteract;
}
void OnCubeInteract(GameObject go) {
if(go != gameObject)
return;
switch(color) {
case "Blue":
Debug.Log("The color is blue.");
break;
case "Red":
Debug.Log("The color is red.");
break;
case "White":
Debug.Log("The color is white.");
break;
default:
Debug.Log("No color.");
break;
}
}
}
// ----
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class PlayerInteract : MonoBehaviour
{
private Camera camOrigin;
public float rayDist = 100.0f;
void Start()
{
camOrigin = Camera.main;
}
void Update() {
RaycastHit hit;
if (Input.GetKey(KeyCode.E)) {
if (Physics.Raycast(camOrigin.transform.position, camOrigin.transform.forward, out hit, rayDist)) {
if (hit.transform.tag == "Interactable") {
EventHandler.current.objectInteracted(hit.transform.gameObject);
}
}
}
}
}
// ----
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
public class EventHandler : MonoBehaviour
{
public static EventHandler current; // Declare event handler
void Awake()
{
current = this; // Assign current.
}
// Where all events are declared.
public event Action<GameObject> onObjectInteract;
// Where all events are invoked.
public void objectInteracted(GameObject go) {
if (onObjectInteract != null) { // Check if event is null before invoking it.
onObjectInteract(go);
}
}
}
I saw, and I tested. And I got what I wanted. Thank you, kind stranger.
Things were so complicated because I didn't know what Interfaces were. I was trying to use an Event System for player interaction, and I found that it is better suited for other things. I am familiar with interfaces, and it turned that it was best for what I was trying to do.
Your answer
