Duckbridge

Just a couple of kids with some dreams

Author: duckAdmin

Luckslinger tech #2 – A simple, yet effective Event system in Unity

Hey again, this is entry 2 in the ‘Luckslinger tech’ series  and this one will be about the ‘event system’ that we use in our games. We use this in MANY places in Luckslinger and it makes the development of the game(and other games) a lot easier and more flexible.

This system is used for dispatching in-game events and is similar to the publish-subscribe pattern.

The system is quite simple, there is object A which listens to object B and then when object B wants to send a message to object A, it just dispatches, that message. An example:

GameManager {
     Player player = new Player();
     player.AddEventListener(this.gameObject);  
     public void OnPlayerDied() {
          RestartGame();
       }
} 
Player {
   Public void OnHit() {
        health--;
        if(health < 1) {
           DispatchMessage(“OnPlayerDied”, null);
         }
     }
}

It’s an example of an event that we actually use in Luckslinger (but ofcourse it’s not that simple in-game).

When ‘DispatchMessage’ is called, it sends a message to all the objects that are listening to the Player object, in this case it’s only the GameManager, so in the GameManger, the ‘OnPlayerDied’ function is called through the event (and no parameter is passed, you could do that if you want)

So how do you get a system like this to work? Well we’re in Luck, because in Unity this is relatively easy to do (We can also do this in Java, but I’ll do a separate post on this if people want to know how to do it).

Unity has this thing called ‘SendMessage’, which allows you to call a function on an object by it’s name (a string). And you guessed it, we will basically be using this function, but we’ll be building something around it to make it work easy!

 

The code looks like this:

public abstract class DispatchBehaviour : MonoBehaviour {
     
     private List<GameObject> listeninggameObjects = new List<GameObject>();
     protected bool isEnabled = true;
 
     public void DispatchMessage(string message, object parameter) {
         if(listeninggameObjects != null) {
             for(int i = 0 ; i < listeninggameObjects.Count ; i++) {
                 if(listeninggameObjects[i]) {
                     listeninggameObjects[i].SendMessage(message, parameter, SendMessageOptions.DontRequireReceiver);
                 }
             }
         }    
     }
     
     public void AddEventListener(GameObject go) {
         if(go != null && !listeninggameObjects.Contains(go)) {
             listeninggameObjects.Add(go);
         }
     }
 
     public void RemoveEventListener(GameObject go) {
         listeninggameObjects.Remove (go);
     }    public virtual void Disable() {
         this.isEnabled = false;
     }
 }

 

So it is a class that is a child of MonoBehaviour (so you can extend the DispatchBehaviour class in your own classes). Which means that you could make a Player class which is able to dispatch messages to other objects by doing the following:
 
 public class Player : DispatchBehaviour  {
             //player code stuff
} 

Basically what the DispatchBehaviour class does is that you can add objects into the list of Listeners with the ‘AddEventListener’ function and then you can send a message to all of them in the ‘DispatchMessage(‘message’,parameter)’ function. And because you extend the DispatchBehaviour class, you can always access the functions.

The way this would work in Unity is quite simple, almost the same as what I’ve done before.
I’ll give some pseudo/example code:

 public class GameManager : MonoBehaviour {
public void Awake() {
Player player = this.transform.Find(“Player”).GetComponent<Player>();
player.AddEventListener(this.gameObject);
}

public void OnPlayerDied() {
Debug.Log(“Ah, you died, restart”);
}

public void OnPlayerDied(Player player) {
Debug.Log(“Ah, player with “ + player.name +” died, restart”);
}

}

public class Player : DispatchBehaviour {

public void Awake() {
Invoke(“OnFakeDied”, 2f);
}

public void OnFakeDied() {
DispatchMessage(“OnPlayerDied”, null);
}

public void OnFakeDiedWithParameter () {
DispatchMessage(“OnPlayerDiedWithName”, this);
}

}

You could probably just copy-paste this into Unity in an empty Scene with two gameObjects and just attach the correct scripts to the game Objects and it should work.

That’s it! Pretty easy right :).
My name is Marciano Viereck and I’m the programmer at Duckbridge and we’ve recently released Luckslinger on Steam with a 2 man team.

Luckslinger tech – #1 How to make 2D Sprite animations in Unity

So we’ve just released Luckslinger on Steam and some people were curious about the ‘system’ that we use for doing all the sprite-animations in the game. Actually the basics are quite simple, but after that it gets a bit more complicated. For this post I’ll just go over the basics and explain how we use Unity’s Sprites to make simple(and later complex) 2D sprite animations.

Basically how it works is that, we make the animations in Graphicsgale and then export it as a full png. So that the whole animation is in one image. Then we import it in Unity as a Sprite with ‘Multiple’ sprite mode, we then cut all the frames of the spritesheet correctly and filter as point and set the Format to Truecolor.

We then create an ‘SpriteAnimation’ in Unity and then add the ‘Animation2D’ component to it, we then add all the cut sprites in the array, do the settings, press Play in Unity and voila!

 

So how does this ‘Animation2D’ component work? We’ll make it right now!

So I’d say, create a new C# Class in your Unity project and call it Animation2D.

First of all, we’ll need to add some settings to the Class.

public float FPS;
public bool isLooping;
public Sprite[] frames;
public bool playOnStartup = false;
private SpriteRenderer outputRenderer;
private float secondsToWait;

private int currentFrame;
private bool stopped = false;

Most of these variables are quite self-explanatory, you can set the FPS in the editor, set if it’s looping or not, set drag the correct frames for the animation and choose wether the animation will play when the scene loads. And the private variables are more for internal stuff.

So where do we go from here? Create an Awake function for your class (void Awake()) and it should look like this.

public void Awake () {
         outputRenderer = this.GetComponent<SpriteRenderer>();
             
         currentFrame = 0;
         if(FPS > 0) 
             secondsToWait = 1/FPS;
         else 
             secondsToWait = 0f;

         if(playOnStartup) {
             Play(true);
         }
     }

What happens here is that firstly we grab the SpriteRenderer which should also be added to the GameObject which contains this script, then we just reset the frame and set the secondstoWait. If the ‘playOnStartup’ is set to true, then the animation will start playing instantly. (otherwise you can make it play from somewhere else by calling the ‘Play’ function which we’ll make in a second.

 

public void Play(bool reset = false) {

         if(reset) {
             currentFrame = 0;
         }

         stopped = false;
         outputRenderer.enabled = true;

         if(frames.Length > 1) {
             Animate();
         } else if(frames.Length > 0) {
             outputRenderer.sprite = frames[0];
         }
     }

I guess most of this function also explains itself, I just reset some variables and check if there are more than 1 sprites into the array of animation sprites. If so, then start playing the animation, if not, then just set the sprite to the outputRenderer so it’s a still animation.

So next up if the final part, and the ‘core’ part of the Animation2D class, and can be used to add more functionality to the Animation2D class (as we have!)

public virtual void Animate() {
         CancelInvoke("Animate");
         if(currentFrame >= frames.Length) {
             if(!isLooping) {
                 stopped = true;
             } else {
                 currentFrame = 0;
             }
         }
     
         outputRenderer.sprite = frames[currentFrame];

         if(!stopped) {
             currentFrame++;
         }

         if(!stopped && secondsToWait > 0) {
             Invoke("Animate", secondsToWait);
         }
     }

So this function is called by ‘Invoke’ and first of all Cancels any Invoke that might have been called (so that the animation doesn’t mess up by accident). Basically what it does is increment the ‘currentFrame’ counter by 1 and then takes the sprite in the animation’s array at that index and applies it to the output.

And it checks if you want it to loop. If you want it to loop and the counter is longer or equal to the size of the animation array, then it will reset. If not, it will just stop.

And then if the animation hasn’t stopped yet it will use Invoke to re-call the Animation function.

I guess you could easily make a ‘Stop’ function which Cancels any Invoke of ‘Animate’ and sets ‘stopped’ to true.

Horse running animation in Luckslinger made with this system

That’s all for now, if you have any question or so feel free to email (duckbridge.dev[at]gmail.com) or comment. This animation class is quite simple, but we built our whole animation system based on this little class here!

I guess I could do more of these posts about more code-stuff of our game, like the loading system, saving system, some minigames, Ui stuff, some AI stuff, whatever.

My name is Marciano Viereck and I’m the programmer at Duckbridge and we’ve recently released Luckslinger on Steam. (with a 2 man team)

Luckslinger showcase at E3!

Hey all!

We haven’t posted any news in a while, but we’re suuuuuuuuuper excited to share that we will be showcasing Luckslinger at E3 in Los Angeles together with indiecade! (all 3 days of E3)

We’re still hard at work on the full version of Luckslinger and (as you might have guessed) our release-date moved a bit (at first we wanted to release at the end of May) but we will announce our new release date soon :)!

And for those who have played our demo, thanks for playing :) the full version will be waaay better than the demo version :D

New facebook page for Luckslinger!

Hey all,

We recently decided that it would (probably) be a good idea to make a  separate facebook page for Luckslinger, check it here :)

https://www.facebook.com/luckslinger

Copyright © 2017 Duckbridge

Theme by Anders NorenUp ↑