关于Unity的PlayMaker

So, should you use Playmaker in production? Short answer is:

Long answer follows.

Playmaker

Playmaker is a visual scripting tool for Unity. It has been a top-selling asset in the Asset Store for a couple of years.

Learning environment

I get invited to host Unity workshops from time to time. One of these workshops consisted of 6 lessons and the audience didn‘t know anything about programming. That‘s where I finally decided to try to build an entire game using Playmaker.

The game was really small with Unity physics doing most of the work, but anyway many small scripts to handle interactivity were needed. And here Playmaker worked really great.

The concept of states and actions appears to be very intuitive, so even people with near to no programming experience could "script" simple interactions very fast.

So, for teaching Unity I will definitely use Playmaker again.

State machines

Well, I‘m a huge fan of state machines. I usually structure my code so I know exactly in which states all the modules of my application are. And every action is controlled from top to bottom in a hierarchy of simple state machines. This apporach keeps the code very simple and easy to follow and debug.

It seemed that Playmaker being a visual state machine framework would fit fine in my pipeline. But, oh God, how I was wrong.

Code, OOP and software architecture

If you are an experienced software engineer you know how important it is to structure your code right.

We all remember those days spent trying to debug a spaghetti mess of interlinked code promising to God to never be so lazy again if he helps us find why this monstrosity doesn‘t work.

Sooner or later you inevitably come to a set of good practices of software architecture and code structuring. If you do everything right and use a good IDE like Visual Studio which allows you to easily browse code and jump to lines where a function is defined or called, it‘s really easy to follow what‘s going on in your code and usually is not hard to figure out why something is not working.

The critical features here are:

  • Ability to see where methods are called from,
  • Transparent control hierarchy (i.e. a chain of command with no global events or variables),
  • Right encapsulation with no external state exposed.

Playmaker violates all these statemens and adds even more ugly stuff.

Playmaker in production

Now I‘m going to list all the problems I found in Playmaker I could remember while working on a real project. In no particular order.

If you know a good workaround for any of these problems feel free to post them in comments at the end of the article.

1. Playmaker breaks encapsulation

If you don‘t want to shoot yourself in a foot you absolutely shouldn‘t expose object‘s internal state to the world.

Well, Playmaker does just that. It completely breaks encapsulation.

Most likely you would have a script on the same object with Playmaker FSM which exposes API to control the object. This script does some work and makes the FSM to change state. It‘s a normal behavior but here you have state moved outside of the object, visible to everyone, state which can be modified by anything any time.

Even if you are an experieced developer and you understand possible consequences of this decision, believe me, you WILL be tempted to do the wrong thing and modify this state bypassing proper API calls. Young programmers will do this immediately if you give them any chance at all.

2. Playmaker makes it impossible to see control flow

Any action in any state can call any method or change a local or global variable. There‘s no way to find out what changes what except going through every state and every action by hand.

There‘s no Find Usages or Go to Definition like in any good IDE, if someone decides to bypass the API (and they will) you will have a very hard time trying to find out what really is happening there.

3. Playmaker is incompatible with git

Seriously, we had so much pain in the ass because of how Playmaker saves its graphs into Unity scene. It seems that it does this the most unmergeable way possible. And you don‘t even know that something was damaged during a merge right away. Beleive me or not it was happening a lot even if someone just moved some states around to make them look better...

4. Playmaker makes scripts more complicated

Playmaker was created to make coding simpler, right? Not really.

Playmaker makes small "code" simpler to write but large complicated code becomes a complete mess.

This is actually a problem of all visual languages. Believe me, I worked a lot with visual scripting environments.

In a visual language you connect nodes which do simple tasks, like adding two numbers or calling a method. And there‘s a threshold where you have to delete all your "visual" code and reimplement this logic as anode or an action in Playmaker terminology. Because visual "code" becomes too complicated very quickly.

Sooner or later you‘ll end up with this.

Which is MUCH harder to follow than code.

Of course, you can develop common practices to try to fix this mess. Like, having one action with major logic per state or design your action in some modular fashion. But you can‘t get rid of this problem completely especially when you have a set of actions which you probably can combine into a Frankenstein‘s monster to do what you want. Because the cost of making a new action (multiplied by laziness) is higher.

4.1 Passing data

Unlike dataflow visual languages where you pass modified data around, to pass something from one action to another you have to use variables. Which is (a) another huge layer of complexity and (b) makes one more huge hole in encapsulation.

So, instead of doing action2(action1("hi")); in code you have to (a) add one or more variables, (b) add variable support to both actions, (c)configure to use same variables on both instances of these actions.Which is adding a lot of unnecessary complexity.

4.2 Events on state change

It‘s surprising, but there‘s no way for a script to be notified when a FSM changes state. If you want to sync a FSM‘s state with something else you will have to put a special action in every state yourself. Which makes states even bigger.

5. Playmaker uses global variables and events

You probably know or at least heard that global variables and global events are evil. Usually it‘s wrong to say that something is 100% bad or 100% good because world is not black and white. There are ways to use global variables/singletons and global events/messages without driving yourself crazy.

But how global events and global variables are implemented in Playmaker is the same as giving you a loaded machine gun and aiming it to your foot.

Anything can dispatch an event or change a global variable, and any other object can react to this. And due to (2) you have no way of debugging this.

And because Playmaker encourages you to use global events and global variables, even if you are aware of the consequences, sooner or later you will start using them. And you‘ll regret about this decision at the end...

6. Playmaker makes state machines excessively complicated

This one might be my personal choice, but anyway these are my personal thoughts so I ought to list it too.

There are several ways to implement a state machine. Different implementations might be called a Mealy machine, or a Moore machine, or another way to combine current state and current input into action.

The thing is that Playmaker forces you to have all the logic in states.So, to execute something you have to change state. This gets even more complicated considering the execute in every frame flag which many actions have. Because in current system it‘s either a transition from a state to itself (while during this transition not all the actions get executed) or a piece of logic which executes without a transition. Both of these options break the execution model Playmaker offers.

What‘s more, if you want to add a constant logic for an event which behaves the same in most of the states you will have to add this logic to all states in Playmaker.

I think you can use several FSMs to deal with this problem but having several FSMs just adds even more complexity.

Another model (which I use in my code) would be to use states as filters what to do with incoming events. In this case you need much less states and all your event handlers will look like this:

private void EventHandler() {
    switch (currentState) {
        case State.One:
            // ignore
            break;
        case State.Two:
            doSomeStuff();
            break;
        case State.Three:
            doOtherStuff();
            break;
    }
}

I don‘t have to change states when I want to execute some logic in response to an event. Also, I‘m absolutely sure that this event will have no effect if current state is State.One.

Of course, you can have some logic executed right when state changes. Anyway, this abstraction of state machines allows to have less states and is easy to read in code.

Good stuff

But there are some good points. When I was trying to list good sides of Playmaker I came up only with two:

  1. Visual representation of states and transitions,
  2. Usually it‘s easy to see what is being done in a state.

I am an experienced software engineer and I can keep in mind most of the nested graphs of state machines in my app. But it‘s always better to have a visual representation.

One of my less experienced colleague told me that he really liked working with Playmaker, because he was able to see actual state graphs.

Of course, guess who was in charge of fixing all the mess Playmaker introduced with these shiny graphs... But he has a point. Visualizing control flow and state graphs does help.

As for individual states, if you structure and name all the actions rightit‘s really easier to read what‘s going on in the state comparing to reading a bunch of unrelated methods in source code. But as I noticed this type of "coding" actively uses another part of your brain and keeps wasting brain power on how "code" looks instead of focusing on how it works.

Not that it‘s a completely bad thing but it easily drives you from what you need to do into some sort of "playing with fonts" procrastination.

Conclusion

First of all, I will never use Playmaker in my app again.

Second, there might be a better paradigm and a better way to use a visual state machine in Unity. The one which doesn‘t have all the flaws Playmaker has.

This is just another field for me to explore.

时间: 2024-10-05 09:29:40

关于Unity的PlayMaker的相关文章

从Unreal Engine 3到Unreal Engine 4

Unreal Engine 4发布好长好长时间了,直到最近才有时间仔细去看一下. TimSweeney老大一句话"IF YOU LOVE SOMETHING, SET IT FREE",原来需要几十万授权金才能拿到的东西,就从$19,变成免费了,而且开源.作为一个国际顶尖的引擎,能走出这一步,对我等普通开发者真是福音啊.如此的牛X,再加上开源,相信Unreal Engine 4会火起来的,你看看最近E3上的产品展示也能感觉到.不过,Unreal的定位毕竟是"国际顶尖"

unity中使用FingerGestures插件3.0

FingerGestures是一个unity3D插件,用来处理用户动作,手势. 译自FingerGestures官方文档 目录 FingerGestures包结构 FingerGestures例子列表 设置场景 教程:识别一个轻敲手势 教程:手势识别器 教程:轻击手势识别器 教程:拖拽手势识别器 教程:滑动手势识别器 教程:长按手势识别器 教程:缩放手势识别器 教程:旋转手势识别器 教程:自定义手势识别器 教程:识别手势事件 建议:使用.net代理事件 fingerGestures包结构 路径,

Unity插件

1.2D Toolkit 如果过去你一直从事3D游戏开发,最近想转做2D游戏,最好尝试一下2D Toolkit.2D Toolkit是一款2D开发组件,它具有很强的灵活性和适应性,能够让开发者在Unity环境中进行2D开发. 2D Toolkit基本没有学习门槛,拥有可编写脚本的动画编辑器以及具有Unity平台特性的组件集合,能够对像素进行完美呈现.2D Toolkit能够完全支持Unity 4,它对于2.5D场景的开发和建立也十分有效. 2.NGUI NGUI是一款强大的UI系统框架.它能够完

【Unity笔记】常用插件

记录一些常见插件,随时补充. A星寻路 Dijstra迪杰斯特拉 iTween动画插件 原理:插值法,给出初始值和终点值,自动算出中间值. DoTween Tween动画 Playmaker $45 Playmaker由第三方软件商Hutong Games开发完成.它的Logo是一个中文的"玩"字,独特.有创意. 既是一个可视化脚本工具,又是一个分层逻辑框架.设计师.程序员使用Playmaker能够很快地完成游戏原型制作,既适合独立开发者,又适用于团队协作.Playmaker能够大大提

Unity常见面试题大全

1.       [C#语言基础]请简述拆箱和装箱. 答: 装箱操作: 值类型隐式转换为object类型或由此值类型实现的任何接口类型的过程. 1.在堆中开辟内存空间. 2.将值类型的数据复制到堆中. 3.返回堆中新分配对象的地址. 拆箱操作: object类型显示转换为值类型或从接口类型到实现该接口值类型的过程. 1.判断给定类型是否是装箱时的类型. 2.返回已装箱实例中属于原值类型字段的地址. 2.        [.NET(C#)] attribute,property,markup,ta

【Unity3D基础教程】给初学者看的Unity教程(零):如何学习Unity3D

[Unity3D基础教程]给初学者看的Unity教程(零):如何学习Unity3D http://www.cnblogs.com/neverdie/p/How_To_Learn_Unity3D.html 作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点推荐.谢谢! Unity3D有什么优势 Unity3D是一个跨平台的游戏引擎,如果您开始看这篇博客的话,你一定实在权衡学习或者使用哪种游戏引擎来开发您的游戏,

easy touch利用playmaker拖动ngui对象

最近在学习unity3d的几个插件.easy touch,playmaker,ngui.为了使几个能够一起使用,还弄了playmaker ngui scripts和easy touch addon 4 playmaker插件. 最近做的一个需要touch拖动一个ngui的2d对象,又想用playmaker来控制.这话怎么说怎么绕啊.反正,是有杀鸡用宰牛刀的感觉. 在easy touch addon 4 playmaker的例子里面有怎么拖动gui对象的示例,不过我在拖动ngui的时候发现总是不对

PlayMaker的应用

PlayMaker属于一个可视化的状态机编辑工具,集成到了Unity的IDE里,在Unity的市场上很受欢迎,本人看见后第一感觉是跟CryEngine的那个状态机特别相似.CE的那个状态机编辑器其实是很难用的,研究过的同学纷纷表示事倍功半.从过去的经验上看,这种可视化的状态机编辑器适合于批量的生产,例如,新手引导,每一个功能也许都会有一个新手引导,以前的做法是需要程序员们写一堆的代码.写新手引导,要了解状态机,要了解各种事件的触发机制,对一个新手来说,学习曲线还是有的.如果评估工作量的话,一个中

Playmaker Input篇教程之引入的核心概念

Playmaker Input篇教程之引入的核心概念 Playmaker Input引入的核心概念 Playmaker引入了4个核心概念:状态机.动作.变量和事件.了解它们是学习操作Playmaker的前提,本节会分别介绍它们. Playmaker Input状态机 状态机,即Finite State Machine,读者在本章前面的部分已经见过了,它主要负责组织各个离散的"状态".状态机里包含5个元素:起始事件(Start Event).状态(State).过渡事件(Transiti