Multi person detection test
I have tested the Intel D435i camera using the skeleton example and it picked up 3 people (out of 6 present). Since the space where this wall interaction will be installed is not as spacious the 3 person limit is good enough.
The game interaction
I currently have a simple endless runner that works for 1 person. I have made it so the person can move left/right, jump and crouch a bit and the character they control will also move as they do.
Since the controls now work I wanted to tackle the multi user part of the game.
In the image, on the left side in the hierarchy, you can see a bunch of players, I tested how the split screen would look like. The Player is a gameObject with a Camera and a 3D player character model. It also has a PlayerMove script attached to it which takes in a reference to the 3D player character model so I can switch between playing the jump/crouch/run animations. I’m using a sphere as a joint (currently purple but will be invisible in the end).
This is the PlayerMove script
public class PlayerMove : MonoBehaviour
{
[SerializeField] float moveSpeed = 3f;
[SerializeField] float strafeSpeed = 4f;
public static bool canMove = true;
public bool isJumping = false;
public bool comingDown = false;
public bool isRolling = false;
public GameObject playerObject; //reference to the player so we can play the animations
public nuitrack.JointType[] typeJoint;
GameObject[] CreatedJoint;
public GameObject PrefabJoint;
private float setMovementInY = 0.32f;
private float moveDirection = 0;
private float startYaxisPosition;
private bool userDetected = false;
void Start()
{
CreatedJoint = new GameObject[typeJoint.Length];
for (int q = 0; q < typeJoint.Length; q++)
{
CreatedJoint[q] = Instantiate(PrefabJoint);
CreatedJoint[q].transform.SetParent(transform);
CreatedJoint[q].transform.localScale = new Vector3(0.55f, 0.275f, 0.55f);
CreatedJoint[q].transform.localPosition = new Vector3(0, 0, 0);
}
}
void FixedUpdate()
{
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime, Space.World);
if (canMove){ //canMove is not used yet, will be used when in the menu screens
if (NuitrackManager.Users.Current != null && NuitrackManager.Users.Current.Skeleton != null){
for (int q = 0; q < typeJoint.Length; q++){
UserData.SkeletonData.Joint joint = NuitrackManager.Users.Current.Skeleton.GetJoint(typeJoint[q]);
if (!userDetected){
userDetected = true;
startYaxisPosition = joint.Position.y;
}
//moveDirection - multiplying the joint position and dividing by how fast we move
moveDirection = joint.Position.x * LevelBoundry.rightSide / strafeSpeed;
//we can move left/right only when we are inside the LevelBoundry values, say -10 and 10
if (transform.position.x >= LevelBoundry.leftSide && transform.position.x <= LevelBoundry.rightSide){
transform.Translate(moveDirection / strafeSpeed, 0, 0);
}
//if we overshoot the left boundry set the value to LeftBoundry value
if (transform.position.x <= LevelBoundry.leftSide){
transform.position = new Vector3(LevelBoundry.leftSide, setMovementInY, transform.position.z);
}
//if we overshoot the right boundry set the value to RightBoundry value
if (transform.position.x >= LevelBoundry.rightSide){
transform.position = new Vector3(LevelBoundry.rightSide, setMovementInY, transform.position.z);
}
//Jumping implementation. Torso (joint) needs to make a difference of 0.2f to be detected as a jump. Also prevent rolling during a jump
if (joint.Position.y - startYaxisPosition > 0.2f && !isJumping){
if (!isJumping && !isRolling){
isJumping = true;
playerObject.GetComponent<Animator>().Play("Running Forward Flip");
StartCoroutine(JumpRollSequence());
}
}
//Rolling/crouching implementation. Torso (joint) needs to make a difference of negative 0.2f to be detected as a roll/crouch. Also prevent jumping during a roll
if (joint.Position.y - startYaxisPosition < -0.2f && !isRolling){
if (!isJumping && !isRolling){
isRolling = true;
playerObject.GetComponent<Animator>().Play("Sprinting Forward Roll");
StartCoroutine(JumpRollSequence());
}
}
}
}
}
if(isJumping){
if(comingDown == false){
transform.Translate(Vector3.up * Time.deltaTime * 3, Space.World);
}
else{
transform.Translate(Vector3.up * Time.deltaTime * -3, Space.World);
}
}
if (isRolling){
if (comingDown == false){
transform.Translate(Vector3.up * Time.deltaTime * -0.5f, Space.World);
}
else{
transform.Translate(Vector3.up * Time.deltaTime * 0.5f, Space.World);
}
}
}
IEnumerator JumpRollSequence(){
yield return new WaitForSeconds(0.45f);
comingDown = true;
yield return new WaitForSeconds(0.45f);
isJumping = false;
isRolling = false;
comingDown = false;
playerObject.GetComponent<Animator>().Play("Slow Run");
}
}
However, I don’t want to get ahead of myself so I need some guidance on how I could implement multiple users that would be locked to a Player character until the game ends. But first how could I determine who from the people that the camera sees is player 1,2,3? I could add a menu before the game start that would require from participants to push a button to indicate they want to play, could the user ID be “locked in” to one of the player characters in this way?
I tried the SkeletonAvatar example and the script works as you can easily set the User ID. However, at runtime, each SkeletonAvatar script makes a SkeletonRoot game object that consists of joint prefabs and connection lines (not what I want and this can be seen in the image hierarchy and game view).
Since the SkeletonAvatar inherits from BaseAvatar which Inherits from TrackedUser I made the PlayerMove inherit from TrackedUser instead of MonoBehaviour like in the script above. This gave me the User ID which I could change on each Player inside the editor. However, I was still controlling both player characters. Since I was testing alone I at least expected the player character with User ID set to 2, to not move(only run straight), so what am I missing?