MasterMemory
Embedded Typed Readonly In-Memory Document Database for .NET and Unity. (by Cysharp)
Steamworks.NET
Steamworks wrapper for Unity / C# (by rlabrecque)
Our great sponsors
MasterMemory | Steamworks.NET | |
---|---|---|
2 | 8 | |
1,401 | 2,567 | |
3.4% | - | |
3.0 | 4.9 | |
8 days ago | about 1 month ago | |
C# | C# | |
MIT License | MIT License |
The number of mentions indicates the total number of mentions that we've tracked plus the number of user suggested alternatives.
Stars - the number of stars that a project has on GitHub. Growth - month over month growth in stars.
Activity is a relative number indicating how actively a project is being developed. Recent commits have higher weight than older ones.
For example, an activity of 9.0 indicates that a project is amongst the top 10% of the most actively developed projects that we are tracking.
Stars - the number of stars that a project has on GitHub. Growth - month over month growth in stars.
Activity is a relative number indicating how actively a project is being developed. Recent commits have higher weight than older ones.
For example, an activity of 9.0 indicates that a project is amongst the top 10% of the most actively developed projects that we are tracking.
MasterMemory
Posts with mentions or reviews of MasterMemory.
We have used some of these posts to build our list of alternatives
and similar projects.
-
Persistent hash maps for C#
A dramatically more powerful and performant read only store would be something like https://github.com/Cysharp/MasterMemory
-
Nothing says "your code sucks" like implementing a save system
if you really need something like a database in game take something more optimized which can work object orientated https://github.com/Cysharp/MasterMemory or go straight with serialization to file from a list of serializable interfaces in a list.
Steamworks.NET
Posts with mentions or reviews of Steamworks.NET.
We have used some of these posts to build our list of alternatives
and similar projects. The last one was on 2022-03-13.
- How do you get more than four controllers to work with Steam Input and the new input system?
- Should I review my own game? (Still not published on Steam)
-
Networking solution for a turn based strategy in Unity?
You have a lot of options for networking (yes, the example you mentioned works well under peer-to-peer). I ended up using Steamworks.NET because it's pretty directly tied to the Steam SDK. It also let me match to my friends right on Steam (guessing you and your friends use it).
-
Photon Pun 2 Multiplayer Controlling the Same Player
using Photon.Pun; using Photon.Realtime; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using Hashtable = ExitGames.Client.Photon.Hashtable; //Steamworks.Net repo - https://github.com/rlabrecque/Steamworks.NET.git?path=/com.rlabrecque.steamworks.net#20.1.0 public class PlayerController : MonoBehaviourPunCallbacks, IDamageable { [SerializeField] Image healthbarImage; [SerializeField] GameObject ui; [SerializeField] GameObject cameraHolder; [SerializeField] float mouseSensitivity, sprintSpeed, walkSpeed, jumpForce, smoothTime; public Slider sensSlider; public GameObject musicSource; [SerializeField] Item[] items; int itemIndex; int previousItemIndex = -1; float verticalLookRotation; Vector3 smoothMoveVelocity; Rigidbody rb; PhotonView PV; const float maxHealth = 100f; float currentHealth = maxHealth; PlayerManager playerManager; GunSystem gunSystem; public AudioSource damageSound; [Header("Movement")] private float moveSpeed; public float groundDrag; [Header("Jumping")] public float jumpCooldown; public float airMultiplier; bool readyToJump; [Header("Keybinds")] public KeyCode sprintKey = KeyCode.LeftShift; [Header("Ground Check")] public float playerHeight; public LayerMask whatIsGround; bool grounded; [Header("Slope Handling")] public float maxSlopeAngle; private RaycastHit slopeHit; private bool exitingSlope; public Transform orientation; float horizontalInput; float verticalInput; Vector3 moveDirection; public float slip; public float noSlip; Collider collider; public MovementState state; public enum MovementState { walking, sprinting, air } void Awake() { PV = GetComponent(); rb = GetComponent(); collider = GetComponent(); } void Start() { playerManager = PhotonView.Find((int)PV.InstantiationData[0]).GetComponent(); if (PV.IsMine) { EquipItem(0); } else { Destroy(GetComponentInChildren().gameObject); Destroy(rb); Destroy(ui); Destroy(musicSource); } readyToJump = true; mouseSensitivity = PlayerPrefs.GetFloat("Sensitivity", mouseSensitivity); sensSlider.value = mouseSensitivity; } void Update() { grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround); if(!Pause.isPaused) { MyInput(); } if(!PV.IsMine) { return; } else { if (grounded) rb.drag = groundDrag; else rb.drag = 0; } if(!PV.IsMine) return; if(!Pause.isPaused) { Look(); } for(int i = 0; i < items.Length; i++) { if(Input.GetKeyDown((i + 1).ToString())) { ResetItemIndex(); EquipItem(i); items[i].GetComponent().enabled = true; break; } } if(Input.GetAxisRaw("Mouse ScrollWheel") > 0f) { if(itemIndex >= items.Length - 1) { ResetItemIndex(); EquipItem(0); items[0].GetComponent().enabled = true; } else { ResetItemIndex(); EquipItem(itemIndex + 1); items[itemIndex].GetComponent().enabled = true; } } else if(Input.GetAxisRaw("Mouse ScrollWheel") < 0f) { if(itemIndex <= 0) { ResetItemIndex(); EquipItem(items.Length - 1); items[items.Length - 1].GetComponent().enabled = true; } else { ResetItemIndex(); EquipItem(itemIndex - 1); items[itemIndex].GetComponent().enabled = true; } } items[itemIndex].Use(); if(transform.position.y < -3f) // Die if you fall out of the world { Die(); } } void FixedUpdate() { if (!PV.IsMine) return; if(!Pause.isPaused) { SpeedControl(); StateHandler(); MovePlayer(); NoSlip(); } } private void Look() { if (!PV.IsMine) return; transform.Rotate(Vector3.up * Input.GetAxisRaw("Mouse X") * mouseSensitivity); verticalLookRotation += Input.GetAxisRaw("Mouse Y") * mouseSensitivity; verticalLookRotation = Mathf.Clamp(verticalLookRotation, -90f, 90f); cameraHolder.transform.localEulerAngles = Vector3.left * verticalLookRotation; } private void MyInput() { if (!PV.IsMine) return; horizontalInput = Input.GetAxisRaw("Horizontal"); verticalInput = Input.GetAxisRaw("Vertical"); // when to jump if(Input.GetButtonDown("Jump") && readyToJump && grounded) { readyToJump = false; Jump(); Invoke(nameof(ResetJump), jumpCooldown); } } void NoSlip() { if(rb.velocity.x == 0 && rb.velocity.y == 0 && rb.velocity.z == 0) { collider.material.dynamicFriction = noSlip; collider.material.staticFriction = noSlip; } else { collider.material.dynamicFriction = slip; collider.material.staticFriction = slip; } } private void StateHandler() { // Mode - Sprinting if(grounded && Input.GetKey(sprintKey) || Input.GetButton("XBOX_LJP")) { state = MovementState.sprinting; moveSpeed = sprintSpeed; } // Mode - Walking else if (grounded) { state = MovementState.walking; moveSpeed = walkSpeed; } // Mode - Air else { state = MovementState.air; } } private void MovePlayer() { // calculate movement direction moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput; // on slope if (OnSlope() && !exitingSlope) { rb.AddForce(GetSlopeMoveDirection() * moveSpeed * 20f, ForceMode.Force); if (rb.velocity.y > 0) rb.AddForce(Vector3.down * 80f, ForceMode.Force); } // on ground else if(grounded) rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force); // in air else if(!grounded) rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force); // turn gravity off while on slope rb.useGravity = !OnSlope(); } private void SpeedControl() { // limiting speed on slope if (OnSlope() && !exitingSlope) { if (rb.velocity.magnitude > moveSpeed) rb.velocity = rb.velocity.normalized * moveSpeed; } // limiting speed on ground or in air else { Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z); // limit velocity if needed if (flatVel.magnitude > moveSpeed) { Vector3 limitedVel = flatVel.normalized * moveSpeed; rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z); } } } private void Jump() { exitingSlope = true; // reset y velocity rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); rb.AddForce(transform.up * jumpForce, ForceMode.Impulse); } private void ResetJump() { readyToJump = true; exitingSlope = false; } private bool OnSlope() { if(Physics.Raycast(transform.position, Vector3.down, out slopeHit, playerHeight * 0.5f + 0.3f)) { float angle = Vector3.Angle(Vector3.up, slopeHit.normal); return angle < maxSlopeAngle && angle != 0; } return false; } private Vector3 GetSlopeMoveDirection() { return Vector3.ProjectOnPlane(moveDirection, slopeHit.normal).normalized; } void EquipItem(int _index) { if(_index == previousItemIndex) return; itemIndex = _index; items[itemIndex].itemGameObject.SetActive(true); if(previousItemIndex != -1) { items[previousItemIndex].itemGameObject.SetActive(false); } previousItemIndex = itemIndex; if(PV.IsMine) { Hashtable hash = new Hashtable(); hash.Add("itemIndex", itemIndex); PhotonNetwork.LocalPlayer.SetCustomProperties(hash); } } public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) { if(!PV.IsMine && targetPlayer == PV.Owner) { EquipItem((int)changedProps["itemIndex"]); } } public void TakeDamage(float damage) { PV.RPC("RPC_TakeDamage", RpcTarget.All, damage); } [PunRPC] void RPC_TakeDamage(float damage) { if(!PV.IsMine) return; damageSound.Play(); currentHealth -= damage; healthbarImage.fillAmount = currentHealth / maxHealth; if(currentHealth <= 0) { Die(); } } void Die() { playerManager.Die(); } public void Sensitivity() { mouseSensitivity = sensSlider.value; PlayerPrefs.SetFloat("Sensitivity", mouseSensitivity); } void ResetItemIndex() { for (int j = 0; j < items.Length; j++) { items[j].GetComponent().enabled = false; } } }
-
Steamworks multiplayer - Godot vs Unity
I have a multiplayer game on steam made with Godot C# and Steamworks.NET wrapper https://steamworks.github.io/.
-
Steamworks.NET issue with "ExchangeItems"
Hi, I am using Steamworks.NET for my game, I'm near releasing it and I have an issue. I use the "ExchangeItems" function for my game so players can earn cosmetics, The function consumes the crate (that the player opens), and the output is a generator with a bundle. The issue/error I get is: k_EResultFail, and the crate doesn't get consumed and I don't earn any items.
-
I made a C# Steamworks.NET Template for macOS and Windows
I put together a repository you can borrow if you want to make a C# Godot game that uses Steamworks.NET on either Mac or Windows.
-
How do you create a game with Steam Workshop in mind?
Also, C# wrapper https://github.com/rlabrecque/Steamworks.NET
What are some alternatives?
When comparing MasterMemory and Steamworks.NET you can also consider the following projects:
Entitas - Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
Facepunch.Steamworks - Another fucking c# Steamworks implementation
MessagePack for C# (.NET, .NET Core, Unity, Xamarin) - Extremely Fast MessagePack Serializer for C#(.NET, .NET Core, Unity, Xamarin). / msgpack.org[C#]
Steamworks.NET-Test - Test project for Steamworks.NET
MagicOnion - Unified Realtime/API framework for .NET platform and Unity.
GameTemplate - C# Godot game template with Steamworks.NET ready out-of-the-box.
ILSpy - .NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
ZeroFormatter - Infinitely Fast Deserializer for .NET, .NET Core and Unity.
MasterMemory vs Entitas
Steamworks.NET vs Facepunch.Steamworks
MasterMemory vs MessagePack for C# (.NET, .NET Core, Unity, Xamarin)
Steamworks.NET vs Steamworks.NET-Test
MasterMemory vs MagicOnion
Steamworks.NET vs GameTemplate
MasterMemory vs ILSpy
Steamworks.NET vs MessagePack for C# (.NET, .NET Core, Unity, Xamarin)
MasterMemory vs ZeroFormatter
Steamworks.NET vs ILSpy