这篇文章转自http://va.lent.in/should-you-use-playmaker-in-production/

此文作者大概深受其苦,吐槽了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.

转一篇关于Unity的PlayMaker的更多相关文章

  1. 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)  ...

  2. 【Unity3D技术文档翻译】第1.9篇 使用 Unity AssetBundle Browser tool (AssetBundle系列完结)

    上一章:[Unity3D技术文档翻译]第1.8篇 AssetBundles 问题及解决方法 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced D ...

  3. Playmaker Input篇教程之Playmaker购买下载和导入

    Playmaker Input篇教程之Playmaker购买下载和导入 Playmaker Input篇认识Playmaker Playmaker是Unity的插件,其标志如图1-1所示.开发者使用它 ...

  4. 用好lua+unity,让性能飞起来——luajit集成篇/平台相关篇

    luajit集成篇 大家都知道luajit比原生lua快,快在jit这三个字上. 但实际情况是,luajit的行为十分复杂.尤其jit并不是一个简单的把代码翻译成机器码的机制,背后有很多会影响性能的因 ...

  5. Unity性能优化(4)-官方教程Optimizing graphics rendering in Unity games翻译

    本文是Unity官方教程,性能优化系列的第四篇<Optimizing graphics rendering in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...

  6. Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译

    本文是Unity官方教程,性能优化系列的第二篇<Diagnosing performance problems using the Profiler window>的简单翻译. 相关文章: ...

  7. unity之初识shader

    自己做个总结先.当然文中很多内容都是从各位大神的文档当中看的.我只是站在巨人的肩膀上.       首先什么是shader?其实就是一个在显示屏当中的显示程序,俗称着色器.它可以定义物体在硬件显示屏当 ...

  8. 对想进入Unity开发新人的一些建议

    提前声明:本文只是写给那些非职业游戏开发人士,只面向那些在校本科生,或已就业但无unity背景的同学们,当然是面对程序员方向的.本人刚工作也没多久,资历尚浅,之前在网上有一位同学让我谈谈一些想法,所以 ...

  9. Unity协程(Coroutine)原理深入剖析

    Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 其实协程并没有那么复杂,网上很多地方都说是多 ...

随机推荐

  1. kernel启动console_init之前console不可用时发生crash的调试方法

    http://code.google.com/p/innosoc/wiki/KernelBootCrashDebug 注: 如在i386_start_kernel中加入:early_printk(&q ...

  2. [书目20160526]Brain Rules 让大脑自由:释放天赋的12条定律

    推荐序1 12条定律,让大脑更聪明推荐序2 走过迷雾地带前  言 人人都有一个不可思议的大脑 定律1:越运动,大脑越聪明 信不信,“驴友”比“沙发土豆”更聪明! 老板,请把办公室的咖啡机换成跑步机! ...

  3. WEB安全--逻辑漏洞

    业务逻辑问题是一种设计缺陷.逻辑缺陷表现为设计者或开发者在思考过程中做出的特殊假设存在明显或隐含的错误.精明的攻击者会特别注意目标应用程序采用的逻辑方式,设法了解设计者与开发者做出的可能假设,然后考虑 ...

  4. Java开发之Servlet生命周期

    Servlet会在服务器启动或第一次请求该Servlet的时候开始生命周期,在服务器结束的时候结束生命周期.无论请求多少次Servlet,最多只有一个Servlet实例.多个客户端并发请求Servle ...

  5. 在虚拟机中安装CentOS7

    在虚拟机中安装CentOS7 听语音 | 浏览:17352 | 更新:2014-10-31 12:14 1 2 3 4 5 6 7 分步阅读 一键约师傅 百度师傅最快的到家服务,最优质的电脑清灰! 百 ...

  6. memcache的安装和使用

    Memcache Memcached是一个高性能的分布式缓存系统.memcached自身不会实现分布式,分布式是由程序来实现的. Memcached一旦安装之后,自身进行管理!预申请一个很大的内存空间 ...

  7. java 22 - 7 多线程之控制线程的方法

    线程休眠(让线程休息一会再运行) public static void sleep(long millis) 在自定义线程类中添加该方法. 更改后,运行测试类,结果就是每执行完一轮,就休息1秒(这里设 ...

  8. 使用javascript实现html页面直接下载网盘文件

    公司新建一网站,用的是商派的易开店系统.设计方案中有一个是下载文件的功能,但易开店不支持上传资源,所以无法下载本站资源. 于是想到了网盘资源下载,有些网站是把页面链接到网盘资源文件下载页面,进行二次跳 ...

  9. XAMPP中proftpd的简明配置方法

    XAMPP中proftpd的简明配置方法   用LAMPP的安装方法可以开一个默认的nobody用户,用lampp security就可以初始设置相应的默认用户密码.如果要有多用户,又怎样管理.目录怎 ...

  10. Java集合系列:-----------06List的总结(LinkedList,ArrayList等使用场景和性能分析)

    现在,我们再回头看看总结一下List.内容包括:第1部分 List概括第2部分 List使用场景第3部分 LinkedList和ArrayList性能差异分析第4部分 Vector和ArrayList ...