函数式编程适不适合游戏开发
之前写小游戏(非专业,纯玩)都是习惯面向对象。大概感觉是这样
class Object()
#states: [position, health, direction...]
#methods: [move, serializer]
class Player(Object)
#player_methods: [attack...]
class Boss(Object)
#boss_methods: [...]
p1, p2 = new Player(), new Player()
boss = new Boss()
p1.move(..)
p2.move(..)
boss.attack(..)
Renderer.render(p1, p2, boss)
学了几天 elixir 后发现函数式也挺顺手,但是不知道有没有实际用函数式开发游戏的。
global_state
player1_pos: ..
player1_health: ..
player2_pos: ..
player2_health: ..
boss_pos: ..
boss_health: ..
...
}
fn move: state -> new_state
fn move_player: () -> state -> new_state
fn move_player_by_num: num -> () -> state -> new_state
fn move_boss: state -> new_state
fn boss_attack: state -> new_state
global_state
|> move_player_by_num(1)
|> move_player_by_num(2)
|> move_boss
|> bos_attack
|> render
感觉除了内存占用大一些没其他坏处,有有经验的分享下么?
以前 vczh 安利我函数式编程, 我不知道学了有什么用, 同问.
github.com/Kyjor/JulGame.jl
github.com/heyx3/Bplus.jl/blob/master/docs/!why.md
有助于提升代码质量
国际上有哪个大公司在使用吗? 有什么工业界实际的项目在运用吗?
hesudu.com/t/847038#r_11567399
看场景。函数式编程你明白是在定义一种变量约束关系,与从原始数据到目标数据的 transform 就好。
linq 我也写过, 除了写法非常潮, 很漂亮, 但是别人看不懂 :-0
反正 linq 写多了也挺轻松, 比如 lodash, 但是还是喜欢 linux c 的抽象, 简单明了, 但是不知道普通的程序员维护起来轻松吗?
我观测的标准就是, 是否流行, 有很多的项目.
我觉得更适合写业务层,丢失了一部分性能,换来了代码的可行度,但是有些人写的 函数式也没啥可读性,写起来比较爽是真的,不容易出 bug
======================
张三丰向张无忌传授一套太极剑法,一路剑法使完,竟无一人喝彩,各人尽皆诧异:“这等慢吞吞、软绵绵的剑法,如何用来对敌过招”。还以为是张真人有意放慢了招数,好让张无忌瞧个明白。
只听张三丰问道:“孩儿,你瞧明白了没有?” 无忌答道:“看清楚了。” 张三丰道:“都记得了没有?” 张无忌答道:“已忘记了一小半。” 张三丰道:“好,那也难为你了。你自己去想想吧 。” 张无忌低头默想。
过了一会,张三丰问道:“现下怎样了?” 张无忌道:“已忘了一大半了。" 周颠等人皆急:“刚学的剑法都忘了一大半,这可如何迎敌?” 便请张三丰重新传授一遍。
张三丰微笑,再使出一路相同的剑法。张无忌沉思一会,睁开眼:“我已忘得干干净净。” 众人皆惊,唯张三丰独喜。随即张无忌拿剑迎敌,大胜。
这是摘自《倚天屠龙记》,张三丰教于张无忌的三个境界。编程也是如此。
第一层,学习语言语法和规则,理解编程范式,巩固基础核心。
第二层,熟练掌握,灵活运用,理解设计模式的运用。
第三层,随心所欲,信手拈来。
第三层最终归于平淡,什么项目用什么,什么场景用什么,不再刻意追求使用什么工具,什么语言,用了什么设计模式,一切都是基于专业的透彻理解,其他的都是对经验的抽象后的总结。
前人告诉了你这样可以如何如何,有天赋的比如张无忌就能一点就通,我等凡夫俗子通常需要不断踩坑才能深刻体会。
erlang 就是很典型的函数时编程,且在游戏开发领域很常用,尤其是那种 MMORPG 的网游,不过主要原因还是 erlang 的 actor 方式的通信模型
可以搞基
用 erlang/elixir 的很大一部分是做游戏后端的.
其实游戏编程还蛮适合函数式的,因为游戏其实就是个巨大的有限状态自动机,各种游戏操作只是对状态的变换罢了。
没写过游戏,但是我觉得无论面向对象的方式写,还是函数式的方式写,最后的输出的“结果”是一样的,那其实就只有代码的“样貌”不同,对于个人开发者而言,要对比的差别应该是可读性、可维护性,以及写代码时的心智负担等,如果是团队开发来说,要考虑就更多了。
其实 F# 嵌入 Godot 是非常可行的。我记得有个 Up 发过视频。
可以,但没必要,就现在游戏圈里能找到的牛马的技术水平,能把面向对象写明白就不错了
不适合,中、大型游戏性能完全达不到要求,可能适合简单的小游戏。
函数式编程是放弃一部分单体性能换取方便的极致的高并发,因为不可变性无副作用,所有数据都依靠最基础的数据源计算而不像面向对象有很多中间状态,这是很适合服务端开发的,但非常不适合客户端开发。
比如游戏生命值,函数式是每次获取都现场计算基础生命值+buff+装备等等得到最终生命值,而游戏普遍做法是有一个最终生命值的状态,每次 buff ,装备都去修改这个状态,获取最终生命值直接获取这个状态。
你写的这个代码,越看越有 ECS 的味道
游戏还是属于 state change 很多的场景,其实不太合适。
functional 想法用在一些接口设计还可以,纯函数式就不太好用
函数式编程还是在做编译器和解释器的场景用的比较合适
写 server 还是写 client?
感觉都不合适, 游戏天生自带了一吨外部状态, 天生和函数式理念不符
还是写得太少了,在高手面前编程范式都是可以挑选的,而不是拘泥于一种。上面也有人提到了 erlang, elixir 很多人都用来做游戏后端, 给一个 20 年老程序员 网易游戏总监云飞的 blog 地址,
他之前搞得 skynet 框架 正是借鉴了 erlang 的特点(比如热更新)。他写这些东西的时候已经是 10 年前了。
blog.codingnow.com/2013/08/skynet_update.html
客户端肯定不合适,至少不能纯用某个语言来写,连个事实标准的图形 api binding 都没有,要我自己新造个轮子来解析 vulkan xml ,我还真嫌麻烦。
至于 elixir ,要例子的话,我记得一些日本公司有拿来做服务端用,在他们一些技术博客上看过,比如 cygames?
这一堆函数式语言里我觉得最有双端生产力的是 F#,只可惜 BDFL 自己都不在乎自己的成果了,微软剩下那几个全职开发同时负责编译器和内部支持,完全忙不过来,F#最后只会越来越和 C#脱节
对 skynet github.com/cloudwu/skynet/
实际封装后的游戏服务器例子
github.com/li5414/RillServer
性能会跟不上,之前知乎看过某个帖子,也是大佬重构 erlang 写的后端极大的提高并发量, c++ 在性能敏感场景就是这么吊你不得不服.
用 erlang 的好处就是
- 并发,每个进程都有自己的队列,收发消息简单粗暴,进程隔离
- 监督进程可以管理子进程
- 热更新
对于性能
非得需要极致性能,那么 + c + zig + rust
对于项目
所有的大型逻辑项目,都是屎山堆屎
顽皮狗的游戏逻辑用一个 lisp 方言脚本开发,详见游戏引擎架构那本书
坏处是 这 tm 啥 jb 符号语言
迫于老板让我规划服务器集群,我这几天查阅了一些资料,总结出一些方案,想写出来让 V 友参考一下,有没有什么坑。 先列一下服务器资源: 5 台 128G 内存新服务器 ====…
今天来讲一讲TCP 的 TIME_WAIT 的问题。这个问题尽人皆知,不过,这次遇到的是不太一样的场景,前两天也解决了,正好写篇文章,顺便把 TIME_WAIT 的那些事都说一…
2012年的时候写过一篇叫《程序算法与人生选择》的文章,我用算法来类比如何做选择,说白了就是怎么去计算,但是并没有讲程序员可以发展的方向有哪些。 所以,就算是有这些所谓的方法论…