【Rust】RustでWebAPIを作って、UnityクライアントからAPIコールしてみる【Unity】
こんにちは。最近涼しくなってきて嬉しいホンジョウです。
今回はRustでWebAPIを作ってみたくなったので、作っていこうと思います。
Webフレームワークは、Axumを使ってみようと思います。
Axum GitHubリポジトリ
インストール方法に関してはこちらをご確認ください。
本当はもっと綺麗にクラス分けをして書きたいところですが、一旦動作確認的にMonoBehaviourでベタ書きしてしまいます。
あとはSceneにUIを作成して、実行できるようにしましょう。APIからUserデータを取得していることを確認できました。
今回はベタ書きのJSONを返すだけのAPIでしたが、DBからデータを取得したりするのも試してみたいと思います。ご覧いただきありがとうございました。
今回はRustでWebAPIを作ってみたくなったので、作っていこうと思います。
Webフレームワークは、Axumを使ってみようと思います。
Axum GitHubリポジトリ
開発環境
- macOS 13.4 Ventura
- rustc 1.72.0
- cargo 1.72.0
- Unity 2022.2.21
インストール方法に関してはこちらをご確認ください。
Cargo.tomlの編集
今回使用していくパッケージをCargo.tomlに記述していきます
[package]
name = "rust_web_api"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
axum = "0.6.1"
tokio = { version = "1.23.0", features = ["full"] }
serde = { version = "1.0.149", features = ["derive"] }
serde_json = "1.0.89"
Rustプロジェクトのディレクトリ構成
src/
├ controller/
│ ├ mod.rs
│ └ users.rs
└ main.rs
mod.rsの記述
pub mod users;
users.rsの記述
users.rsにはレスポンスに含めるUser構造体と、Userを生成してJSONに変換し、IntoResponseにして返す関数を用意します。
use axum::{
response::Json,
response::IntoResponse,
http::StatusCode
};
use serde::Serialize;
use serde_json::json;
#[derive(Serialize)]
struct User {
name: String,
hp: u32,
atk: u32,
def: u32,
spd: u32
}
pub async fn get_users() -> impl IntoResponse {
let user = User {
name: "test_name".to_string(),
hp: 100,
atk: 10,
def: 20,
spd: 30,
};
(StatusCode::OK, Json(json!(user)))
}
main.rsの記述
今回はGETメソッドのAPIだけを用意します。
use axum::{
routing::get,
Router,
response::Json,
response::IntoResponse,
http::StatusCode
};
use serde_json::json;
use std::net::SocketAddr;
mod controller;
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/", get(root))
.route("/users", get(controller::users::get_users));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
async fn root() -> impl IntoResponse {
(
StatusCode::OK,
Json(json!("OK"))
)
}
この時点で実行してみて、問題なくJSONが返ってくるようであれば、「RustでWebAPIを作ってみた」はこれにて完成です。 それでは次にUnityクライアント側の処理を書いていきましょう。
Unityプロジェクトのディレクトリ構成
Assets/
└ Scripts/
├ SceneInitializer.cs
├ User.cs
└ UserInfoView.cs
User.csの記述
ここではAPIレスポンスから受け取るUserのデータを格納するUserクラスを書いていきます。
using System;
using UnityEngine;
[Serializable]
public sealed class User
{
[SerializeField] string name;
[SerializeField] int hp;
[SerializeField] int atk;
[SerializeField] int def;
[SerializeField] int spd;
public string Name => name;
public int Hp => hp;
public int Atk => atk;
public int Def => def;
public int Spd => spd;
}
UserInfoView.cs
こちらはUnityの画面上にUserのデータを表示するUI用のクラスになります。
using UnityEngine;
using UnityEngine.UI;
public sealed class UserInfoView : MonoBehaviour
{
[SerializeField] Text name;
[SerializeField] Text hp;
[SerializeField] Text atk;
[SerializeField] Text def;
[SerializeField] Text spd;
public void UpdateUserInfo(User user)
{
name.text = "Name: " + user.Name;
hp.text = "HP: " + user.Hp.ToString();
atk.text = "ATK: " + user.Atk.ToString();
def.text = "DEF: " + user.Def.ToString();
spd.text = "SPD: " + user.Spd.ToString();
}
}
SceneInitializer.csの記述
ここでゲームの開始時にAPIからデータを取得して、UIに反映させる処理を書いていきます。本当はもっと綺麗にクラス分けをして書きたいところですが、一旦動作確認的にMonoBehaviourでベタ書きしてしまいます。
using System;
using System.Net;
using System.Net.Http;
using Cysharp.Threading.Tasks;
using UnityEngine;
public class SceneInitializer : MonoBehaviour
{
[SerializeField] UserInfoView view;
readonly HttpClient httpClient = new();
void Start()
{
StartAsync().Forget();
}
async UniTaskVoid StartAsync()
{
var response = await httpClient.GetAsync("http://127.0.0.1:3000/users");
var json = await response.Content.ReadAsStringAsync();
if(response.StatusCode == HttpStatusCode.OK)
{
var user = JsonUtility.FromJson(json);
view.UpdateUserInfo(user);
}
}
}
Sceneの作成と実行
あとはSceneにUIを作成して、実行できるようにしましょう。APIからUserデータを取得していることを確認できました。
今回はベタ書きのJSONを返すだけのAPIでしたが、DBからデータを取得したりするのも試してみたいと思います。ご覧いただきありがとうございました。