Skip to content

CSharp Module tweak & Unity Tutorial part 1, 2b, 3 tweaks #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c392094
expanded on taggedenums and added examples for each special ReducerKind
Lethalchip May 23, 2024
0b8ddcb
fixed part2 hyperlinks
Lethalchip May 23, 2024
0d5bf51
fixed config version type
Lethalchip May 23, 2024
2b6ba63
update Throw => throw
Lethalchip May 23, 2024
6b13554
update log typo
Lethalchip May 23, 2024
e728730
fix type on connect reducerkind from init=>connect
Lethalchip May 23, 2024
e669ffb
private=>public for UpdatePlayerLoginState reducer
Lethalchip May 23, 2024
ead920d
remove double "publish" condenses it into one publish at the end afte…
Lethalchip May 23, 2024
cf1b2c7
fixed name of GameManager file, tweaks to instructions
Lethalchip May 23, 2024
82110db
fixed onConnectError
Lethalchip May 23, 2024
fdfea0b
more TutorialGameManager renames to BitcraftMiniGameManager.cs and al…
Lethalchip May 23, 2024
1974a04
added clarity to UIUsernameChooser.cs and LocalPlayer.cs -- Also fixe…
Lethalchip May 23, 2024
9aed263
some small tweaks again to GameManager name
Lethalchip May 23, 2024
eb284ec
updated tagged enums to reflect record usage and pattern matching
Lethalchip Jun 14, 2024
af55f08
filter -> find fixes
Lethalchip Jun 14, 2024
cf047b6
expanded on taggedenums and added examples for each special ReducerKind
Lethalchip May 23, 2024
0da635d
fixed config version type
Lethalchip May 23, 2024
8e708d6
update Throw => throw
Lethalchip May 23, 2024
cdaea7d
update log typo
Lethalchip May 23, 2024
a1dd444
fix type on connect reducerkind from init=>connect
Lethalchip May 23, 2024
b96c06b
private=>public for UpdatePlayerLoginState reducer
Lethalchip May 23, 2024
b7816aa
remove double "publish" condenses it into one publish at the end afte…
Lethalchip May 23, 2024
96d1eaa
fixed name of GameManager file, tweaks to instructions
Lethalchip May 23, 2024
6aaa2b9
fixed onConnectError
Lethalchip May 23, 2024
b1bf5e9
more TutorialGameManager renames to BitcraftMiniGameManager.cs and al…
Lethalchip May 23, 2024
b95b213
added clarity to UIUsernameChooser.cs and LocalPlayer.cs -- Also fixe…
Lethalchip May 23, 2024
3c04122
some small tweaks again to GameManager name
Lethalchip May 23, 2024
2bede0b
updated tagged enums to reflect record usage and pattern matching
Lethalchip Jun 14, 2024
d9a5fad
filter -> find fixes
Lethalchip Jun 14, 2024
ab42d18
Merge branch 'csharp-module-updates-and-unity-tutorial-fixes' of http…
Lethalchip Jun 18, 2024
f3f3981
Merge branch 'master' into csharp-module-updates-and-unity-tutorial-f…
Lethalchip Jun 18, 2024
4e5a813
updated based on feedback
Lethalchip Jun 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions docs/modules/c-sharp/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public static void AddIn5Minutes(ReducerContext e, string name, int age)

#### Special reducers

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:
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:

- `ReducerKind.Init` - this reducer will be invoked when the module is first published.
- `ReducerKind.Update` - this reducer will be invoked when the module is updated.
Expand All @@ -337,4 +337,21 @@ public static void Init()
{
Log("...and we're live!");
}
```

[SpacetimeDB.Reducer(ReducerKind.Update)]
public static void Update()
{
Log("Update get!");
}

[SpacetimeDB.Reducer(ReducerKind.Connect)]
public static void OnConnect(DbEventArgs ctx)
{
Log($"{ctx.Sender} has connected from {ctx.Address}!");
}

[SpacetimeDB.Reducer(ReducerKind.Disconnect)]
public static void OnDisconnect(DbEventArgs ctx)
{
Log($"{ctx.Sender} has disconnected.");
}```
4 changes: 2 additions & 2 deletions docs/unity/part-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,5 @@ We chose ECS for this example project because it promotes scalability, modularit

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

- [Rust](part-2a-rust)
- [C#](part-2b-c-sharp)
- [Rust](part-2a-rust.md)
- [C#](part-2b-csharp.md)
19 changes: 6 additions & 13 deletions docs/unity/part-2b-c-sharp.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Then we are going to start by adding the global `Config` table. Right now it onl
public partial class Config
{
[SpacetimeDB.Column(ColumnAttrs.PrimaryKey)]
public Identity Version;
public uint Version;
public string? MessageOfTheDay;
}
```
Expand Down Expand Up @@ -133,8 +133,8 @@ public static void CreatePlayer(ReducerContext ctx, string username)
}
catch
{
Log("Error: Failed to create a unique PlayerComponent", LogLevel.Error);
Throw;
Log("Error: Failed to create a unique EntityComponent", LogLevel.Error);
throw;
}

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

---

### Publishing a Module to SpacetimeDB

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.

```bash
cd server
spacetime publish -c unity-tutorial
```

### Finally, Add Chat Support

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.
Expand Down Expand Up @@ -335,11 +326,13 @@ public static void SendChatMessage(ReducerContext ctx, string text)

## Wrapping Up

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

Now that we added chat support, let's publish the latest module version to SpacetimeDB, assuming we're still in the `server` dir:
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.

```bash
cd server
spacetime publish -c unity-tutorial
```

Expand Down
26 changes: 14 additions & 12 deletions docs/unity/part-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ The Unity SpacetimeDB SDK relies on there being a `NetworkManager` somewhere in

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

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:
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:

**Append to the top of TutorialGameManager.cs**
**Append to the top of BitcraftMiniGameManager.cs**

```csharp
using SpacetimeDB;
Expand All @@ -46,7 +46,7 @@ using System.Linq;

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

**Append to the top of TutorialGameManager class inside of TutorialGameManager.cs**
**Append to the top of BitcraftMiniGameManager class inside of BitcraftMiniGameManager.cs**

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

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

**REPLACE the Start() function in TutorialGameManager.cs**
**REPLACE the Start() function in BitcraftMiniGameManager.cs**

```csharp
// Start is called before the first frame update
void Start()
{
instance = this;

Application.runInBackground = true;

SpacetimeDBClient.instance.onConnect += () =>
{
Debug.Log("Connected.");
Expand All @@ -86,7 +88,7 @@ void Start()
// Called when we have an error connecting to SpacetimeDB
SpacetimeDBClient.instance.onConnectError += (error, message) =>
{
Debug.LogError($"Connection error: " + message);
Debug.LogError($"Connection error: {error} - {message}");
};

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

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.

**Append after the Start() function in TutorialGameManager.cs**
**Append after the Start() function in BitcraftMiniGameManager.cs**

```csharp
void OnSubscriptionApplied()
Expand All @@ -148,7 +150,7 @@ void OnSubscriptionApplied()

### Adding the Multiplayer Functionality

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`.
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`.

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

Expand All @@ -171,7 +173,7 @@ public void ButtonPressed()
}
```

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.
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.

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

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

Expand Down Expand Up @@ -246,21 +248,21 @@ private void EntityComponent_OnUpdate(EntityComponent oldObj, EntityComponent ob

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`.

**Append to bottom of Start() function in TutorialGameManager.cs:**
**Append to bottom of Start() function in BitcraftMiniGameManager.cs:**

```csharp
PlayerComponent.OnInsert += PlayerComponent_OnInsert;
```

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.

**Append to bottom of TutorialGameManager class in TutorialGameManager.cs:**
**Append to bottom of TutorialGameManager class in BitcraftMiniGameManager.cs:**

```csharp
private void PlayerComponent_OnInsert(PlayerComponent obj, ReducerEvent callInfo)
{
// If the identity of the PlayerComponent matches our user identity then this is the local player
if(obj.OwnerId == local_identity)
if(obj.Identity == local_identity)
{
// Now that we have our initial position we can start the game
StartGame();
Expand Down