Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - MaDDoX

Pages: [1] 2
Share New Actions / Smooth Look At 2D (bugfix)
« on: January 24, 2016, 11:48:37 AM »
"Finish Event" wasn't working properly, the angle was always returning zero due to the way Vector3.Angle operates. It was pretty frustrating since the whole point of a 'smooth look at' is to transition smoothly (duh) and fire up an event once it's finished. I did a very minor fix so it just calculates the absolute z offset between angles to assert if it's "done" or not. Here it goes, just copy and paste it over the SmoothLookAt2D.cs content:

Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2014. All rights reserved.
//--- __ECO__ __ACTION__ ---//

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
[Tooltip("Smoothly Rotates a 2d Game Object so its right vector points at a Target. The target can be defined as a 2d Game Object or a 2d/3d world Position. If you specify both, then the position will be used as a local offset from the object's position.")]
public class SmoothLookAt2d : FsmStateAction
[Tooltip("The GameObject to rotate to face a target.")]
public FsmOwnerDefault gameObject;

[Tooltip("A target GameObject.")]
public FsmGameObject targetObject;

[Tooltip("A target position. If a Target Object is defined, this is used as a local offset.")]
public FsmVector2 targetPosition2d;

[Tooltip("A target position. If a Target Object is defined, this is used as a local offset.")]
public FsmVector3 targetPosition;

[Tooltip("Set the GameObject starting offset. In degrees. 0 if your object is facing right, 180 if facing left etc...")]
public FsmFloat rotationOffset;

[Tooltip("How fast the look at moves.")]
public FsmFloat speed;

[Tooltip("Draw a line in the Scene View to the look at position.")]
public FsmBool debug;

[Tooltip("If the angle to the target is less than this, send the Finish Event below. Measured in degrees.")]
public FsmFloat finishTolerance;

[Tooltip("Event to send if the angle to target is less than the Finish Tolerance.")]
public FsmEvent finishEvent;

private GameObject previousGo; // track game object so we can re-initialize when it changes.
private Quaternion lastRotation;
private Quaternion desiredRotation;

public override void Reset()
gameObject = null;
targetObject = null;
targetPosition2d = new FsmVector2 { UseVariable = true};
targetPosition = new FsmVector3 { UseVariable = true};
rotationOffset = 0;
debug = false;
speed = 5;
finishTolerance = 1;
finishEvent = null;

public override void OnEnter()
previousGo = null;

public override void OnLateUpdate()

void DoSmoothLookAt()
var go = Fsm.GetOwnerDefaultTarget(gameObject);
if (go == null)

var goTarget = targetObject.Value;

// re-initialize if game object has changed

if (previousGo != go)
lastRotation = go.transform.rotation;
desiredRotation = lastRotation;
previousGo = go;

// desired look at position

Vector3 lookAtPos = new Vector3(targetPosition2d.Value.x,targetPosition2d.Value.y,0f);
if (!targetPosition.IsNone)
lookAtPos += targetPosition.Value;

if (goTarget != null)
lookAtPos = goTarget.transform.position;
Vector3 _offset =;

if (!targetPosition.IsNone)
_offset +=targetPosition.Value;
if (!targetPosition2d.IsNone)
_offset.x = _offset.x+ targetPosition2d.Value.x;
_offset.y = _offset.y+ targetPosition2d.Value.y;

if (!targetPosition2d.IsNone || !targetPosition.IsNone)
lookAtPos += goTarget.transform.TransformPoint(targetPosition2d.Value);

Vector3 diff = lookAtPos - go.transform.position;

float rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
desiredRotation = Quaternion.Euler(0f, 0f, rot_z - rotationOffset.Value);

lastRotation = Quaternion.Slerp(lastRotation, desiredRotation, speed.Value * Time.deltaTime);
go.transform.rotation = lastRotation;

// debug line to target

if (debug.Value)
Debug.DrawLine(go.transform.position, lookAtPos, Color.grey);

// send finish event?

if (finishEvent != null)
//var targetDir = lookAtPos - go.transform.position;
//var angle = Vector3.Angle(targetDir, go.transform.right) - rotationOffset.Value;

var angle = Mathf.Abs(go.transform.rotation.eulerAngles.z - desiredRotation.eulerAngles.z);

if (Mathf.Abs(angle) <= finishTolerance.Value)


I found this action to be quite useful, so I'm sharing it with you guys. I've originally developed it for my Ludum Dare #24 entry, I guess I've mentioned it here in the forums, but it was quite buggy so I've decided to postpone its release until it was solid. It took me surprisingly long to found out what was the problem, but the fact that it doesn't use a proper "counter" (for simplicity's sake) made me have to work out some unusual logic to run it the right amount of times. After some tests it seems quite solid, please inform me if you find any problems.

The follow screenshot shows an usage example, hopefully it's self-explanatory enough. Tell me if it isn't :)

PS.: Part of the code is based off of 'Get Next Child'.

Hey guys, the RageTools logo animation was done entirely with PlayMaker and RageTools, and I did a fast-motion video showcasing the graphs used with iTween actions, etc. You can see it after 7:30 in this video:

The result is shown full-screen right at the begin of the video. It was really cool making this kind of animation in a 100% visual and intuitive way (not to mention without using bitmaps at all heh), to be honest making this in After Effects would be sensibly harder :)

If you're curious, here's the page link, links to the Asset Store, homepage etc are all in there.

I can't believe I forgot to post this action before, I found it to be absolutely handy in my workflow. Many times all you want to do is offset an object by a certain amount (say, "speed"), and having to fiddle with custom variables to remember the old position and add to it can be a quite cumbersome way to do this. iTween is sheer overkill for such linear, stepped operations and the "translate" action is a continuous, perma-state operation, so very hard to be useful for things other than controllers.

Thus this modified "set position" action, excellent for so many simple translation operations that I wouldn't be able to list them all. Simply replace the default setposition.cs action (in assets/playmaker) and it'll be ready for use. Just toggle on the "additive" button and presto. Enjoy! :)

In many circumstances it helps a lot to get a string formatted in a specific way straight during the conversion stage from an int of float, instead of going through a routine to format the string after the fact. C# has some nice built-in format strings just for that, which weren't exposed in Playmaker - so far :)

A couple good examples of use:

-Leading zeroes on an int-converted variable. Suppose you have values like 20, 140 and want to see them shown as 0020, 0140, etc. To do that you'd use Format = "0000" or "D4"

- Format in percentage notation a float number, for instance, convert 0.2 to 20% in a statistics display. For that you'd use format = "P2".

For more information on the available options, read here:

To install simply overwrite the original actions in Assets/Playmaker/Actions. If it's an existing project don't worry, these actions are compatible with any existing data, if the 'format' field is set to null it performs the original, no-format behavior. Hope you find it of use, enjoy!

Playmaker Bug Reporting / Templates not working across projects
« on: May 18, 2011, 06:35:25 AM »
Found this a couple days ago during an online coding session with my team. I've saved an fsm template, sent it through skype, and when my bud imported it all he got was an empty state. I thought it could be related to some missing custom action, but he sent me a new template which I've then tried to import in the *same* project (we use GIT) and I got the same result.

Needless to say this is pretty bad since we can't share Fsms created separately. Maybe using export packag as mentioned in another thread but still..

Share New Actions / Collision Event with Multiple Tags
« on: May 04, 2011, 08:40:22 PM »
What the name says! Very useful for the common situation when you have multiple collision tags which lead to the same state. Just replace the original CollisionEvent.cs file inside Assets/PlayMaker/Actions and done. Here goes the creator log:

// Sandro Bihaiko Change Log:
// - Minor Code Cleanup (05/2011)
// - Added Multiple Tag Support

Share New Actions / Reset Variables
« on: May 04, 2011, 08:01:19 PM »
What if you have, in a certain state, to set multiple int/floats to zero and some gameobject variables to null? Plenty of "Set" actions right? No longer! Brought to you by Sandro Bihaiko, my business partner and our studio's lead coder, this is one of those nifty lil' things that makes your day just a bit easier :)


PS.: In case you check the code and guess why did he use "Foreach", Sandro assured me that there's absolutely no performance loss compared to the regular FOR expression. He confirmed it with his friend Rodrigo Bamboo (one of Unity Technologies main software engineers and creator of the Boo language), and he said that the compiler is already fully optimized for "foreach" usage, people just forget to use the "break" to stop the loop when needed - then blame the function itself. I had no idea and trusted the popular belie.. er, myth. Happy to know better now, I also find this command much easier to code and read :)

Feature Requests / SubFSM!
« on: May 03, 2011, 07:27:33 AM »
We've started discussion about nested FSMs (or SubFSMs, kinda like "subroutine") in this thread:

And many important points were brought up, including how you can currently use "Next Frame" to execute multiple states in a single update. Recently while completing a short game project I've had many problems trying to make things run in the same update, it quickly became obvious that they don't do it by default. If I got it correctly each state takes one update. "Next Frame" can supposedly make multiple states execute in the same update, yet it never got clear to me what defines that the "state block" started, only that it has ended, and Alex's example only cites a loop. ???

Anyways, back to the point, the more and more we dig into PlayMaker the clearer it gets that nested FSMs are the way to go. It has been mentioned that one state would "link" to a complete new FSM. Supposing that's still the idea, would all the the states (and consequently the actions in it) in that FSM be executed in the same logic frame (update)? Sorry for the probably stupid question but what happens when/if the execution of those states take too long, does Unity slows everything down to try and keep up or would it "clip" the execution of actions after a certain threshold, and keep executing them in the next frame? I imagine the right answer is the first one, but I want to make this crystal clear 'coz it's a very important concept.

In any ways, please make Nested/SubFSMs a top priority, it'd make our lives 10x easier - and the need for new/hybrid actions, 10x rarer.

Share New Actions / Trigger Broadcast Event
« on: May 02, 2011, 04:28:43 PM »
Supposing you want to broadcast an event after a specific trigger event, by default you always have to drive the execution flow to another state (using Trigger Event), and in that state you execute the 'broadcast event' action. In some circumstances this can be really bad since some messages just have to be sent/broadcasted as quickly as possible and there's apparently some minor overhead (delay) in switching states, which can make all the difference between things working as you want or not. I've created 'Trigger Broadcast Event' exactly to fill this gap - although I recognize that a proper SubFSM structure (a mini-FSM which would be executed in the same update and return to the calling point once finished) would be perfect for such scenarios and instantly render such actions obsolete.

Yet the clock won't stop ticking, so, meanwhile.. enjoy :)

Share New Actions / Read Float
« on: April 29, 2011, 10:56:38 AM »
Works just like Read Game Object (link) but for Floats. Main advantage of these actions is finding the FSM and its hosting object by name instead of by reference, it makes it really easy to pull off values (especially multiple ones) from another FSM.

Share New Actions / Read Int
« on: April 29, 2011, 10:54:40 AM »
Works just like Read Game Object (link) but for Integers. Main advantage of these actions is finding the FSM and its hosting object by name instead of by reference, it makes it really easy to pull off values (especially multiple ones) from another FSM.

Feature Requests / "Global Variables" through automatic messaging
« on: April 29, 2011, 09:31:30 AM »
Many have asked for - and even Alex himself mentioned that he wants - "Global Variables" inside PlayMaker. The thing is that there aren't only upsides for Global Variables, and I'd like to discuss it a bit here before proposing my idea.

Tthe fact is that there's something to Global Variables that stinks (as in "code smell", I'm sure Alex know the definition :)) to OOP (object oriented programming) coders. I consider myself anything BUT a hardcore OO coder, I've graduated in Computer Science when OO was still a novelty so I have a much more procedural approach to things, but I recognize the OO advantages - I also recognize its many disadvantages, something that most coders which grew up in these OO days fail to do, thinking it's some sort of silver bullet.

One of the nice things about OOP is "encapsulation", which's basically making sure that the variables which only have to do with one logic block are never "exposed" (accessible) from outside. This helps a lot in reducing clutter and making things consistent, basically each logic block becomes a black box which only reveals what it takes and what it gives back as it does its thing.

This is great, back in the day when local variables didn't exist things were such a hairy mess. But since nothing in life is for free, we now have the problem of knowing what each of these parameters do and what type they are, and how to transfer the parameters between the code blocks. 

PlayeMaker so far has dealt with this beautifully with its easy-to-use "set event data" and messaging actions, so I'm very concerned on how to keep these user-friendliness without losing the encapsulation advantages. Thus my proposal is:

- Have "Global Variables" as an implicit concept. You'd basically have a new tab in the variables section where all these "global variables" could be accessed from. In practice wherever they're created they're actually "hosted" - that's the single place where the value is stored. Any other FSM which "checks in" the variable will have a local variable with the same name and type automatically created.

- Whenever you access (writes) the checked-in global variable in an action, in practice PlayMaker wraps up a set event data and messaging to its host FSM. Likewise, whenever it reads from this global variable, PlayMaker performs an under-the-hood get FSM vartype.

This way things would be easy and transparent for us developers, without breaking the encapsulation concept and keeping the variable consistent across all FSMs. Opinions/Comments welcome as usual!

Share New Actions / Read Game Object
« on: April 28, 2011, 09:28:52 AM »
Why having a different kind of "Get FSM Game Object"? The point is, right now we don't have global variables, nor the ability to duplicate actions, so if you initialize your local variables with content placed elsewhere (quite a common approach to keep things organized) you're in for a lot of legwork simply to initialize your variables. You have to drag and drop the object that contains the source FSM, then select the FSM (if there's more than one, also far from uncommon) then select the source variable then the destination variable. That, per action.

So I decided I could do something to smooth up this process a little. 'Read Game Object' finds the source game object per name (meaning you can copy+paste it), same for the FSM name, then all you have to do is select the local variable. As long as there's a same-named variable in the source FSM, the content will be copied over.

To change the handy default source strings, besides the manual paste/typing method you have two options:

1) Edit the .cs file and change the strings in the "Reset" section (I've set it for the naming convention that I use):
Code: [Select]
       public override void Reset()
            objectName = "_ GameFSMs _";
            fsmName = "fsmPrototypes";

2) To make it "drag and droppy", simply use a variable. You can start the state/FSM with a "Get Name" action and assign the desired object name to a string variable which will be used for all following "Read Game Object" actions.

I imagine this will get deprecated as soon as Global Variables are introduced, but meanwhile I found it quite handy, hope you find it of use as well.

PS.: I'll be posting "Read" actions for other variable types as I need/make them

Feature Requests / Add "Toggle Link Style" to the transition menu
« on: April 27, 2011, 01:59:28 PM »
As the title says, the bezier links are more visually pleasing but in many circumstances the "circuit" style is more useful, I just don't want to have everything as circuits because they are very bad in other circumstances. I'm not sure if the Unity API allows it, but if we can have this setting "per-transition", it'd be excellent.

PS.: The preferences setting, beyond setting the default, would then toggle everything in the scene.

Pages: [1] 2