从“黑神话:悟空”看Go为什么不适合AAA游戏开发

2024年8月20日,国产AAA游戏《黑神话:悟空》正式发布!凭借其卓越的画面表现、成熟的玩法和令人惊叹的技术细节,迅速引爆了全球游戏市场,在上线不到一周的时间内,全平台已经大卖超1000万套,一举成为全球游戏玩家瞩目的焦点,并获得普遍的好评。作为一款AAA级大作,它不仅在艺术设计上精益求精,背后更是依托于极高的技术标准。这类游戏的开发对编程语言和技术栈的要求十分严苛,尤其是在图形渲染、物理引擎、多线程处理等方面。

35ca2e20ff043ccd3cb89dd8121e15a8.jpeg

Go语言近年来因其在云计算、后端开发中的出色表现吸引了大量开发者的关注。凭借简洁的语法和强大的并发支持,Go已经成为很多领域中的热门选择。那么问题来了:Go语言能否适应像《黑神话:悟空》这样的AAA游戏开发呢

尽管Go语言在服务器端开发中大放异彩,但当我们仔细审视AAA游戏的核心需求时,会发现它在这个领域面临着诸多挑战。本文将从《黑神话:悟空》为例,粗略分析一下为什么Go难以胜任AAA游戏开发的角色,并探讨它在游戏开发中的潜在应用场景。

1. 什么是AAA游戏开发?

AAA游戏代表着业界顶尖的游戏开发水平,通常伴随着高预算、高人力投入和高技术标准。这类游戏通常具有以下特征:

  • 庞大的制作团队和高昂的开发成本

  • 先进的图形渲染和逼真的视觉效果

  • 复杂的游戏机制和丰富的内容

  • 高度优化的性能,以确保流畅的游戏体验

为了实现极高的画面质量、复杂的物理系统以及流畅的用户体验,AAA游戏开发对技术栈提出了以下几大核心需求:

  • 图形渲染

AAA游戏需要对实时3D图形进行极致优化,确保画面细节丰富、光影逼真,同时保持高帧率,特别是在当前4K甚至8K分辨率的趋势下。

  • 物理引擎

真实的物理模拟是游戏沉浸感的核心,要求引擎能够处理复杂的碰撞检测、重力模拟、流体动态等。

  • 多线程和并发处理

为了最大化利用现代多核处理器的性能,AAA游戏通常依赖多线程编程来处理不同的任务(如渲染、物理、AI等)。

  • 资源管理

在大型游戏中,如何有效管理海量的资源文件(如纹理、音效、模型等),并在需要时进行动态加载,是一项关键任务。

  • AI系统

构建复杂的人工智能系统,控制NPC行为和游戏世界的动态变化。

这些核心需求是否与Go的优势相契合呢?我们继续往下看。

2. Go语言的优势及应用场景

我们知道Go语言作为由Google开发的开源编程语言,自2009年问世以来,在多个领域获得了广泛的应用和认可。

715af54f52da40cbf8abb58432a97b65.png

Go的主要特点包括:

  • 简洁的语法和快速的编译速度

  • 内置的并发支持(goroutines和channels)

  • 强大的标准库

  • 跨平台编译能力

  • 垃圾回收机制

这些特性使得Go在云计算、Web服务、网络编程和并发处理等领域表现出色

然而,正是这些优势,却在游戏开发,包括AAA游戏开发中,变成了局限。下面我们基于黑神话的核心技术需求来看看Go在游戏开发方面的局限。

3. 从黑神话看Go语言在游戏开发中的局限性

作为一款备受期待的国产AAA大作,《黑神话:悟空》在开发过程中采用了高度优化的图形引擎和复杂的物理系统,这些技术需求与Go语言的设计理念存在较大的差距。

  • 图形渲染需求

对于像《黑神话:悟空》这样的游戏,实时渲染复杂的3D场景和角色模型对性能的要求极高。当前业界主流的游戏开发语言和引擎,如C++和Unreal Engine 5(虚幻5引擎),能够在内存分配、指针操作和底层硬件控制上实现精细优化。相比之下,Go的垃圾回收机制虽然简化了内存管理,但却容易在高频内存操作中带来延迟(内存分配和垃圾回收),这对于追求极致性能的AAA游戏来说是难以接受的。

下面写了两个简单程序,对比一下go与c++的内存分配性能:

// malloc-mem.go
// go build -o malloc-mem-go malloc-mem.go

package main

import (
    "fmt"
    "time"
)

func main() {
    const iterations = 1000 // 多次分配的次数
    start := time.Now()

    for i := 0; i < iterations; i++ {
        arr := make([]int, 1_000_000) // 每次分配一个大小为1000的数组
        for j := range arr {
            arr[j] = j
        }
    }

    elapsed := time.Since(start).Milliseconds()
    fmt.Printf("Go 分配内存时间: %d ms\n", elapsed)
}

// malloc-mem.cpp
// g++ -std=c++11 -O3  -o malloc-mem-cpp malloc-mem.cpp 

#include <iostream>
#include <chrono>
#include <vector>

int main() {
    const int iterations = 1000; // 多次分配的次数
    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < iterations; ++i) {
        std::vector<int> arr(1000000); // 每次分配一个大小为1000的数组
        for (size_t j = 0; j < arr.size(); ++j) {
            arr[j] = j;
        }
    }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::milli> elapsed = end - start;
    std::cout << "C++ 分配内存时间: " << elapsed.count() << " ms" << std::endl;

    return 0;
}

在我的linux虚拟机上,上述两个程序的输出结果如下:

$ ./malloc-mem-go
Go 分配内存时间: 1644 ms
$ ./malloc-mem-cpp
C++ 分配内存时间: 451.621 ms

我们看到:C++轻松击败Go!

此外,Go标准库虽然全面,但缺乏专门的游戏开发和图形处理库,多数是对C/C++图形库的Go binding,但由于cgo引入的额外性能开销,开发人员都不愿使用这样的binding。

  • 物理模拟

AAA游戏中的物理引擎不仅需要实时模拟角色动作和环境交互,还要求高精度的碰撞检测、布料模拟、流体动态等。C++由于能够直接访问底层硬件,并且通过手动管理内存实现高效计算,成为了开发物理引擎的首选。而Go虽然最初也是以系统编程语言身份诞生的,但真实情况是它的底层硬件控制能力较C++要弱上很多。Go语言的抽象层次较高,难以实现同等水平的优化,cgo又不受大家待见。

  • 多线程和并发处理

尽管Go在并发处理上有明显优势,但AAA游戏开发中的多线程并非仅是简单的任务并发,更需要对线程的调度、同步和共享内存的管理进行精细控制。C++允许开发者手动优化这些过程,而Go的goroutine虽然简便,但其自动化的调度策略往往难以达到AAA游戏中对性能的严格要求。

说到这里,很多Gopher已经感到“绝望”了,在游戏开发领域,Go在C++这样的霸主面前似乎“一无是处”啊。其实也不用这样,在游戏开发领域,尤其是AAA游戏开发领域,C++是一家独大的,即便像C、Rust这样的同等性能level的编程语言也是不抗打的。

那么Go在游戏开发领域就真的没有用武之地了么?也不见得,下面我们看看Go在游戏开发领域有哪些潜力可挖。

4. Go语言是否有机会进入游戏开发?

其实这是个妥妥的伪命题!

尽管Go不适合传统的AAA游戏开发,但它在一些特定的游戏开发领域中发挥作用,并且已经在大规模使用。早在GopherChina 2015年大会上,就有一家厦门的游戏公司分享了Go替换Erlang开发游戏服务端(页游和手游)的案例。

下面列出一些Go可以发挥作用的游戏开发领域:

  • 游戏服务器开发

Go在处理并发请求时表现优异,非常适合用于开发游戏的后端服务器,尤其是多人在线游戏的服务器部分,Go的高效并发和简洁性可以降低开发成本。国内很多手游/页游的服务端都是基于Go实现的。相信屏幕前的Gopher们就有不少从从事Go游戏服务端开发的。

  • 独立游戏或休闲游戏

对于对性能要求不如AAA游戏那么高的独立游戏和休闲游戏,Go语言的开发效率和跨平台能力可能会成为一种优势。目前Go社区在这一领域有很多成熟的开源引擎项目,比如著名的Ebiten[1],一个简单易用的 2D 游戏引擎,支持多平台(Windows、macOS、Linux、移动设备等)。在github已经收获万stars。并且在2024年还举办了Game Jam大会活动[2],显然发展的很不错!3D引擎较少,可用的包括:g3n[3]、raylib-go[4]等。

6143274f23d3d236cbd24e04f4dd610e.png

  • 跨平台工具或编辑器

Go的快速编译和执行速度,也使得它在开发游戏编辑器或跨平台工具时有一定的优势。

5. 小结

从《黑神话:悟空》这样一个AAA级游戏的技术需求来看,Go语言目前显然还无法满足这一领域的核心性能要求,未来大概率也不会满足。尽管Go在云计算、后端服务等领域大放异彩,但它在游戏开发领域,尤其是AAA级别的大作中,受限于性能、内存管理和生态系统等因素,难以与C++这样的AAA游戏老大竞争。

不过,Go语言的优势也并非完全无用武之地。随着游戏开发需求的多样化和服务器端的扩展,Go已经在游戏服务端、页游/手游等独立游戏方面发光发热,并占据了一席之地。对于那些对Go语言感兴趣的开发者而言,尽管在前台画面和底层性能上暂时无缘AAA游戏,但后端和辅助工具仍然是一个值得学习和探索的方向。

参考资料

[1] 

Ebiten: https://github.com/hajimehoshi/ebiten

[2] 

在2024年还举办了Game Jam大会活动: https://itch.io/jam/ebitengine-game-jam-2024

[3] 

g3n: https://github.com/g3n/engine

[4] 

raylib-go: https://github.com/gen2brain/raylib-go

[5] 

Gopher部落知识星球: https://public.zsxq.com/groups/51284458844544

[6] 

链接地址: https://m.do.co/c/bff6eed92687

- END -


推荐阅读:

6 个必须尝试的将代码转换为引人注目的图表的工具

Go 1.23新特性前瞻

Gopher的Rust第一课:第一个Rust程序

Go早期是如何在Google内部发展起来的

2024 Gopher Meetup 武汉站活动

go 中更加强大的 traces

「GoCN酷Go推荐」我用go写了魔兽世界登录器?

Go区不大,创造神话,科目三杀进来了

想要了解Go更多内容,欢迎扫描下方👇关注公众号,扫描 [实战群]二维码  ,即可进群和我们交流~


- 扫码即可加入实战群 -

72c597c9854dba168c77c054b160c355.png

1d23f514ed0befd8d4a174cf73c62909.png

分享、在看与点赞Go e096b7a890e91743578b61b86d609bcf.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值