Skip to content

Commit 6317ec1

Browse files
authored
CSharp Module tweak & Unity Tutorial part 1, 2b, 3 tweaks (#56)
* expanded on taggedenums and added examples for each special ReducerKind Fixed a few typos/mistakes here and there also. * fixed part2 hyperlinks * fixed config version type from Identity to uint * update Throw => throw * update log typo * fix type on connect reducerkind from init=>connect * private=>public for UpdatePlayerLoginState reducer * remove double "publish" condenses it into one publish at the end after chat * fixed name of GameManager file, tweaks to instructions kept application.runInBackground (it wasn't included) renamed many instances of "TutorialGameManager.cs" to "BitcraftMiniGameManager.cs" to represent accurate filename * fixed onConnectError * more TutorialGameManager renames to BitcraftMiniGameManager.cs and also a FilterByX fix * added clarity to UIUsernameChooser.cs and LocalPlayer.cs -- Also fixed RemotePlayer.cs errors * some small tweaks again to GameManager name * updated tagged enums to reflect record usage and pattern matching * filter -> find fixes * expanded on taggedenums and added examples for each special ReducerKind Fixed a few typos/mistakes here and there also. * fixed config version type from Identity to uint * update Throw => throw * update log typo * fix type on connect reducerkind from init=>connect * private=>public for UpdatePlayerLoginState reducer * remove double "publish" condenses it into one publish at the end after chat * fixed name of GameManager file, tweaks to instructions kept application.runInBackground (it wasn't included) renamed many instances of "TutorialGameManager.cs" to "BitcraftMiniGameManager.cs" to represent accurate filename * fixed onConnectError * more TutorialGameManager renames to BitcraftMiniGameManager.cs and also a FilterByX fix * added clarity to UIUsernameChooser.cs and LocalPlayer.cs -- Also fixed RemotePlayer.cs errors * some small tweaks again to GameManager name * updated tagged enums to reflect record usage and pattern matching * filter -> find fixes * updated based on feedback
1 parent 4e15ed1 commit 6317ec1

File tree

4 files changed

+41
-29
lines changed

4 files changed

+41
-29
lines changed

docs/docs/modules/c-sharp/index.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ public static void AddIn5Minutes(ReducerContext e, string name, int age)
321321

322322
#### Special reducers
323323

324-
These are two special kinds of reducers that can be used to respond to module lifecycle events. They're stored in the `SpacetimeDB.Module.ReducerKind` class and can be used as an argument to the `[SpacetimeDB.Reducer]` attribute:
324+
These are four special kinds of reducers that can be used to respond to module lifecycle events. They're stored in the `SpacetimeDB.Module.ReducerKind` class and can be used as an argument to the `[SpacetimeDB.Reducer]` attribute:
325325

326326
- `ReducerKind.Init` - this reducer will be invoked when the module is first published.
327327
- `ReducerKind.Update` - this reducer will be invoked when the module is updated.
@@ -337,4 +337,21 @@ public static void Init()
337337
{
338338
Log("...and we're live!");
339339
}
340-
```
340+
341+
[SpacetimeDB.Reducer(ReducerKind.Update)]
342+
public static void Update()
343+
{
344+
Log("Update get!");
345+
}
346+
347+
[SpacetimeDB.Reducer(ReducerKind.Connect)]
348+
public static void OnConnect(DbEventArgs ctx)
349+
{
350+
Log($"{ctx.Sender} has connected from {ctx.Address}!");
351+
}
352+
353+
[SpacetimeDB.Reducer(ReducerKind.Disconnect)]
354+
public static void OnDisconnect(DbEventArgs ctx)
355+
{
356+
Log($"{ctx.Sender} has disconnected.");
357+
}```

docs/docs/unity/part-1.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,5 @@ We chose ECS for this example project because it promotes scalability, modularit
119119

120120
From here, the tutorial continues with your favorite server module language of choice:
121121

122-
- [Rust](part-2a-rust)
123-
- [C#](part-2b-c-sharp)
122+
- [Rust](part-2a-rust.md)
123+
- [C#](part-2b-csharp.md)

docs/docs/unity/part-2b-c-sharp.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Then we are going to start by adding the global `Config` table. Right now it onl
4141
public partial class Config
4242
{
4343
[SpacetimeDB.Column(ColumnAttrs.PrimaryKey)]
44-
public Identity Version;
44+
public uint Version;
4545
public string? MessageOfTheDay;
4646
}
4747
```
@@ -133,8 +133,8 @@ public static void CreatePlayer(ReducerContext ctx, string username)
133133
}
134134
catch
135135
{
136-
Log("Error: Failed to create a unique PlayerComponent", LogLevel.Error);
137-
Throw;
136+
Log("Error: Failed to create a unique EntityComponent", LogLevel.Error);
137+
throw;
138138
}
139139

140140
// The PlayerComponent uses the same entity_id and stores the identity of
@@ -275,15 +275,6 @@ In a fully developed game, the server would typically perform server-side valida
275275

276276
---
277277

278-
### Publishing a Module to SpacetimeDB
279-
280-
Now that we've written the code for our server module and reached a clean checkpoint, we need to publish it to SpacetimeDB. This will create the database and call the init reducer. In your terminal or command window, run the following commands.
281-
282-
```bash
283-
cd server
284-
spacetime publish -c unity-tutorial
285-
```
286-
287278
### Finally, Add Chat Support
288279

289280
The client project has a chat window, but so far, all it's used for is the message of the day. We are going to add the ability for players to send chat messages to each other.
@@ -335,11 +326,13 @@ public static void SendChatMessage(ReducerContext ctx, string text)
335326

336327
## Wrapping Up
337328

329+
### Publishing a Module to SpacetimeDB
338330
💡View the [entire lib.cs file](https://gist.github.com/dylanh724/68067b4e843ea6e99fbd297fe1a87c49)
339331

340-
Now that we added chat support, let's publish the latest module version to SpacetimeDB, assuming we're still in the `server` dir:
332+
Now that we've written the code for our server module and reached a clean checkpoint, we need to publish it to SpacetimeDB. This will create the database and call the init reducer. In your terminal or command window, run the following commands.
341333

342334
```bash
335+
cd server
343336
spacetime publish -c unity-tutorial
344337
```
345338

docs/docs/unity/part-3.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ The Unity SpacetimeDB SDK relies on there being a `NetworkManager` somewhere in
3434

3535
![Unity-AddNetworkManager](/images/unity-tutorial/Unity-AddNetworkManager.JPG)
3636

37-
Next we are going to connect to our SpacetimeDB module. Open `TutorialGameManager.cs` in your editor of choice and add the following code at the top of the file:
37+
Next we are going to connect to our SpacetimeDB module. Open `Assets/_Project/Game/BitcraftMiniGameManager.cs` in your editor of choice and add the following code at the top of the file:
3838

39-
**Append to the top of TutorialGameManager.cs**
39+
**Append to the top of BitcraftMiniGameManager.cs**
4040

4141
```csharp
4242
using SpacetimeDB;
@@ -46,7 +46,7 @@ using System.Linq;
4646

4747
At the top of the class definition add the following members:
4848

49-
**Append to the top of TutorialGameManager class inside of TutorialGameManager.cs**
49+
**Append to the top of BitcraftMiniGameManager class inside of BitcraftMiniGameManager.cs**
5050

5151
```csharp
5252
// These are connection variables that are exposed on the GameManager
@@ -64,14 +64,16 @@ The first three fields will appear in your Inspector so you can update your conn
6464

6565
Now add the following code to the `Start()` function. For clarity, replace your entire `Start()` function with the function below.
6666

67-
**REPLACE the Start() function in TutorialGameManager.cs**
67+
**REPLACE the Start() function in BitcraftMiniGameManager.cs**
6868

6969
```csharp
7070
// Start is called before the first frame update
7171
void Start()
7272
{
7373
instance = this;
7474

75+
Application.runInBackground = true;
76+
7577
SpacetimeDBClient.instance.onConnect += () =>
7678
{
7779
Debug.Log("Connected.");
@@ -86,7 +88,7 @@ void Start()
8688
// Called when we have an error connecting to SpacetimeDB
8789
SpacetimeDBClient.instance.onConnectError += (error, message) =>
8890
{
89-
Debug.LogError($"Connection error: " + message);
91+
Debug.LogError($"Connection error: {error} - {message}");
9092
};
9193

9294
// Called when we are disconnected from SpacetimeDB
@@ -123,7 +125,7 @@ The "local client cache" is a client-side view of the database defined by the su
123125

124126
Next we write the `OnSubscriptionApplied` callback. When this event occurs for the first time, it signifies that our local client cache is fully populated. At this point, we can verify if a player entity already exists for the corresponding user. If we do not have a player entity, we need to show the `UserNameChooser` dialog so the user can enter a username. We also put the message of the day into the chat window. Finally we unsubscribe from the callback since we only need to do this once.
125127

126-
**Append after the Start() function in TutorialGameManager.cs**
128+
**Append after the Start() function in BitcraftMiniGameManager.cs**
127129

128130
```csharp
129131
void OnSubscriptionApplied()
@@ -148,7 +150,7 @@ void OnSubscriptionApplied()
148150

149151
### Adding the Multiplayer Functionality
150152

151-
Now we have to change what happens when you press the "Continue" button in the name dialog window. Instead of calling start game like we did in the single player version, we call the `create_player` reducer on the SpacetimeDB module using the auto-generated code. Open `UIUsernameChooser.cs`.
153+
Now we have to change what happens when you press the "Continue" button in the name dialog window. Instead of calling start game like we did in the single player version, we call the `create_player` reducer on the SpacetimeDB module using the auto-generated code. Open `Assets/_Project/Username/UIUsernameChooser.cs`.
152154

153155
**Append to the top of UIUsernameChooser.cs**
154156

@@ -171,7 +173,7 @@ public void ButtonPressed()
171173
}
172174
```
173175

174-
We need to create a `RemotePlayer` script that we attach to remote player objects. In the same folder as `LocalPlayer.cs`, create a new C# script called `RemotePlayer`. In the start function, we will register an OnUpdate callback for the `EntityComponent` and query the local cache to get the player’s initial position. **Make sure you include a `using SpacetimeDB.Types;`** at the top of the file.
176+
We need to create a `RemotePlayer` script that we attach to remote player objects. In the same folder as `Assets/_Project/Player/LocalPlayer.cs`, create a new C# script called `RemotePlayer`. In the start function, we will register an OnUpdate callback for the `EntityComponent` and query the local cache to get the player’s initial position. **Make sure you include a `using SpacetimeDB.Types;`** at the top of the file.
175177

176178
First append this using to the top of `RemotePlayer.cs`
177179

@@ -203,7 +205,7 @@ public class RemotePlayer : MonoBehaviour
203205
PlayerComponent? playerComp = PlayerComponent.FindByEntityId(EntityId);
204206
if (playerComp is null)
205207
{
206-
string inputUsername = UsernameElement.Text;
208+
string inputUsername = UsernameElement.text;
207209
Debug.Log($"PlayerComponent not found - Creating a new player ({inputUsername})");
208210
Reducer.CreatePlayer(inputUsername);
209211

@@ -246,21 +248,21 @@ private void EntityComponent_OnUpdate(EntityComponent oldObj, EntityComponent ob
246248

247249
Next we need to handle what happens when a `PlayerComponent` is added to our local cache. We will handle it differently based on if it’s our local player entity or a remote player. We are going to register for the `OnInsert` event for our `PlayerComponent` table. Add the following code to the `Start` function in `TutorialGameManager`.
248250

249-
**Append to bottom of Start() function in TutorialGameManager.cs:**
251+
**Append to bottom of Start() function in BitcraftMiniGameManager.cs:**
250252

251253
```csharp
252254
PlayerComponent.OnInsert += PlayerComponent_OnInsert;
253255
```
254256

255257
Create the `PlayerComponent_OnInsert` function which does something different depending on if it's the component for the local player or a remote player. If it's the local player, we set the local player object's initial position and call `StartGame`. If it's a remote player, we instantiate a `PlayerPrefab` with the `RemotePlayer` component. The start function of `RemotePlayer` handles initializing the player position.
256258

257-
**Append to bottom of TutorialGameManager class in TutorialGameManager.cs:**
259+
**Append to bottom of TutorialGameManager class in BitcraftMiniGameManager.cs:**
258260

259261
```csharp
260262
private void PlayerComponent_OnInsert(PlayerComponent obj, ReducerEvent callInfo)
261263
{
262264
// If the identity of the PlayerComponent matches our user identity then this is the local player
263-
if(obj.OwnerId == local_identity)
265+
if(obj.Identity == local_identity)
264266
{
265267
// Now that we have our initial position we can start the game
266268
StartGame();

0 commit comments

Comments
 (0)