Unity: error when trying to invoke an event - c#

I want to trigger an event whenever the player collides with another object, and made the event in the EventManager script, referenced it in the player script, subscribed to it the "onCollision" method but when i try to invoke it in the "OnCollisionEnter2D" method it throws me an error like i would need to subscribe it, and i cant figure out why. How could i invoke it properly? I looked in the tutorials and documentation but i dont understand what i'm doing wrong..
the error: PlayerScript.cs(42,21): error CS0070: The event 'EventManager.onCollisionDo' can only appear on the left hand side of += or -= (except when used from within the type 'EventManager')
EventManager script:
using System.Collections.Generic;
using UnityEngine;
using System;
public class EventManager : MonoBehaviour
{
public event onCollisionDo_dlg onCollisionDo;
public delegate void onCollisionDo_dlg();
}
Player script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class PlayerScript : MonoBehaviour
{
public float speed = 10;
private Rigidbody2D body;
private Vector2 Movement;
[SerializeField]
private GameObject EventManager_reference; // reference to the EventManager via inspector
private EventManager EventMS; // reference to the EventManager script
void Start()
{
body = GetComponent<Rigidbody2D>();
EventMS = EventManager_reference.GetComponent<EventManager>();
EventMS.onCollisionDo += onCollision;
}
void Update()
{
Movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
}
private void FixedUpdate()
{
body.MovePosition((Vector2)transform.position + (Movement * speed * Time.deltaTime));
}
private void onCollision() // Method to execute when event triggered
{
print("it collided");
}
private void OnCollisionEnter2D(Collision2D temp)
{
EventMS.onCollisionDo?.Invoke(); // Here is the problem
}
}

Reason behind the issue
The error appeared due to having the event invoked outside the class it was in.
More info: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/event
Potential solution
If you want to be able to invoke your delegate outside the EventManager class, remove the event keyword or add a public method that would allow to invoke the event using an another way.
Extra note
In this case you can use a built in delegate called Action instead of making a custom one.

Related

Unity Console says "type or namespace definition, or end of file expected unity"

I'm making a VR test and I've run into a problem and am not sure what to do. Unity keeps saying "type or namespace definition, or end of file expected unity" I am using someone else's code but I am following the tutorial. Here is my code
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VrRig : MonoBehaviour { }
public Transform headConstraint;
public Vector3 headBodyOffset;
{
// Start is called before the first frame update
void Start()
{
headBodyOffset = transform.position - headConstraint.position;
}
// Update is called once per frame
void Update()
{
transform.position = headConstraint.position + headBodyOffset;
transform.forward = Vector3.ProjectOnPlane(headConstraint.up,Vector3.up).normalized;
}
}
you are creating an empty class by having the curly brackets open and closed right after the class declaration. after you declare a code block with class members but never assign it to anything. If you put an opening curly bracket right after the class declaration and close it after all your members, it should work.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VrRig : MonoBehaviour
{
public Transform headConstraint;
public Vector3 headBodyOffset;
// Start is called before the first frame update
void Start()
{
headBodyOffset = transform.position - headConstraint.position;
}
// Update is called once per frame
void Update()
{
transform.position = headConstraint.position + headBodyOffset;
transform.forward = Vector3.ProjectOnPlane(headConstraint.up,Vector3.up).normalized;
}
}

Animation does not contain definition for 'play'

For no apparent reason Unity has started just now started showing errors in this code such as the attachment picture below.
I cannot get over this error and can't find a single explanation.
Since it seems fairly simple l think there might be some people who can give a hint.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Animation : MonoBehaviour
{
private Animation anim;
void Start()
{
anim = GetComponent<Animation>();
}
private void Update()
{
anim.Play();
}
}
Your own class is called Animation .. and no it has no such method ;)
Careful with naming your class equally to an already existing one.
You will now have to use explicitly UnityEngine.Animation everywhere
public class Animation : MonoBehaviour
{
private UnityEngine.Animation anim;
void Start()
{
anim = GetComponent<UnityEngine.Animation>();
}
private void Update()
{
anim.Play();
}
}
since otherwise the compiler will of course assume by Animation you are referring to your class itself.
In general: what is the purpose of calling Play every frame?

cannot access non static method "GetComponent" in static context, despite me not declaring the class as static

I am currently working on making a class accessible from other scripts. Below is what I have coded.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))]
// Start is called before the first frame update
public class _move
{
private float _sizex;
private float _sizey;
public _move(float sizx, float sizy....etc)
{
_sizex = sizx;
_sizey = sizy;
}
public void regularmove(float sizex, float sizey...etc)
{
GameObject _player;
_player = GameObject.GetComponent<GameObject>();
BoxCollider2D bc2d;
bc2d = _player.GetComponent <BoxCollider2D>();
bc2d.offset = new Vector2(locationx + 1, locationy);
}
}
however, when I try to compile it, it gives me an error.
cannot access non-static method"GetComponent"
on this line of code
_player = GameObject.GetComponent<GameObject>();
I do not know why this is happening because I have not declared the class as static, and do not really know the properties of GetComponent that well. Can someone tell me what is happening and how I can solve this?
Also, when I change
GameObject _player;
to
public GameObject player;
the scripts below suddenly cease to work, giving me errors like
cannot resolve symbol _player
what exactly is happening here?
Thanks in advance!
Whatever script creating the instance of the _move class (This is bad naming btw, it should be Move) should also pass its gameObject to the constructor.
// attributes here are not valid if your class is not a MonoBehaviour
public class Move
{
GameObject m_object;
public Move(GameObject obj, ...)
{
m_object = obj;
}
}
if your class is meant to be a MonoBehaviour component, then it has a GameObject member already and you can use the attributes:
[RequireComponent(typeof(BoxCollider2D),typeof(Rigidbody2D))]
// Start is called before the first frame update
public class Move : MonoBehaviour
{
void Start()
{
Debug.Log(gameObject.name);
}
}

How to use "OnClick.AddListener" on multiple GameObjects in one Frame

I'm pretty new to Unity and C# scripting.
In my scene I have four buttons. I declared them in my script as public and put the items (on type Button) via drag and drop in my inspector in unity. Depending on which button is clicked, i want my program to do something. You can see in the script below what I've done. That scripts works perfectly just like I want it to.
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Example : MonoBehaviour
{
public Button Left;
public Button Right;
public Button Starten;
public Button Zurueck;
private void Start()
{
loadRezept(0);
Right.onClick.AddListener(iterationUp);
Left.onClick.AddListener(iterationDown);
Starten.onClick.AddListener(starten);
Zurueck.onClick.AddListener(zurueck);
}
... (here are the methods "iterationUp" and so on...)
This script work perfectly. But now there is my question: how can I do the same on using gameobjects?
If I just change the type "Button" to "GameObject" I don't have the possibility to use "onClick.AddListener". I don't want a script for every single gameobject. I just want something like I posted above.
GameObject itself has no such events.
Sounds like what you are asking for is a custom UnityEvent
You can create your own component like e.g.
public class HighlightController : MonoBehaviour
{
public UnityEvent OnHighlight;
// Somewhere Invoke the event e.g.
public void SetHighlighted()
{
OnHighlight.Invoke();
}
}
where you can add listeners now either via code or via the Inspector (just like the onClicked).
So put this on your GameObjects and then e.g. have fields like
[SerializeField] private HighlightController highlight;
//etc...
private void Awake()
{
highlight.OnHighlight.AddListener(HandleHighlight);
//etc...
}
private void HandleHighlight ()
{
...
}
// Make sure to cleanup listeners when not needed anymore
private void OnDestroy()
{
highlight.OnHighlight.RemoveListener(HandleHighlight);
//etc...
}
Or yes as mentioned as simple event could do the same without the serialization:
public class HighlightController : MonoBehaviour
{
public event Action OnHighlight;
public void SetHighlighted ()
{
OnHighlight?.Invoke();
}
}
and do
private void Awake()
{
highlight.OnHighlight += HandleHighlight;
}
private void OnDestroy ()
{
highlight.OnHighlight -= HandleHighlight;
}

Unity 3d script adding functions as trigger on Inspector window

I have defined three functions (OnReticleEnter(),Exit() and hover()) in the script and attached with a game object:
using UnityEngine;
using System.Collections;
using TMPro;
public class MyObject : MonoBehaviour
{
// Custom reticle events
public GameObject gOBJ;
void OnReticleEnter()
{
gOBJ.SetActive(true);
}
void OnReticleExit()
{
gOBJ.SetActive(false);
}
void OnReticleHover()
{
gOBJ.SetActive(true);
}
}
My problem is I want these functions in the inspector window so that I can define multiple actions like event trigger's pointer enter.
Is there any way I can make these functions available as event trigger on inspector window?

Categories

Resources