转一篇关于Unity的PlayMaker
这篇文章转自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:
- Visual representation of states and transitions,
- 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的更多相关文章
- 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...
- 【Unity3D技术文档翻译】第1.9篇 使用 Unity AssetBundle Browser tool (AssetBundle系列完结)
上一章:[Unity3D技术文档翻译]第1.8篇 AssetBundles 问题及解决方法 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced D ...
- Playmaker Input篇教程之Playmaker购买下载和导入
Playmaker Input篇教程之Playmaker购买下载和导入 Playmaker Input篇认识Playmaker Playmaker是Unity的插件,其标志如图1-1所示.开发者使用它 ...
- 用好lua+unity,让性能飞起来——luajit集成篇/平台相关篇
luajit集成篇 大家都知道luajit比原生lua快,快在jit这三个字上. 但实际情况是,luajit的行为十分复杂.尤其jit并不是一个简单的把代码翻译成机器码的机制,背后有很多会影响性能的因 ...
- Unity性能优化(4)-官方教程Optimizing graphics rendering in Unity games翻译
本文是Unity官方教程,性能优化系列的第四篇<Optimizing graphics rendering in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...
- Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译
本文是Unity官方教程,性能优化系列的第二篇<Diagnosing performance problems using the Profiler window>的简单翻译. 相关文章: ...
- unity之初识shader
自己做个总结先.当然文中很多内容都是从各位大神的文档当中看的.我只是站在巨人的肩膀上. 首先什么是shader?其实就是一个在显示屏当中的显示程序,俗称着色器.它可以定义物体在硬件显示屏当 ...
- 对想进入Unity开发新人的一些建议
提前声明:本文只是写给那些非职业游戏开发人士,只面向那些在校本科生,或已就业但无unity背景的同学们,当然是面对程序员方向的.本人刚工作也没多久,资历尚浅,之前在网上有一位同学让我谈谈一些想法,所以 ...
- Unity协程(Coroutine)原理深入剖析
Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 其实协程并没有那么复杂,网上很多地方都说是多 ...
随机推荐
- 列表list
Python是一种面向对象的语言,但它不像C++一样把标准类都封装到库中,而是进行了进一步的封装,语言本身就集成一些类和函数,比如print,list,dict etc. 给编程带来很大的便捷 Pyt ...
- Linux运行等级,根目录,文件类型etc
Linux的Runlevel Linux默认有6个Terminal(Ctrl+Alt+F1~F6)和1个X window(Ctrl+Alt+F7,图形化界面)让用户登录 Linux的runlevel一 ...
- Windows Azure CN 超业余性能测试
先来说说为什么会有这篇文章吧.从朋友那里搞来个Windows Azure CN的测试帐号,在公司的时候领导的朋友有一个阿里云的服务器,平时部署小东西都往上面丢,不过那是人家的东西,还有其他的应用跑在上 ...
- 使用::before和::after来完成尖角效果
一.目标 目标完成下图效果: 二.完成 1.分析 在::before和::after伪元素的用法一文中有说到使用::befrore和::after可以完成一个六边形.这个案例是用一个#star-six ...
- 150924-还是起得来床的好-HTML(CSS)
一早醒来是9:10,这些天最晚的了,也可能是睡的最爽的了. 不废话,早上Matlab仿真干不出来,不如学学html,上代码~ <!DOCTYPE HTML><html>< ...
- 【温故而知新-Javascript】使用Web存储
Web存储允许我们在浏览器里保存简单的键/值数据.Web存储和cookie很相似,但它有着更好的实现方式,能保存的数据量也很大.这两种类型共享相同的机制,但是被保存数据的可见性和寿命存在区别. PS: ...
- Effective Java 读书笔记
创建和销毁对象 >考虑用静态工厂方法替代构造器. 优点: ●优势在于有名称. ●不必再每次调用他们的时候都创建一个新的对象. ●可以返回原返回类型的任何子类型的对象. ●在创建参数化类型实例的时 ...
- 一行代码远离Google浏览器兼容问题的困扰
跟Html相比,Web Flash开发的最大优势就在于兼容性好,因为FlashPlayer的开发商只有Adobe一家.但自从Google插了一脚进来,改版出自己的FlashPlayer以后,这一优势就 ...
- Hibernate关联映射关系
Hibernate关联映射关系 一.双向一对多关联映射关系:当类与类之间建立了关联,就可以方便的从一个对象导航到另一个或另一组与它关联的对象(一对多双向关联和多对一双向关联是完全一样的) 1.1创建实 ...
- SQL主外键和子查询
主键 数据库主键是指表中一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY约束来创建主键.一个 ...