C# UnityEvents - Override - c#

I had been searching so much to solve my problem but I found nothing.
So, what is my problem?
I have a class that extends from UnityEvent and it has 2 virtual methods and it has public identifier in another file that should call those methods. But when I put my script in inspector nothing happens (except root virtual methods).
The class:
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
namespace Namespace {
[System.Serializable]
public class SomeClass : UnityEvent {
public virtual void OnSomething(GameObject objectSender, GameObject objectAction) {
}
public virtual void OnSomethingElse(GameObject objectSender, GameObject objectAction) {
}
}
}
I overrided those methods in a file and but in variable "script" shown below but they are not overrided.
And using of SomeClass:
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
namespace Namespace {
public class ActionListener : MonoBehaviour {
public SomeClass script;
// When I lose last hope
// private void Start() {
// script.Invoke();
//}
public void OnHover(GameObject sender, GameObject action) {
script.OnHoverListener(sender, action);
}
public void OnClick(GameObject sender, GameObject action) {
script.OnClickListener(sender, action);
}
}
}

I have solved this problem using MonoBehaviour instead UnityEvent.
And not it looks like this
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
namespace Namespace {
public class SomeClass : MonoBehaviour {
public virtual void OnSomething(GameObject objectSender, GameObject objectAction) {
}
public virtual void OnSomethingElse(GameObject objectSender, GameObject objectAction) {
}
}
}
And in use
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
namespace Namespace {
public class ActionListener : MonoBehaviour {
public SomeClass script;
public void OnHover(GameObject sender, GameObject action) {
script.OnSomething(sender, action);
}
public void OnClick(GameObject sender, GameObject action) {
script.OnSomethingElse(sender, action);
}
}
}

Related

I want to Go to another Scene after dialogue ends

I'm making a 2D game and want to jump from a dialogue scene that is a tutorial for the beginning of the game to a scene where the game starts but I don't know how to achieve that after the dialogue ends. here is the entire script for the scene ( dialogue manager, Dialogue, and Dialogue trigger).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class DialogueManager : MonoBehaviour
{
public TextMeshProUGUI nameText;
public TextMeshProUGUI dialogueText;
private Queue<string> sentences;
void Start()
{
sentences = new Queue<string>();
}
public void StartDialogue(Dialogue dialogue)
{
nameText.text = dialogue.name;
sentences.Clear();
foreach (string sentence in dialogue.sentences)
{
sentences.Enqueue(sentence);
}
DisplayNextSentence();
}
public void DisplayNextSentence()
{
if (sentences.Count == 0)
{
EndDialogue();
return;
}
string sentence = sentences.Dequeue();
dialogueText.text = sentence;
}
void EndDialogue()
{
Debug.Log("End of conversation.");
}
}
And this is the Dialogue Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Dialogue
{
public string name;
[TextArea(3, 10)]
public string[] sentences;
}
And this is the Dialogue Trigger:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour
{
public Dialogue dialogue;
public void TriggerDialogue()
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue);
}
}
Use SceneManager.LoadScene in your EndDialogue() method
void EndDialogue()
{
// load new scene here
Debug.Log("End of conversation.");
}

Implementing Factory Method design pattern in Unity

i have the following code:
Product code -
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Guns : MonoBehaviour //product
{
public abstract void shoot();
public GameObject CreateBullet(GameObject bullet)
{
return Instantiate(bullet, transform.position, Quaternion.identity);
}
public void ShootBullet(GameObject bullet, Vector3 direction)
{
bullet.transform.Translate(direction * Time.deltaTime);
}
}
Concrete Product Code 1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class M16 : Guns //ConcreteProduct
{
[SerializeField] GameObject m16bullet;
Vector3 m16bulletdirection = new Vector3(5, 0, 0);
public override void shoot()
{
CreateBullet(m16bullet);
ShootBullet(m16bullet, m16bulletdirection);
}
}
Concrete Product Code 2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Uzi : Guns //ConcreteProduct
{
[SerializeField] GameObject uzibullet;
Vector3 uzibulletdirection = new Vector3(10, 0, 0);
public override void shoot()
{
CreateBullet(uzibullet);
ShootBullet(uzibullet, uzibulletdirection);
}
}
Creator Code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class GunCreator : MonoBehaviour //Creator
{
public abstract Guns GunFactory();
}
Concrete Creator Code 1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class M16Creator : GunCreator // ConcreteCreator
{
public override Guns GunFactory()
{
return new M16();
}
}
Concrete Creator Code 2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UziCreator : GunCreator // ConcreteCreator
{
public override Guns GunFactory()
{
return new Uzi();
}
}
and a client code, which currently do nothing as I dont know how to make a gun using this method. So How do all of this help me create new gun prefab with the relevant code on them?
Besides, as far as i understand, every new gun will have to have a NewGunCreator class that derives from GunCreator and a NewGun class that derives from Guns. wouldnt it be easier to leave out the creator classes?
cheers!

Dictionary not read when using GetComponent<>() in Unity

I have three scripts inside GameObjects strucured as following:
GameObjectA
└ Script1
GameObjectB
└ Script2
└ Script3
Script3 has a Dictionary I need to recall in Script2:
public void SomeMethod()
{
Dictionary<string, int> someDictionary;
someDictionary = gameObject.GetComponent<Script3>().myDictionary;
//other stuff
}
If I call the method in Script2 in its Start method, it gets called and normally, and the Dictionary is read without problems.
However, during code execution, I'll sometimes need to call Script2 from Script1:
Public GameObject GameObjectB;
GameObjectB.GetComponent<Script2>().SomeMethod();
and, if I do so, when stepping through code during execution I realize the Dictionary SomeDictionary is empty.
Is this normal? I can give more information or the real snippets if needed, I find this behavior weird and I don't know if it acts regularly.
Edit: real codes below.
Script1, PauseMenu:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PauseMenu : MonoBehaviour
{
public GameObject tracksMenuContent;
public void TracksList()
{
tracksMenuContent.GetComponent<PopulateGrid>().Populate();
}
}
Script2, PopulateGrid:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PopulateGrid : MonoBehaviour
{
[SerializeField] private TileDescr _prefab;
public static PopulateGrid instance;
private void Awake()
{
Populate();
}
public void Populate()
{
Dictionary<string, TileSupply> tilesList;
tilesList = gameObject.GetComponent<TileDB>().tiles30;
TileDescr newObj; // Create GameObject instance
foreach (KeyValuePair<string, TileSupply> tile in tilesList)
{
Sprite tileSprite = Resources.Load<Sprite>("Tiles/tile" + tile.Key);
string tileText = "[" + tile.Key + "] " + tile.Value.available + "/" + tile.Value.total;
newObj = Instantiate(_prefab, transform);
newObj.Initialize(tileSprite, tileText);
}
}
}
Script3, TileDB:
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TileSupply
{
public int available;
public int total;
}
public class TileDB : MonoBehaviour
{
public Dictionary<string, TileSupply> tiles30 = new Dictionary<string, TileSupply>();
public void Awake()
{
tiles30.Add("1", new TileSupply() { available = 1, total = 1 });
//many more elements, all pretty similar
}
}
a possible solution is to use static:
public class TileDB : MonoBehaviour
{
public static Dictionary<string, TileSupply> tiles30 = new Dictionary<string, TileSupply>();
public void Awake()
{
tiles30.Add("1", new TileSupply() { available = 1, total = 1 });
}
}
after to use the tiles30 in other script, just call the dictionary like that
TileDB.tiles30

Unity Changing the Text of an object in another script/scene

Basically, I have this Text (scoreText) which is in my "Menu" scene so hence I have initiated it in GameControlMenu.cs, however, I'm trying to change its text from my other script GameControl.cs whilst I'm currently on my "Main" scene.
GameControlMenu.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameControlMenu : MonoBehaviour
{
public static GameControlMenu instanceMenu;
public Text scoreText;
void Start()
{
//does stuff but not important to question
}
}
GameControl.cs:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class GameControl : MonoBehaviour
{
public static GameControl instance;
public int score = 5;
void Start()
{
GameControlMenu.instanceMenu.scoreText.text = "PREVIOUS SCORE: " + score;
}
}
This setup works for a couple of my other variables which I'm accessing from another file but for whatever reason this just keeps throwing me the error: NullReferenceException: Object reference not set to an instance of an object
Any help is appreciated :)
You can't do GameControlMenu.instanceMenu... since GameControlMenu is in another scene as you described, and the instance isn't in the current scene.
But what you can do is to store the value somewhere first, and let the GameControlMenu use it when the other scene loads like so:
GameControlMenu.cs
public class GameControlMenu : MonoBehaviour
{
public static GameControlMenu instanceMenu;
public static string StuffToShowOnScoreText { get; set; }
public Text scoreText;
void Awake()
{
// So that it loads the text on start
scoreText.text = StuffToShowOnScoreText;
// ...
}
}
GameControl.cs
public class GameControl : MonoBehaviour
{
public static GameControl instance;
public int score = 5;
void Start()
{
// Store the value
GameControlMenu.StuffToShowOnScoreText = "PREVIOUS SCORE: " + score;
}
}

How can I trigger OnPlayerConnected while using NetworkManager Unity?

I am using UNet and NetworkManager component. I am trying to when the player connected to server just say to me 'I am connected'. I must serialize that. I am using NetworkBehaviour, I think this may lead to failure. But how can I serialize that ?
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.Networking;
public class MultiPlayerOyunKontrol : NetworkBehaviour
{
void OnPlayerConnected(NetworkPlayer player)
{
Debug.Log("Player baglandi"+this.transform.name);
}
}
The OnPlayerConnected function is not even part of UNet API. It's part of Unity's legacy network API. This is how should have been be used:
public class MultiPlayerOyunKontrol : MonoBehaviour
{
void OnPlayerConnected(NetworkPlayer player)
{
Debug.Log("Player baglandi"+this.transform.name);
}
}
not
public class MultiPlayerOyunKontrol : NetworkBehaviour
{
void OnPlayerConnected(NetworkPlayer player)
{
Debug.Log("Player baglandi"+this.transform.name);
}
}
Basically, OnPlayerConnected has nothing to do with NetworkBehaviour so it wouldn't work unless you are using the old Unity network API which you're not.
Below is a proper way to see when client is connected or disconnected with UNet:
void Start()
{
NetworkServer.Listen(9000);
NetworkServer.RegisterHandler(MsgType.Connect, OnConnected);
NetworkServer.RegisterHandler(MsgType.Disconnect, OnDisconnected);
NetworkServer.RegisterHandler(MsgType.Error, OnError);
}
public void OnConnected(NetworkMessage netMsg)
{
Debug.Log("Client Connected");
}
public void OnDisconnected(NetworkMessage netMsg)
{
Debug.Log("Disconnected");
}
public void OnError(NetworkMessage netMsg)
{
Debug.Log("Error while connecting");
}

Categories

Resources