Godot emit signal defined in another scene [duplicate] - c#

This question already has an answer here:
Godot Signal "Emitted" but not "Received"
(1 answer)
Closed 2 years ago.
I have a Signal inside a script attached to a node:
Game.tscn/Game.cs
using Godot;
public class Game : Node2D
{
[Signal]
public delegate void AddPowerUp(Powerup powerup);
}
I try to emit a signal from another class:
ExtraBall.tscn/Powerup.cs
public override void _IntegrateForces(Physics2DDirectBodyState state)
{
EmitSignal("AddPowerUp", this);
}
Then in another scene, Level.tscn, I instanced Game and ExtraBall. However, I get an error when I try to emit the signal.
E 0:00:05.828 emit_signal: Can't emit non-existing signal "AddPowerUp".
Here's how it looks like in the engine:
Game has the Signal and I attach to a function in Player:
In the Level scene, I instance Game and ExtraBall:
Shouldn't ExtraBall be able to know about the "AddPowerUp" signal since it was instanced under the same SceneTree? If not, how do I go about emitting a signal that's defined somewhere else?

I ended up doing it a different way.
I removed the Game instance from the Level scene.
Declared the signal inside ExtraBall.cs
Created an instance of Level inside Game
Connected the signal from ExtraBall to a function inside Player through code.
The scene trees are as follows:
Game (Node2D)
Player (Player.tscn)
Level (Node2D)
ExtraBall (Extraball.tscn)
Not sure if this is a good approach, but it seems to work without any issues. I posted a small "game" that shows the solution at the bottom.
Game.cs
public class Game : Node2D
{
[Signal] public delegate void LevelLoaded();
public override void _Ready()
{
PackedScene scene = ResourceLoader.Load("res://source/level/Level.tscn") as PackedScene;
AddChild(scene.Instance());
EmitSignal("LevelLoaded");
}
}
Player.cs
public class Player : KinematicBody2D
{
public override void _Ready()
{
GetNode<Node>("/root/Game").Connect("LevelLoaded", this, "OnLevelLoaded");
}
public void OnLevelLoaded()
{
GetNode<Node>("/root/Game/Level/ExtraBall").Connect("TestSignal", this, "OnTestSignal");
}
public void OnTestSignal()
{
GD.Print("YAY!");
}
}
ExtraBall.cs
public class ExtraBall : RigidBody2D
{
[Signal] public delegate void TestSignal();
public override void _IntegrateForces(Physics2DDirectBodyState state)
{
var bodies = GetCollidingBodies();
foreach (Node2D node in bodies)
{
EmitSignal("TestSignal");
}
}
}
Small project with solution: https://www.dropbox.com/s/v7zac3lripsslrz/SignalTest.zip?dl=0

Related

Building a hierarchical state machine in Unity, having trouble with virtual functions

So I've been working on a state machine for a player character in a Unity game, and thought a hierarchical system would work well. However, I'm having some trouble getting methods to traverse the inheritance chain. If someone could point out my mistake for me, I'd greatly appreciate it.
Here's my PlayerScript : Monobehavior script:
public PlayerState State;
public void Start() {
State = new StoppedState();
State.Enter(this);
}
public void Update() {
State.Update(this);
}
And here are the PlayerStates:
public class PlayerState {
public virtual PlayerState Update(PlayerScript player) {
Debug.Log("Blorp");
return null;
}
public virtual void Enter(PlayerScript player) {}
}
public class LowPriorityState : PlayerState {
public new virtual PlayerState Update(PlayerScript player) {
Debug.Log("Blop");
PlayerState newState = base.Update(player);
//Do state stuff, determine if state should change
return newState;
}
}
public class StoppedState : LowPriorityState {
public override PlayerState Update(PlayerScript player) {
Debug.Log("Blip");
PlayerState newState = base.Update(player);
//Do state stuff, determine if state should change
return newState;
}
public override void Enter(PlayerScript player) {
Debug.Log("Entered Stopped State");
}
}
The expected output after 1 frame is:
Entered Stopped State
Blip
Blop
Blorp
but instead I'm getting:
Entered Stopped State
Blorp
...which is completely baffling, because it's clearly using the overridden "Enter" method but not using the overridden "Update" method. Does anyone know what I'm doing wrong and how to fix it?
The "new" modifier is used to hide a method of the base class and create a completely new method. This way, if the variable is of type BaseClass, it will call the method in the base class, and if the variable is of type DerivedClass, it will call the method in the derived class.
So in the LowPriorityState you are creating a new method, not overriding the one from PlayerState. So your field State of type PlayerState will continue to call the method from the base class.
And then you override this new method in StoppedState, but as your field State is of type PlayerState, it continues to call the method from the base class.
So just replace the new keyword with override.

C# Virtual Method Issue

I'm currently programming a 2D Game Engine in C# using GDI+ and at the moment I'm trying to implement a component based structure.
The idea is that my GameObject class has a list of components. Each component can be completely different to the next.
I represented components by creating a Component class, which looks like this:
public class Component : BaseObject
{
/// <summary>
/// The game object this component is attached too.
/// </summary>
private GameObject gameObject = null;
/*
* Below I called the protected virtual methods from the "BaseObject" class.
* The base object class only contains these 4 protected virtual methods. Nothing else.
*/
public void Load()
{
OnLoad(this, EventArgs.Empty);
}
public void Unload()
{
OnUnload(this, EventArgs.Empty);
}
public void Update(GameTime gameTime)
{
OnUpdate(this, new UpdateEventArgs(gameTime));
}
public void Render(GraphicsEngine graphicsEngine)
{
OnRender(this, new RenderEventArgs(graphicsEngine));
}
public GameObject GameObject
{
get { return gameObject; }
set { gameObject = value; }
}
}
In my game object class, every component that is within the components list gets updated and rendered like so:
internal void Update(GameTime gameTime)
{
OnUpdate(this, new UpdateEventArgs(gameTime));
// All components being updated
components.ForEach(c => c.Update(gameTime));
}
With all of that being said, I've created a SpriteComponent class, which is meant to render a simple 2D sprite, based on the game objects position, it's overrided render method looks like this:
protected override void OnRender(object sender, RenderEventArgs e)
{
e.GraphicsEngine.DrawBitmap(bitmap, GameObject.Transform.Position);
base.OnRender(sender, e);
}
However for some reason this happens (This is the render method of the GameObject class):
internal void Render(GraphicsEngine graphicsEngine)
{
if (Enabled)
{
// Rendering a sprite component like this works fine
// Here I've created created a SpriteComponent inside the game object class to test it
if(sprite != null)
graphicsEngine.DrawBitmap(sprite.Bitmap, transform.Position);
OnRender(this, new RenderEventArgs(graphicsEngine));
// But rendering it using it's own method doesn't work
//sprite.Render(graphicsEngine);
// and this doesn't work properly either
// components.ForEach(c => c.Render(graphicsEngine));
}
}
And here is a picture of the result when I either iterate through the components list and render it, or render the sprite component by it's self:
I would look into you calling the OnRender. It is not best practice to call these event handlers. The has to be some other method you need to call which will invoke the OnRender.
Similar to OnDraw (Event handler) and Update (Invoke method)
I think you did override wrong method, As I see you have override the OnRender
While probably you calling Render method.
Try to make the Render method virtual and override it in child classes

Check the previous loaded scene

I'm making a game in Unity3D with C# for mobile devices and can't figure out how to check which scene was loaded before the current scene. I need to check this to change the spawn point from the player gameobject. First I added a simple script to my buttons (loadnextscene and loadprevscene)
public class SwitchScene : MonoBehaviour {
public int sceneNumber;
public void LoadScene(int sceneNumber) {
Application.LoadLevel(sceneNumber);
}
}
A second scripts handles the touch input from the user and changes the movement of the player object.
So, for example: If the player clicks on the "load previous scene" button in the second Level to switch to the first level again, I want to set the spawn point of the player object on the right half on the screen and not on the left side like when the game was started the first time.
I tried it with Singleton and PlayerPrefs, but it did not work out.
You need to save the scene number to some variable before LoadScene, then check it after the scene loaded.
The only problem is that this variable will be destroyed after the new scene is loaded. So, to prevent it, you can use DontDestroyOnLoad. Here is what you do:
First, create a new empty game object, and attach the following script to it:
using UnityEngine;
using System.Collections;
public class Indestructable : MonoBehaviour {
public static Indestructable instance = null;
// For sake of example, assume -1 indicates first scene
public int prevScene = -1;
void Awake() {
// If we don't have an instance set - set it now
if(!instance )
instance = this;
// Otherwise, its a double, we dont need it - destroy
else {
Destroy(this.gameObject) ;
return;
}
DontDestroyOnLoad(this.gameObject) ;
}
}
And now, before you load, save the scene number in the Indestructable object:
public class SwitchScene : MonoBehaviour {
public int sceneNumber;
public void LoadScene(int sceneNumber) {
Indestructable.instance.prevScene = Application.loadedLevel;
Application.LoadLevel(sceneNumber);
}
}
And last, in your scene Start() check Indestructable.instance.prevScene and do your magic accordingly.
More info here:
http://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html
*I did not compile the code, so there may be some errors, but this is the general idea.
Why did the PlayerPrefs approach did not work?
I think its the easiest way to solve your problem.
public class FirstLevel : MonoBehaviour {
public void Start() {
PlayerPrefs.SetString("SceneNumber", SceneManager.GetActiveScene().name);
}
}
And then in the second scene simply read the saved PlayerPrefs
public class SecondLevel : MonoBehaviour {
string PrevScene;
public void Start() {
PrevScene = PlayerPrefs.GetString("SceneNumber");
// if there will be a third scene, etc.
PlayerPrefs.SetString("SceneNumber", SceneManager.GetActiveScene().name);
}
public void GoToPrevScene() {
SceneManager.LoadScene(PrevScene);
}
}
You can solve this problem with a single static member variable in the SwitchScene class. No need for the singleton pattern or DontDestroyOnLoad.
public class SwitchScene : MonoBehaviour
{
public int sceneNumber;
private static int previousScene;
private int oldPreviousScene;
void Start()
{
oldPreviousScene = previousScene;
previousScene = sceneNumber;
}
public void HandleLoadPrevButtonClick()
{
SceneManager.LoadScene(oldPreviousScene);
}
}

how do I extend a class from another script in c# Unity

I'm trying to extend a base class on my player object.
player has damage script that looks like this
using UnityEngine;
using System.Collections;
public class Damage : MonoBehaviour
{
public int health = 100;
public virtual void ReceiveDamage(int damageAmount)
{
Debug.Log ("Original");
}
}
And then the same player has another script like this :
using UnityEngine;
using System.Collections;
public class playerDamage : Damage
{
public override void ReceiveDamage(int damageAmount)
{
Debug.Log ("Extended");
}
}
But when I call the script from a 3rd scrip on another object like this:
var damageScript = collision.gameObject.GetComponent<Damage>();
if( damageScript)
{
damageScript.ReceiveDamage(damageAmount);
}
the only response to the log is "Original"
Shouldn't the child be called and "Extended" written to the log?
There are several ways to do this. The easiest one is to SendMessage.
collision.gameObject.SendMessage("ReceiveDamage", damageAmount);
Whatever implementation of ReceivedDamage that the collision GameObject has, that will be the one that is called. This is awesome because you don't need to specify the type yourself nor use GetComponent.
Important Extra Information
In any implementation that you choose the key step is to make sure that the right script is attached to the collision.gameObject. If you attach both scripts then you are playing with fire.
To avoid playing with fire please make Damage an abstract class.
public abstract class Damage : MonoBehaviour
{
public int health = 100;
public virtual void ReceiveDamage(int damageAmount)
{
Debug.Log ("Original");
}
}
Abstract will give you the same functionality you want, except that Unity3d won't let you attach Damage to the GameObjects, which is good to avoid mistakes. You will always have the option to have the original ReceiveDamage and the choice to override it on future classes that inherit from Damage, like this:
public class Example : Damage
{
// This one still has ReceiveDamage but it happens in the base class.
}
or
public class PlayerDamage : Damage
{
public override void ReceiveDamage(int damageAmount)
{
Debug.Log("Extended");
}
}
I think when you call this line:
var damageScript = collision.gameObject.GetComponent<Damage>();
It gets the component by name, which in this case would be the Damage script, not the playerDamage script.
In you script it should be:
var damageScript = collision.gameObject.GetComponent<playerDamage>();
if( damageScript)
{
damageScript.ReceiveDamage(damageAmount);
}

Unity singleton manager classes

In Unity, whats a good way to create a singleton game manager that can be accessed everywhere as a global class with static variables that will spit the same constant values to every class that pulls those values? And what would be the way to implement it in Unity? Do I have to attach it to a GameObject? Can it just be there in a folder without being in the scene visually?
Like always: it depends. I use singletons of both kinds, components attached to GameObject and standalone classes not derived from MonoBehaviour. IMO the overall question is how are instances bound to the lifcycle of scenes, game objects, ... And not to forget sometimes it is more convenient to have a component especially referencing other MonoBehaviour objects is easier and safer.
There are classes that just need to provide some values like for example a config class that needs to load settings from persistence layer when called. I design theese classes as simple singletons.
On the other hand some objects need to know when a scene is started i.e. Start is called or have to perform actions in Update or other methods. Then I implement them as component and attach them to a game object that survives loading new scenes.
I designed component based singletons (type 2) with two parts: a persistent GameObject called Main, which holds all components and a flat singleton (type 1) called MainComponentManager for managing it. Some demo code:
public class MainComponentManger {
private static MainComponentManger instance;
public static void CreateInstance () {
if (instance == null) {
instance = new MainComponentManger ();
GameObject go = GameObject.Find ("Main");
if (go == null) {
go = new GameObject ("Main");
instance.main = go;
// important: make game object persistent:
Object.DontDestroyOnLoad (go);
}
// trigger instantiation of other singletons
Component c = MenuManager.SharedInstance;
// ...
}
}
GameObject main;
public static MainComponentManger SharedInstance {
get {
if (instance == null) {
CreateInstance ();
}
return instance;
}
}
public static T AddMainComponent <T> () where T : UnityEngine.Component {
T t = SharedInstance.main.GetComponent<T> ();
if (t != null) {
return t;
}
return SharedInstance.main.AddComponent <T> ();
}
Now other singletons that want to register as Main component just look like:
public class AudioManager : MonoBehaviour {
private static AudioManager instance = null;
public static AudioManager SharedInstance {
get {
if (instance == null) {
instance = MainComponentManger.AddMainComponent<AudioManager> ();
}
return instance;
}
}
If this class is just for accessing global variables then you don't really need a singleton pattern for this, or use a GameObject.
Simply create a class with public static members.
public class Globals
{
public static int mStatic1 = 0;
public static float mStatic2 = 0.0f;
// ....etc
}
The other solutions are fine but overkill if all you need is global access to variables.
Engineers who are new to Unity often don't notice that
you can't have a "singleton" in an ECS system.
It is meaningless.
All you have in Unity is GameObjects, at, XYZ positions. They can have components attached.
It would be like trying to have "a singleton" or "inheritance" in .... Photoshop or Microsoft Word.
Photoshop file - pixels at XY positions
Text editor file - letters at X positions
Unity file - GameObjects at XYZ positions
It is "just that simple".
So, in a game you will have "general" behaviors where there is only "one" of the thing. (So obviously there is only "one sound effects engine" , "one screen", "one scoring system" and so on.) A normal programmer would think of those as "singletons", but Unity just has nothing to do with singletons and no connection to singletons.
So if you have "a tank" or "a tree" of course it's normal you may have dozens of those things. But "the sound effects engine" or "the networking system" are "general, only-one-of-them" systems.
Hence, trivially, in Unity "the sound effects engine" or "the networking system" very simply sits on a game object, and, you (obviously) just have the one of them.
Those "general, only-one-of-them" items just sit on the preload scene.
You absolutely have to have a preload scene anyway, in every Unity project.
(Simple how-to: https://stackoverflow.com/a/35891919/294884 )
In the future Unity will include a "built-in preload scene" - when that day comes this will finally never be discussed again!
(Note - some of the languages you use to compile Components for Unity of course have OO concepts; but Unity itself has no connection to OO at all. Unity is like photoshop. You have "game objects" each at a certain 3D position.)
(Note - in the early days of Unity you'd see attempts at making code, say c#, which creates a game object on the fly, attempts to keep the game object unique, and "attaches itself" to the game object as a component. Apart from being completely bizarre/pointless, just FWIW it's theoretically not possible to ensure uniqueness (actually not even within a single frame). Again, it's moot because in Unity general behaviors just go on the preload scene.)
I wrote a singleton class that makes easy to create singleton objects. Its is a MonoBehaviour script, so you can use the Coroutines. Its based on this Unity Wiki article, and I will add option to create it from Prefab later.
So you don't need to write the Singleton codes. Just download this Singleton.cs Base Class, add it to your project, and create your singleton extending it:
public class MySingleton : Singleton<MySingleton> {
protected MySingleton () {} // Protect the constructor!
public string globalVar;
void Awake () {
Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID());
}
}
Now your MySingleton class is a singleton, and you can call it by Instance:
MySingleton.Instance.globalVar = "A";
Debug.Log ("globalVar: " + MySingleton.Instance.globalVar);
Here is a complete tutorial: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/
This is the setup I have created.
First create this script:
MonoBehaviourUtility.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
static public class MonoBehaviourUtility
{
static public T GetManager<T>( ref T manager ) where T : MonoBehaviour
{
if (manager == null)
{
manager = (T)GameObject.FindObjectOfType( typeof( T ) );
if (manager == null)
{
GameObject gameObject = new GameObject( typeof( T ).ToString() );
manager = (T)gameObject.AddComponent( typeof( T ) );
}
}
return manager;
}
}
Then in any class you want to be a singleton do this:
public class ExampleManager : MonoBehaviour
{
static public ExampleManager sharedManager
{
get
{
return MonoBehaviourUtility.GetManager<ExampleManager>( ref _sharedManager );
}
}
static private ExampleManager _sharedManager;
}
One way to do it is to make a scene just to initialize your game manager like this:
public class GameManager : MonoBehaviour {
static GameManager instance;
//other codes
void Awake() {
DontDestroyOnLoad(transform.gameObject);
instance = this;
}
//other codes
}
That's it, that's all you need to do. And then immediately after initializing the game manager, load the next scene and never come back to this scene again.
Have a look at this tutorial:
https://youtu.be/64uOVmQ5R1k?list=WL
Edit:
Changed GameManager static instance; to static GameManager instance;
Instead of creating one singleton for each class. I would suggest you to create a generic class for singleton. i use to follow this method which make my life very easy.
For More detail visit here
Or
Create Unity C# class in unity and use following code
/// <summary>
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton<MyClassName> {}
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static T Instance
{
get
{
if (m_ShuttingDown)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed. Returning null.");
return null;
}
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
Here is a simple code taken from Unity Tutorial. for better understanding open the link
using System.Collections.Generic; //Allows us to use Lists.
public class GameManager : MonoBehaviour
{
public static GameManager instance = null; //Static instance of GameManager which allows it to be accessed by any other script.
private BoardManager boardScript; //Store a reference to our BoardManager which will set up the level.
private int level = 3; //Current level number, expressed in game as "Day 1".
//Awake is always called before any Start functions
void Awake()
{
//Check if instance already exists
if (instance == null)
//if not, set instance to this
instance = this;
//If instance already exists and it's not this:
else if (instance != this)
//Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
Destroy(gameObject);
//Sets this to not be destroyed when reloading scene
DontDestroyOnLoad(gameObject);
//Get a component reference to the attached BoardManager script
boardScript = GetComponent<BoardManager>();
//Call the InitGame function to initialize the first level
InitGame();
}
//Initializes the game for each level.
void InitGame()
{
//Call the SetupScene function of the BoardManager script, pass it current level number.
boardScript.SetupScene(level);
}
//Update is called every frame.
void Update()
{
}
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
public static T instance { get; private set; }
protected virtual void Awake() {
if (instance == null)
{
instance = (T)this;
DontDestroyOnLoad(gameObject);
OnInit();
}
else if (instance != this)
{
Destroy(gameObject);
}
}
protected virtual void OnInit()
{
}
}
GameManage :
class GameManager : Singleton<GameManager> {
}

Categories