playMaker

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 - Thore

Pages: [1]
1
Action Requests / Camera: Smooth Follow Action + Distance Damping?
« on: September 17, 2017, 08:50:21 AM »
Hej,

I struggle somewhat to get a more advanced camera going, that needs to change how fast and loose it follows the player (I want this based on distance, but possibly also on other parameters). Smooth Follow Action works fine, but it always snaps into place.

I tried also the following: I created a game object, called Shadow which uses Position Smooth Damp. I get the distance to player, substract that from a value and feed this as the smooth time. In other words, the greater the distance, the faster it will follow. The shadow now follows the player in a rubberband-like manner. The further away you go, the faster it will try to catch up.

I set the camera to Smooth Follow Action, and another time also as a simple child (for the offset) of this Shadow object, rather than the player directly, which gets me somewhere near what I want. The problem is that this creates the typical Non-FixedUpdate jitter, in whatever variant I tried.

Maybe there are other ways to get what I want which is: divide the screen into three parts vertically, A|B|C. When the player is within B (the middle section), the camera is supposed to relax and move slowly. When the player moves towards either A or C (towards some threshold, A|B or B|C) the camera must speed up and basically lock onto the player as long as they run in this direction. Ideally, it's possible to "lock" into the player and release gradually by float.

If you have any idea how I can build this, or any pointer what I could try, I'd greatly appreciate it.

2
Playmaker Tips & Tricks / Improving The Workflow
« on: September 15, 2017, 12:40:30 PM »
It can be hard to keep an overview, once there are dozens of FSMs buzzing and sending events and variables around. There are also ways to make it easier, or more fun, to work with it all.

Here are a couple of workflow tips that will help you, or inspire you to manage your project and will help you staying on top of the ever-growing list of FSMs.

Renaming Actions
On Windows, you can press F2 to rename items (folders in Explorer, Game Objects in Unity, also paths in the animations, …). Did you know that you can rename actions, too? Place the action you want to use, then press F2 (or double-click) and rename it to something that gives you an idea what it does in your context. You can make the action list more intelligible and less abstract this way, almost like pseudocode. However, this makes it more difficult to see what the original action name was. Don't despair. Just hover over the little book icon and the tooltip tells you.

As pointed out by djaydino below, be mindful when working in a team. You can of course keep the action name, and just add to it, e.g. "Get Game Object: Player 1" or if it's obvious from context "Get: Player 1" and you have the best of both worlds.

Floating Labels & Headlines
This is more of a hack. States are also simply boxes with a name on it and a (possible) comment box underneath. You can appropriate them as a headline and paragraph, or as a floating label.

Place an empty state not connected to anything, and colour it (right click on state) with a colour used only for that purpose. That way you can tell these non-functional bits apart more easily. Now name them, and place them anywhere you like. You can add a kind of headline to functional parts of the FSM, for example.

Incoming Event
Let's suppose you have a state where you GET variables from somewhere else, or you read from a script. In other words, the FSM relies on incoming information. This is hard to see in the graph overview. How about using this hack in a similar vain as the floating label.

Create an empty state floating in thin air. Add an event like "Send Variable" or "From Script" to it, and connect it to a state which actually gets the variable from somewhere else. Colour both the state and the link, perhaps use the circuit link style to make it stand out from functional bits. Now you have something similar looking as a global event "coming in", but you can name the state and the event anything you like, and see clearly where variables are injected.

Tagging Nomenclature
I use some simple keywords I'll add into the states "description" field (in the State tab), like #Anim, #Send, etc. I use these to tell me straight away where dependencies are. I then see where, for example, animation events are send off. Short tags do the trick, and are fast and better to comprehend than longer explanations.

Global Events ALL CAPS
Global events are typically named uppercase. That way you can quickly tell them apart, and there's no issue with uppercase spelling (e.g. was it "turn on" or "Turn On"? It's "TURN ON")

Comment Action
Did you know there's an actual comment action? It's very useful to add information inside the states without cluttering up your graph.

Comment Action Dividers
Since you can rename actions, see the tip above, you can rename the Comment action into _______________, +++++++++++, ###########, ..................., ————————, ––––––––––––, --------------- and so on. Now you can structure your action list that way. Neat, isn't it?

Comment Action as Headline
Especially when you want to keep your graphs clean, you'll cram a lot of actions into one state. To still keep an overview, you can place Comment Actions, switch them off (just to be sure) and name them like /// EVERY FRAME /// etc. this way, you can group a block of actions with a headline.

Documentation URL
I haven't used that feature yet. However, the FSM has an option to include documentation right on the FSM tab.

Colour Coding
You can set up additional colours in the playmaker preferences and colour states and even the links (also separately). I sometimes succumb briefly to colour, but refrain from doing it, unless to draw attention to something. If every FSM looks like a rainbow, you have no clarity. Other users (see comments below) use them to differentiate whole groups of states.

Color Naming
You can name your colours and add new ones in the preferences, and that way determine more precisely what they mean. If you call the colour "WIP" (work in progress), you will probably use it consistently, and you will also see in two years what Red was supposed to mean.

Grouping
You can switch on grid snapping which makes structuring and arguably grouping better. Obviously, you can move the states around and group them. Use this for your advantage. Arrange the states of loops close to one another, then leave some nice distance to the next functional block, that way you can keep a good overview even in one FSM that does many things. Forget about symmetry and other such superficial criteria. Think of the FSM to flow top-down, for example; or from left-to-right -- whatever serves your purpose.

You can also control on which side the link arrows come out, by selecting the transition, hold CTRL and then left/right arrows to lock them in place. While I am at it, CTRL+Click on a state creates a FINISHED transition. CTRL+dragging out the link creates a new state that's already connected to the transition.

Naming Conventions
You have a VampireEnemy, and a SlimeEnemy? It may be better to adopt a general-to-detail naming convention for your variables. EnemyVampire, EnemySlime, etc and they are listed next to each other. Using space seems to create no problem, like "Enemy Vampire"; no need for clunky_names. Commonly, variables are also typed like enemyVampire (first lowercase, then every new word attached, starting uppercase). This convention is interpreted in Unity Editor as separate words when used in scripts (enemyVampire makes "Enemy Vampire").

FSM Paths
Name your FSM for example "Gameplay/Jumping" and you'll see in the FSM navigation bar right above the graph view, how it is now tucked inside a menu point "Gameplay". You need to keep this in mind when referencing it.

Watermarks
Right click on the graph view and set a watermark. You can add your own graphics into the folder and use them. Depending on your game, it can give you another quick and visible bit of information. Differentiate game logic FSMs and those that are for UI or effects, maybe. You can mark critical FSM, or use it as a stamp to assign ownership of the FSM when you work in a team (alien-head means Alice is responsible for this FSM). Maybe your game has two opposing sides pitched against each other, with nearly identical FSMs: watermark the sides. Watermarks can also be coloured images. I use this to mark FSMs with player input (movement, jumping, controllers etc). 

Variable Categories
When you select a variable, you can also set a category in the variable tab. Categories you once typed in, appear behind the tiny arrows next to the input field in subsequent variables. That makes it easier to keep the categories consistent. The same tip as above: don't succumb to categorize just because you can. The most important categories you want to use is Runtime and Config. In Config, you put those variables that you need to adjust; variables that are given. Into Runtime, you group all the variables that are overwritten and used for computation when the game is running (where it is pointless, or even game breaking when you adjust them).

On-the-Fly Variables and Events
A small workflow tip. You probably noticed that you can define variables and events right in the action. You find the option in the small dropdown menu where you set them. Once you do define an events there, a red box is popping up, telling you that no transition exists with that event (since you haven't yet added it). If you click on this box, it will create the transition on the fly. This happens when you pick an event that has no transition yet, and it's the fast way to populate especially switches that call for great many events. If you ever want to define ten types of events to use later, stop right there, and mind this trick.

Generic Events
(Non-global) event names don't have to be unique. You can create new events for each state individually ("go to jump"), but you can save some time if you pick more generic names, like Do, Next, Done, Fail, True, False, etc. The state only cares about the events as set in it.

Global Event Tricks
When you send a global event to an FSM, it will find it, and induce the flow there, no matter where it is. For this reason never use global events for anything other than to specifically communicate "globally". But you can also use this inside one FSM. Suppose you anyway use a global event called "AWAKE". Instead of looping back with a link, you can also send AWAKE to this same FSM, going back. This might be useful when your FSM is large and you want to "jump" from one place to another. Watch out, though, it might be a sign that your design is too much spaghetti, and perhaps needs to be broken up.

Shortcut Method Do Once
That's more a design pattern. Many actions do their thing. Then they trigger an event when they are done, or when some condition was met. You can often times leave the events not filled in, say Float Compare, only care about whether the float is smaller, and ignore equal and greater. You can take advantage of this fact, because this is good shortcut. That means, when you place such actions further above in the list, and they get triggered, the rest of actions down below will be skipped.

For example, you want that the actions below are only triggered once. But the sends keep coming in, constantly retriggering the FSM. Place a bool test with a variable that stands for "did we do this already?" on top. If true, do event "Skip". At the very bottom or in a subsequent state you set the variable "Did we do this already?" to true. Hence, when the list was used once, it's set to true, and when the chain is triggered again, the bool on top will recognize this and skip the rest. Later you need to reset the bool to false again. Take advantage of this to create a short cool-off period of retriggering events.

Think Ahead
It can be useful to get a fresh beverage and open a simple txt editor and type out what you exactly want to achieve. What kind of elements do you probably need? Are there different ways to solve the problem? Can you make it simpler with less dependency? Also, think about what exactly your mechanic is trying to solve; what gameplay purpose it will have? It might seem silly, but you should think whether your platformer really needs jumping, for instance. Imagine seriously how a game would be like without that mechanic (this is also great to get innovative games). Consider also inverting the problem, if you cannot trigger something, can you untrigger it? You measure from player to obstacle, how about from obstacle to player? etc. Make this a habit, and you have some clarity when you approach the situation.

Do the Research
Unless you know exactly what you're going to do, check some resources to give you a good turbo start on the frequent problems; get a glimpse of what kind of variables you probably need; and perhaps even find detailed talks, papers or videos on such seemingly simple things like jumping or camera movement (here, here) in a platformer -- stuff that is going to put your game above the competition when implemented with some juice.

Perhaps this is useful to some people. :) Please add your own ideas, or comments below!

EDIT: expanded a bit, made some improvements to the text.

3
Playmaker Help / FSM ↔ Mechanim (Set Animation Trigger behaves like bool)
« on: September 12, 2017, 01:26:34 PM »
Ahoy,

TL;DR: I send a Set Animation Trigger to mechanim, but instead of sending only an impulse, the triggers appear to be on or off, behaving like bools. I ruled out that I accidentally set them every frame.   

Q1: You see the triggers are filled or "on". They were triggered once (correctly) after spawning, because the character drops down shortly. The states that send the anim trigger are passed through only, and marked with the exclamation marks. There are none on Ground.

Q2: Why keeps velocity fluctuating as you see in the screenshot despite that the character is completely at rest? (it seems to have no effect on gameplay, though)

EDIT: I found out that triggers work like bools, but are supposed to be reset when the animation clip transitioned. Someone over at Unity wrote this:

Quote from: User
... Use triggers only if you are sure the animation will play full, from begginig to end, before issuing another trigger...

4
Feature Requests / Interface/Usability: State/Action Hashtags
« on: September 11, 2017, 10:26:35 AM »
What does it try to solve?
Where did I trigger the animation? Where do I wait for input? Where did I use this variable again? Where was the FSM state that I wanted to improve? You know these problems. You have to click through FSMs which can be quite laborious, and you cannot see at a glance what's relevant for you.

Solution!
The solution comes in several stages. The basic one is a solution, the others make the feature even better.

Basic: Introducing State/Action Tags. The user can #hashtag words in the State Comment, which are then searchable. That way you can instantly see, and find, whatever is relevant for you.

Improved: In the improved version, the hashtags on a state are added automatically, when certain actions are added to a state (and removed accordingly). The user has to switch on an option, and then determine somewhere which actions should automatically add the hashtag to the state they're in. It's probably unwieldy to maintain a huge list, so how about an input field that is directly next to the manual and options button at the actions (but once set on an action, it obviously counts for all identical actions anywhere). It's first blank, but there you can set the tag's name and a label colour. See my quick mockups how it could function.

Use Case 1: You have a few places you aren't quite happy with. You simply add #WIP to the state's comment field. Weeks later, you have no idea where you wanted to make improvements. Luckily, you can use the tiny search bar, type in # and it shows you the hashtags you have used, or you when you remember that it was #WIP, you can type that in straight away. Click through the list in the hamburger menu next to it, and quickly go to the correct state.

Use Case 2: Suppose, you have some FSM and you are interested to know precisely where stuff is sent off to the animator. This can be quite hard to see, especially not at a glance, unless you use colour-coding which can be quite cryptic. Luckily, Playmaker now offers automatic hashtags! You go to the options and switch them on. Now a tiny label icon appears right next to the manual and options icon on the actions. You go find just one instance, say "Set Animator Bool", hit the label button, where you define the tag and a label colour. Et voila! Now everywhere where "Set Animator Bool" is used, you see the labels appended after the comment (if no comment, at the same place).

Use Case 3:   Oh noes! You just cannot find any instance where you used "Set Animator Bool". No problem, just make a state anywhere, add the action, and then set the label. If you used the action already, they're now all visible. If not, fine, all future instances will be automatically labelled.


5
Playmaker Help / How to fix a GUI update problem?
« on: September 10, 2017, 08:14:02 AM »
Hello,

I have a holder Game Object, and as a child, a GUI text Game Object. The whole thing sits in the canvas, and generally works just fine. An FSM on the holder is constantly (loop, not every frame) checking some condition, and when the condition is met, either activates, or (via another route) deactivate the GUI text child. It's thus very simple. The loop either goes one route, and has it active, or the other route, and keeps it inactive. This also works correctly.

This object is a prefab and a few of these populate the scene, and they all work just fine. Except one, or two, occasionally, that are not visible (as if inactive) despite that they are truly are active, and are supposed to be visible.

What happens: The Canvas does not show it, or update correctly. I tried the "U GUI Canvas Force Update Canvases" action to no avail. Also, when I move the object a bit by hand during runtime, it suddenly correctly displays the actual state.

I could do something hacky like move the thing by a few pixels and see if this forces the update, but that cannot be a good solution. Any ideas?

6
Playmaker 1.8.4

Action: Load from File
Expectation: Trying to load a file that does not exist should lead to triggering the Failure Event. Likewise, if something is found, it should trigger the Success Event.
Bug: When no file is found, it prints out "FileNotFoundException: Could not find file "<path>", but the state is stuck in the state where this action sits, rather than triggering the failure event.

I also like to request a tooltip change on File Path to "e.g. Assets/Test.txt" to make it clearer. For consideration: I tried to understand how paths work, I often encountered the path to look like this "(Application.persistentDataPath + "/test.txt")", so there could be an issue with some type of builds (but I don't know).

Thanks.

EDIT: found out that it ignores both Success Event and Failure Event. On success, it continues to next action (or to next state via finished), and is still functional.

7
Found this after I wrote the below, my report is a bit clearer: http://hutonggames.com/playmakerforum/index.php?topic=12940.msg60396#msg60396

Playmaker version 1.8.4
(latest as of now)

Action: String Split
Issue: \n \t  separators don't work.

Expectation: According to tooltip, \n should accept a line break, and \t should accept a tab as separators.
Bug: It will treat any n or t as separator, e.g. D'artagnan will be split up. Also, will not split up at actual line break or tab.
 
Repro 1: make a string value, and set it to D'artagnan, then try the action with \n and \t.

Repro 2:
  • create test.txt in asset folder, put d'artagnan Athos Aramis Porthos but each name into a line (or tab).
  • Make a new FSM, add action "load from file" in first state.
  • path is Assets/Test.txt, set variable e.g. "Test"
  • next state, add the String Split action, try with \n or \t, and string array as e.g. "Data".
  • Play, watch Data

Related, a small improvement would be to update the tooltip of Action "Load from File" (which I'm using in conjunction). Change the tooltip to: "e.g. Assets/Test.txt" giving users an instant idea where the text to load is expected.

Thanks!










8
Hello :)

The Issue
I can easily add a script to an object by name (with the "Add Script" action), but then I find no way to access this script for further use, (for example with Get/Set Property). How can I access the script attached?

When I want to reference it, I need to specify "Object Type" from the menu, or use drag and drop and it creates the reference on the fly, but since "Add Script" is dynamic, I don't know beforehand which script is exactly added at runtime. Any ideas? Alternatively, is there a way to define Object Type by string?

Edit: yet another possibility, could a few lines be added to "Add Script" so that it allows the object to be stored for further use?

Thanks in advance!

9
Share New Actions / Puppet2D Flip Action
« on: April 11, 2017, 07:26:33 AM »
If you are using Puppet2D, you probably want to flip the character to move in the opposite direction. This tiny action will help you do that.

How to Use Custom Actions
  • Have a folder for custom actions, e.g. Assets/Playmaker/Actions Custom. You can then later copy that folder for use in another project.
  • Create the file manually, or use Playmaker's Custom Action Wizard (under Playmaker > Tools)
  • The file's name must be identical to the name given as public class ("Puppet2DFlip"). Any such name can only exist once in the project, but you can change it as long as you keep it consistent.

Puppet2DFlip.cs

Code: [Select]
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace HutongGames.PlayMaker.Actions
{

[ActionCategory(ActionCategory.Animation)]
[Tooltip("Flip character using the Puppet2D Flip variable")]
public class Puppet2DFlip : FsmStateAction
{
Puppet2D_GlobalControl script;
public FsmGameObject globalCTRL;
public FsmBool flip;

public override void OnEnter()
{
script = globalCTRL.Value.GetComponent<Puppet2D_GlobalControl>();
script.flip = flip.Value;
Finish();
}
}

}

10
General Discussion / Projectile & Health System: Best Practices?
« on: April 06, 2017, 08:46:47 AM »
It's going to be a Wall of Text.

I've built a few setups with projectiles and health managers, and seen even more tutorials how others are doing it. I'm somewhat unsure what are the best methods (performance, maintenance, ease of use etc), as different people have very different approaches but not much reasoning why exactly.

So I'm offering some ramblings and thoughs about how I do it, and why (reflecting my knowledge/ignorance at this point). The benefit might be a sanity check for everyone, what works and what doesn't and why. :)

1. Modular: I try to keep the parts modular. As such, the weapon-firing logic sits on the weapon (in different FSMs, one for firing, one for cooldown/reload functions). It just waits for a triggering event to fire. This then creates a projectile. Likewise, the visual representation of the player and enemies is a "skeleton" object I can just child underneath a holder with the FSMs. Same for health. This might be over the top for your game, but mine relies on re-using parts with different data. Most tutorials put the attacking logic into the holder, in contrast to my method where the weapon does the thing. However, the pitfall is that you need to think clearly what is horse and what is cart at any point.

2. Not Pooling:  I don't do pooling at the moment. I worry about this a bit. Frequent recommendation is to not create and destroy objects, but instead disable, and transform them (teleport them) and reuse them. I don't know how to do this well (arrays?). I tried this with dust particles on the running animation, but the copying and pasting of transform vectors, accessing the objects and switching them on and off seemed not much better (arguably worse). If someone is bored, an action similar to create, but draws from pool would be awesome. Likewise a complementary action that puts back to pool instead of destroy would be neat. I could have placed the dust into the running animation (switching it on and off there), but for now, it's just a particle "module" (see point 1) that is switched on and off per FSM on every step. I anyway needed an FSM for the footstep sound. I also have simple script for that, but for now opted to keep things in Playmaker. I noticed that on rare occasions the dust was briefly appearing on the zero vector 0,0,0 on enable instead off on under the feet where I placed it. Clearly, there are better ways to do this, but for now this is good enough. However, for projectiles I use old fashioned create/destroy projectiles. On hit, the projectile creates another object for the destroy particles. I can also potentially add area of effect type of stuf there.



3. Projectile Knowledge: The projectile first gets its essential data from the weapon and the player, such as who is enemy team, amount of damage it does etc. For determining stuff it can hit, I have dynamic (variable) and static tags ("hardcoded"). The static ones are simply set into the trigger event from the tag list. The dynamic tag is a variable and will hit whatever string is placed inside it. The purpose is that the projectiles from Team 1 need to look for "Team 2" and vice versa.

4. Know Your Enemy: "Tags" are too limiting, but for now they seem the best way to handle the world markup. Markup is basically the semantics or meaning of the game world, so that the game "knows" what is enemy, wall, ground and so forth (which can also be relative, e.g. my allies are my enemies enemies). The problem is that sometimes projectiles need to know quite a lot. I currently use "Trigger Event" multiple times in a list, to check for various tags I want being affected. Imagine you have three teams, and no friendly fire. Each needs to damage only the other two team tag holders (this is for the sake of illustration). In such a case, there need to be two Trigger Events, one looking for "Team 2" and one for "Team 3" (when the owner is "Team 1"). Is there's a better way, or some trick to expand tags so that objects can have multiple ones? Ideal would be hierarchy of tags, so that you only look for "stuff that can be affected" vs "decoration" and only once it's found, proceed from there. My workaround, to be done, will be a general "stuff that can be hit" tag, and then additional checks for what to do in each case. However, this might have subtle design implications.

5. Time Based Range: The Trigger Events send the "hit" event, which gets propagated to the target's Health module if it finds one. Underneath this Trigger Event list in the same state sits a wait action. If no "hit" event was fired, the wait will fire a "miss" event. The wait time determines the projectile range, naturally. This skips the hit computation and goes straight to the final state containing "destroy self". Time based range is not super exact, but works totally fine for my purposes. I guess an actual range computation would be some nightmarish checking of vectors.

6. Not Using RunFSMs: If one of the Trigger Events finds a collider with the proper tag, the whole damage calculation starts. Different tutorials work with RunFSM, but I don't see a good reason for it. I use RunFSMs to apply status effects, because they are highly variable, and used temporarily -- which in my albeit limited understanding are the best reasons for RunFSMs. In other words, you don't want a dozen of status effect ("poisoned" etc) FSM sit dormant on every actor waiting for being activated. But basic hit points / health management is always the same, and hence I don't see a reason why it should be moved into a RunFSM.

7. Health: Hence, following my modular approach, I have a universal "health" FSM template (any modifications to it are always applied everywhere), and it sits on a health prefab object. I put this as child to anything I want to use a damage system on. Put it below a cube -- done! How this works is that the projectile, after having hit something, looks for this Health component, and passes on its damage data and also triggers a global event in that FSM (e.g. "HIT"). Following convention, I type global events in uppercase.

8. Metaphors & Variables: Conventions and game metaphors are important. Instead of calling it "damage", I call it "energy", and my convention is that damage is minus and healing is positive. If you call the variable "damage" and it's a positive number, i.e.  "10 damage" you might wind up in complications once you want healing. Also, you can conceptualize 1 points being a "quarter heart" (in terms of Zelda), or you can declare that 0.25 as float is one quarter heart. I use INTs, which I find cleaner and less error prone. It also frees you from confusing system with game metaphor. Should you later want to divide your hearts into 6 pieces, you don't have to throw away your balance, just adjust the representation. You still have e.g. 10 points, but they are now displayed as "one Lifeforce and 4 pieces". You might want to use floats when you really need to do complicated computations. I would advice to reconsider your game design, because ultimately players want to understand what "health" means. It is a central game metaphor and should not be opaque what goes on.

(9.) The Health object is initialized by setting the clamp to prevent healing going over the top. I want that healing is possible to up to about 20%, and clamp it there. With floats, you can just do *1.2. I do this by copying starting HP to HP Max, then temporarily compute 1/5th then add both HP and Max together to have the real Max; i.e. Looks cumbersome, but at least it keeps the numbers clear.

Step One 10HP = 10Max
Step Two 10Max/5 = 2Max
Step three 10HP + 2 Max = 12Max.
Done.



(10.) After HIT is triggered, it first checks whether we're invincible. I have this for now, and is intended to have a spawn protection. Invincible begins as true, and thus no energy can pass through (also no healing). A separate FSM on the same health object sets it to false after a short time. This is another frequent design pattern. If this was on the same FSM, triggering the global event (the "HIT") could interrupt the setup. I also use this pattern on the weapon for the cooldown/reload logic. The only thing they do is wait, and then flip some bool on the main FSM, thereby allowing the series of events sloshing through. It may be useful to properly initialize objects that have unpredictable global events in them. You would then always place the bool check underneath the global event, as a gate, and only if set properly, the event is being let through.

(11.) Computing the incoming energy is a simple Int Add. Since damage is negative, it substracts as intended (e.g. 10 Plus [-3 Energy] = 7). Directly afterwards, incoming energy is set to 0, of course, now that it was applied. Finally it's passed through a simple Int Clamp with the Hitpoint Max determined above. Finally, the rat tail of animations and updating GUI is handled (I do this elsewhere). This is also a good practice in my book, because it keeps the health component universal. It will just output "I have no HP anymore" at some point and characters might play death animations, walls might crumble etc.

(12.) Next, I check whether we're still alive. If Health is below 0, I move to Destroyed sequence of states. The first after that is a state with a simple bool check to prevent a potential bug. It asks whether we triggered Destroyed already (same idea as in 9). If we did, it goes into a dead end state of doing nothing. I use this for now to prevent a bug I had in some version, where Destroyed was interrupted over and over again by subsequent projectiles. I might be fixing this by immediately changing tags, but I leave this idea here, because this failsafe design pattern is useful in other circumstances. If Destroyed routine was not triggered yet, it continues where I next set the bool "destroyed triggered once" to true (i.e. one gets through and locks door behind itself). After that, I send events around and change the holder tag (so that projectiles no longer care about this object).

(13.) Final useful thing for me is colour coding of links and states in FSMs. Colouring links is a bit hidden (you find this under right click on an event). The most crucial to me is clearly showing (1) dependencies to other FSMs or other components (animator, scripts etc), and to indicate "Work in Progress/Debug" parts. It would be great if Playmaker would be showing outgoing events similar to the incoming ones (from global events), i.e. thicker black arrow coming out of a state. Even better, if there was an overview that shows FSMs as boxes with all the events as ins-and-outs showing the relationship between them. For now, I use a workaround (which might be a bad idea), basically "dead" (i.e. non-functional) states and events. I create an ordinary local event, e.g. "Send Events", which I put last on a state that sends stuff around. This event is then connected to an empty state named like the global event it triggers, e.g. "HIT". I put the target FSM name in the comment instead of the state name, because the same FSM can be targetted with different global events.  You see an example how this looks like in the screens I put above. Green is always receiving (green state) or sending stuff (green links to non-functional state), Red is debug/work in progress.

/applause for having read to the end! I greatly appreciate comments, ideas, anything you might have.

11
Share New Actions / Get NavMesh Velocity
« on: March 28, 2017, 09:33:47 AM »
I found getting the property from NavMesh was not always working well (the drag and drop method worked fine, but not using referencing it through object variable), so I made this simple action.

Strange School's example was useful in making it (check out the channel as linked there), I'm myself not a coder.

Quote
// Fetches Nav Mesh Velocity directly.
// NOTE: you need to set up a Vector3 variable in
// Playmaker and set this one in "Store Velocity" and take it from there!
 
using UnityEngine;
 
namespace HutongGames.PlayMaker.Actions
{
 
[ActionCategory(ActionCategory.NavMeshAgent)]
public class GetNavMeshVelocity : FsmStateAction
    {
        [RequiredField]
        [CheckForComponent(typeof(UnityEngine.AI.NavMeshAgent))]
       
        [Tooltip("holder of the NavMeshAgent script")]
        public FsmOwnerDefault gameObject;
 
        // variables we need.
        [Tooltip("holder of the target FSM")]
        public FsmGameObject targetGameobject;
        public FsmVector3 storeVelocity;
 
        // Enable or disable Every Frame
        public FsmBool everyFrame;
 
        // Left is the script type, right the variable where it will be stored for use.
           UnityEngine.AI.NavMeshAgent scriptObject;
 
//On Enter 
        public override void OnEnter()
        {
            var go = Fsm.GetOwnerDefaultTarget(gameObject);
 
// Confusing as it is, but simple. We declared above the scriptObject type we want, but it is still empty.
// Hence, we now need to access the object (thats the "var go" just above),
// and fetch from there the concrete object of the same type.
            scriptObject = go.GetComponent<UnityEngine.AI.NavMeshAgent>();
 
 
            if (!everyFrame.Value)
            {
                GetVelocity();
                Finish();
            }
 
        }
 
//Public Override
        public override void OnUpdate()
        {
            if (everyFrame.Value)
            {
                GetVelocity();
            }
        }
 
// Ze Method
        void GetVelocity()
        {
            var go = Fsm.GetOwnerDefaultTarget(gameObject);
            if (go == null)
            {
                return;
            }
 
// Executing the actual operation. FSM velocity is set to that from the scriptObject.
            storeVelocity.Value =  scriptObject.velocity;
                 
        }
    }
}

Comments or feedback appreciated, thanks!

12
Hello Everyone!

I searched here and the ecosystem but couldn't find it. I'm looking for a robust method to get/set several variables from an external script (object) to an FSM.

What I'm trying to do
I like to have the important and essential variables of a game object in one place, and in a nice list, so they can be tweaked and balanced more easily, think Character Sheet. However, they are needed in different FSMs and get/set.

Problems & Assumptions
  • I am aware of the "Get/Set Property" method, but it only allows for one property per action. It would have to be repeated many times to get/set several variables. Also, variable names in the FSM need to be created manually.
  • I could use one FSM as a variable "holder", and use get/set FSM variables to communicate with other FSMs, but they make for a chaotic list, but at least they are consistent across them.
  • Using global variables somehow strikes me as a bad idea.

Current: Hack
I made a simple variable holder script, think Character Sheet, that keeps all the important high level variables in one place (think Running Speed, Damage etc). Then I reference this component as an object (drag/drop component into variable list), then I use get/set property multiple times until I got the various variables I need. I don't like this method, because it looks hacky and seems not very efficient.

Solutions Ideas
  • An action that can fetch and write (get/set) a number of variables at once from an object (script/component).
  • Wrapping my script in such a way that playmaker accepts it as one action, and once in the FSM format, use the FSM-to-FSM communication to spread them around

Can someone point me to a resource that does this, give me a pointer how to solve this (I'm a non-programmer), or a solution that would be good, or reassure me that my solution I use already is good enough? (any feedback welcome)

Thanks in advance! :)

Pages: [1]