前言
如果你想要制作Steam多人游戏,并且想要开始使用PurrNet,那么你来对地方了!
开始之前你可能需要先去了解:
- 【unity游戏开发------网络】基本知识
- 如何将你的游戏发布到steam平台?
- 【unity游戏开发------网络】unity对接steam,并上传发布游戏版本------Steamworks.NET
- 【unity游戏开发------网络】大大简化你的Steam对接 ------ Toolkit for Steamworks
- 【unity游戏开发------网络】一个免费、强大、性能优越且高度模块化的 Unity 网络库 ------ PurrNet的使用介绍
额外说明: 作为独立开发者,测试Steam连接通常很有挑战性,因为它需要两个Steam账户。有很多不同的方法可以单独测试,但为了本指南的目的,我假设你有一个朋友或队友可以帮助你测试。
开始之前
本指南使用以下环境编写:
- Unity 6002.2.6f1
- PurrNet 1.15.0
- Heathen's Toolkit for Steamworks 2025
- Steam已安装并运行中
如果你不熟悉Heathen's Toolkit for Steamworks SDK,我强烈建议你了解一下,如果你认真想用Steam的话------它会让你的生活更轻松。如果你不想使用Heathen's,那么我展示的脚本示例可能无法直接使用,但本指南的大部分内容仍然对你有帮助。我们将在本指南的最后安装Heathen's Toolkit,确保每个人都能跟上进度。
步骤1:创建场景
这是一个全新的项目,所以我将从创建一个新场景开始,并将其放在Assets/Scenes文件夹中。我将这个场景命名为"NetworkedSteamScene",并删除文件夹中已有的"SampleScene":

打开场景:

步骤2:创建网络管理器
在层级窗口任意位置右键点击,选择PurrNet → NetworkManager:

步骤3:配置游戏对象
点击新创建的PurrNet游戏对象,可以随意重命名;我更喜欢叫它"NetworkManager":

删除UDP传输组件并添加Steam传输组件:

如果你想了解更多关于Steam传输的信息,请参考Steam传输文档。
现在点击Steam传输组件上的"Add SteamWorks.Net to Package Manager"------这会将Steamworks.NET添加到你的项目中。如果出现错误,请确保你的机器上安装了git。
如果一切正常,你的设置应该看起来像这样:

让我们通过点击目标图标将网络规则添加到网络管理器组件,并添加默认规则:

如果你不知道这些规则是什么,只想让Steam正常工作,现在请选择"Unsafe"规则。这样做后,网络管理器会变成这样:

让我们将网络管理器配置成这样:

步骤4:脚本设置
这一步我们将使用Heathen's Toolkit for Steamworks来简化工作。如果你没有这个包,下面的代码对你仍然有用。我会注释哪些是Heathen's的API调用,这样你就知道哪些部分需要使用你正在使用的任何Steamworks API包装器来解决。现在让我们安装Heathen's Toolkit for Steamworks。下面是我的包管理器截图:

首先,我们需要创建一个Steam设置对象。如果你没有Heathen's,可以跳过这部分。以下是Heathen's网站上关于如何做到这一点的复制粘贴:
打开项目设置,选择Player > Steamworks

当你第一次这样做时,它会在你的项目设置文件夹中创建一个SteamMain Steam设置对象。

你可以选择添加演示设置和任意多个游戏测试设置。它们都会被添加到设置文件夹中自己的Steam设置对象中。
接下来,让我们添加一个画布,上面有"主机"和"加入"按钮,以及一个文本字段来显示主机ID(只有主机能看到)和一个客户端可以输入文本的输入框。这提示我安装TextMesh Pro,所以我安装了它:

接下来,让我们创建一个脚本来处理与Steam的连接。创建一个名为"ConnectionManager"的新脚本,并将其放在你的脚本文件夹中。

下面是一种松散的代码结构方式,但应该能让你对如何调整以适应自己的游戏有一些见解和直觉。看起来很长,但我保证实际上只有两个方法------我只是尽量让它尽可能清晰。
csharp
using Heathen.SteamworksIntegration;
using PurrNet;
using PurrNet.Steam;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace SteamExample {
/// <summary>
/// 这个类的目的是管理主机和客户端与Steam服务器的连接。它必须存在于
/// 连接到网络化场景的场景中的一个游戏对象上。如果你只有一个场景,那么
/// 它就存在于那个场景中。
/// </summary>
/// <remarks>
/// 我将StartHost()和StartClient()方法分开,试图让它们尽可能清晰。你可以
/// 自由地将它们重构到同一个方法中,或者按照你喜欢的任何方式组织它们。
/// 这绝不是一个万能的解决方案;而是你如何利用PurrNet和
/// Heathen.SteamworksIntegration一起与你的朋友在Steam上连接的示例。
/// </remarks>
public sealed class ConnectionManager : NetworkIdentity {
// 如果你直接将此复制到项目中,请确保拖放每个元素。
[SerializeField] private SteamSettings steamSettings;
[SerializeField] private Button hostButton;
[SerializeField] private Button clientButton;
[SerializeField] private TMP_Text hostTextField;
[SerializeField] private TMP_InputField clientInputField;
private void Awake() {
InstanceHandler.RegisterInstance(this);
DontDestroyOnLoad(this);
InitializeSteam();
}
private void OnEnable() {
hostButton?.onClick.AddListener(HandleHostClicked);
clientButton?.onClick.AddListener(HandleClientClicked);
}
private void OnDisable() {
hostButton?.onClick.RemoveListener(HandleHostClicked);
clientButton?.onClick.RemoveListener(HandleClientClicked);
}
protected override void OnDestroy() {
base.OnDestroy();
InstanceHandler.UnregisterInstance<ConnectionManager>();
}
/// <summary>
/// 这个方法的目的是初始化Steam。
/// </summary>
/// <remarks>
/// 我只是包装了一个方法吗?是的。但如果你正在制作Steam游戏,你可能
/// 出于某种原因想要在这里做更多的事情!所以再次强调,这只是一个示例,
/// 请随意重构以满足你的需求。
/// </remarks>
public void InitializeSteam() {
steamSettings.Initialize();
}
/// <summary>
/// 这个方法负责调用PurrNet的StartHost()方法。它还获取并配置
/// SteamTransport。它还利用Heathens的UserData结构来存储主机的Steam账户ID。
/// </summary>
/// <remarks>
/// 根据你的需要,可以自由地将这个方法设为public或private。
/// 在调用此方法之前,必须初始化Steam。
/// </remarks>
public void StartHost() {
var steamTransport = NetworkManager.main.transport as SteamTransport;
if (steamTransport == null) {
Debug.LogError("NetworkManager上缺少SteamTransport", this);
return;
}
// 这是一个Heathens API调用。
var user = UserData.Get();
steamTransport.peerToPeer = true;
steamTransport.dedicatedServer = false;
steamTransport.address = user.id.ToString();
NetworkManager.main.StartHost();
}
/// <summary>
/// 这个方法负责调用PurrNet的StartClient()方法。它还获取并配置
/// SteamTransport。它还利用Heathens的UserData结构来存储主机的Steam账户ID。
/// </summary>
/// <remarks>
/// 根据你的需要,可以自由地将这个方法设为public或private。
/// 在调用此方法之前,必须初始化Steam。
/// </remarks>
public void StartClient(string steamCode) {
var steamTransport = NetworkManager.main.transport as SteamTransport;
if (steamTransport == null) {
Debug.LogError("NetworkManager上缺少SteamTransport", this);
return;
}
if (string.IsNullOrEmpty(steamCode)) {
Debug.LogError("连接地址为空。", this);
return;
}
// 这是一个Heathens API调用。
var hostAddress = UserData.Get(steamCode);
if (!hostAddress.IsValid) {
Debug.LogError($"{hostAddress}是一个无效的连接地址。", this);
return;
}
steamTransport.peerToPeer = true;
steamTransport.dedicatedServer = false;
steamTransport.address = hostAddress.id.ToString();
NetworkManager.main.StartClient();
}
/// <summary>
/// 这个方法负责调用StartHost()并更改UI视觉效果。
/// </summary>
private void HandleHostClicked() {
if (hostButton == null || hostTextField == null) {
Debug.LogError("主机按钮或主机文本字段为空。请将它们拖放到ConnectionManager中。", this);
return;
}
StartHost();
if (NetworkManager.main.isOffline) {
hostTextField.text = "服务器离线";
hostButton.image.color = Color.red;
return;
}
hostTextField.text = UserData.Get().HexId;
hostButton.image.color = Color.green;
hostButton?.onClick.RemoveListener(HandleHostClicked);
clientButton?.onClick.RemoveListener(HandleClientClicked);
}
/// <summary>
/// 这个方法负责调用StartClient()并更改UI视觉效果。
/// </summary>
private void HandleClientClicked() {
if (string.IsNullOrEmpty(clientInputField.text)) {
clientInputField.text = "请输入主机的Steam十六进制ID。";
clientButton.image.color = Color.red;
return;
}
StartClient(clientInputField.text);
clientInputField.text = $"已连接到 {clientInputField.text}";
clientButton.image.color = Color.green;
clientButton?.onClick.RemoveListener(HandleHostClicked);
clientButton?.onClick.RemoveListener(HandleClientClicked);
}
}
}
让我们将这个脚本作为一个组件添加到一个空的游戏对象上,然后将我们的Steam设置、按钮和TMP对象拖放到它们的序列化字段中。

步骤5:应用程序ID
现在我们有了Steam传输设置,我们需要获取我们的应用程序ID。你可以通过访问Steamworks开发者仪表板来获取你的应用程序ID,或者如果你没有,可以使用Steam提供的"480"应用程序ID(Spacewar)。打开项目所在的文件夹,在根目录创建或修改"steam_appid.txt"文件,将你的ID放在里面并保存。

应用程序ID说明: 480应用程序ID是Steam用于开发和测试的免费应用程序ID。当你在Unity中启动游戏时,Steam会自动显示你正在玩"Spacewar"游戏。这是故意的,应该在你向Steam注册游戏并获得自己的应用程序ID之前使用。你可以在此处了解更多信息:Steam API示例
步骤6:测试
现在我们已经设置好了一切,终于可以测试我们的Steam连接了。按下播放按钮,你应该在控制台中看到一系列初始化消息:

按下主机按钮,如果PurrNet服务器正在运行,你应该在文本字段中看到你的主机ID。你也可以点击网络管理器,确认玩家数量为1并且你已连接:

如果你使用朋友或队友进行测试,请让他们在Unity编辑器中或通过构建版本连接,并提供你的主机ID。如果他们连接成功,他们的屏幕将如下所示:

恭喜!你已成功连接到Steam,并准备好继续你的多人游戏之旅!
专栏推荐
完结
好了,我是向宇,博客地址:https://xiangyu.blog.csdn.net,如果学习过程中遇到任何问题,也欢迎你评论私信找我。
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!
