First prototype RoboidSite support working

This commit is contained in:
Pascal Serrarens 2024-11-19 13:22:59 +01:00
parent 40a8ef2e4d
commit 28926a1507
15 changed files with 794 additions and 26 deletions

View File

@ -34,7 +34,7 @@ namespace Passer.Humanoid {
public override void OnInspectorGUI() { public override void OnInspectorGUI() {
serializedObject.Update(); serializedObject.Update();
#if !hNW_UNET && !hNW_PHOTON && !hNW_MIRROR && !hNW_BOLT #if !hNW_UNET && !hNW_PHOTON && !hNW_MIRROR && !hNW_BOLT && !hNW_ROBOID
EditorGUILayout.HelpBox("Networking Support is disabled. Check Preferences to enable it.", MessageType.Warning); EditorGUILayout.HelpBox("Networking Support is disabled. Check Preferences to enable it.", MessageType.Warning);
#else #else

View File

@ -6,7 +6,7 @@ using UnityEngine;
namespace Passer.Humanoid { namespace Passer.Humanoid {
#pragma warning disable 0618 #pragma warning disable 0618
#if hNW_UNET || hNW_MIRROR || hNW_PHOTON || hNW_BOLT #if hNW_UNET || hNW_MIRROR || hNW_PHOTON || hNW_BOLT || hNW_ROBOID
public partial class HumanoidPlayer { public partial class HumanoidPlayer {
[SerializeField] [SerializeField]

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c951b29def0f4d240a2a7bef87502741
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,578 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
using System.Runtime.Serialization;
#if hNW_ROBOID
using Passer.LinearAlgebra;
namespace Passer.Humanoid {
public partial class HumanoidPlayer : MonoBehaviour, IHumanoidNetworking {
[SerializeField]
protected float _sendRate = 25;
public float sendRate {
get { return _sendRate; }
}
[SerializeField]
protected bool _createLocalRemotes = false;
public bool createLocalRemotes {
get { return _createLocalRemotes; }
set { _createLocalRemotes = value; }
}
public int nssPort = 7681;
protected UdpClient udpClient;
protected IPEndPoint endPoint;
protected object obj;
protected AsyncCallback receiveCallback;
ConcurrentQueue<HumanoidNetworking.IMessage> messageQueue = new ConcurrentQueue<HumanoidNetworking.IMessage>();
public byte networkId;
#region Dummy Interface
public void Send(bool b) { }
public void Send(byte b) { }
public void Send(int x) { }
public void Send(float f) { }
public void Send(Vector3 v) { }
public void Send(Quaternion q) { }
public bool ReceiveBool() {
return false;
}
public byte ReceiveByte() {
return 0;
}
public int ReceiveInt() {
return 0;
}
public float ReceiveFloat() {
return 0;
}
public Vector3 ReceiveVector3() {
return Vector3.zero;
}
public Quaternion ReceiveQuaternion() {
return Quaternion.identity;
}
public ulong GetObjectIdentity(GameObject obj) {
return 0;
}
public GameObject GetGameObject(ulong objIdentity) {
return this.gameObject;
}
public void InstantiateHumanoid(HumanoidControl humanoid) {
if (debug <= HumanoidNetworking.DebugLevel.Info)
DebugLog("Send Instantiate Humanoid " + humanoid.humanoidId);
HumanoidNetworking.InstantiateHumanoid instantiateHumanoid = new HumanoidNetworking.InstantiateHumanoid(humanoid);
if (createLocalRemotes)
this.Receive(instantiateHumanoid);
}
public void DestroyHumanoid(HumanoidControl humanoid) { }
public void Grab(HandTarget handTarget, GameObject obj, bool rangeCheck, HandTarget.GrabType grabType = HandTarget.GrabType.HandGrab) { }
public void LetGo(HandTarget handTarget) { }
public void ChangeAvatar(HumanoidControl humanoid, string avatarPrefabName, string possessionLocation = null) {
if (debug <= HumanoidNetworking.DebugLevel.Info)
Debug.Log(humanoid.nwId + ": Change Avatar: " + avatarPrefabName);
HumanoidNetworking.ChangeAvatar changeAvatar = new HumanoidNetworking.ChangeAvatar(humanoid, avatarPrefabName, possessionLocation);
if (createLocalRemotes)
this.Receive(changeAvatar);
}
public void SyncTrackingSpace(HumanoidControl humanoid) { }
public void ReenableNetworkSync(GameObject obj) { }
public void DisableNetworkSync(GameObject obj) { }
public void DebugLog(string s) {
Debug.Log(s);
}
public void DebugWarning(string s) {
Debug.LogWarning(s);
}
public void DebugError(string s) {
Debug.LogError(s);
}
public HumanoidNetworking.Smoothing smoothing => HumanoidNetworking.Smoothing.None;
private bool _isLocal;
public bool isLocal => _isLocal; // may need to implement this
public ulong nwId => 0;
public HumanoidNetworking.HumanoidPose lastHumanoidPose { get => null; set { return; } }
public List<HumanoidControl> humanoids { get; set; }
#endregion Dummy Interface
protected virtual void Awake() {
mInstance = this;
GameObject.DontDestroyOnLoad(this.gameObject);
humanoids = HumanoidNetworking.FindLocalHumanoids();
for (int i = 0; i < humanoids.Count; i++) {
HumanoidControl humanoid = humanoids[i];
if (humanoid.isRemote)
continue;
humanoid.humanoidNetworking = this;
}
endPoint = new IPEndPoint(IPAddress.Any, nssPort + 3);
udpClient = new UdpClient(endPoint);
receiveCallback = new AsyncCallback(Receiver);
udpClient.BeginReceive(receiveCallback, obj);
}
protected void OnApplicationQuit() {
if (udpClient != null) {
udpClient.Client.Close();
udpClient.Close();
udpClient = null;
}
}
#region Update
float lastSend;
protected virtual void LateUpdate() {
while (messageQueue.TryDequeue(out HumanoidNetworking.IMessage msg)) {
ProcessMessage(msg);
}
if (Time.time > lastSend + 1 / sendRate) {
if (humanoids != null) {
foreach (HumanoidControl humanoid in humanoids) {
if (!humanoid.isRemote) {
UpdateHumanoidPose(humanoid);
}
}
}
lastSend = Time.time;
}
}
protected virtual void ProcessMessage(HumanoidNetworking.IMessage msg) {
switch (msg) {
case NetworkIdMsg networkId:
ProcessNetworkId(networkId);
break;
}
}
void Receiver(IAsyncResult result) {
// Take care of buffered messages after the client has been closed
if (udpClient == null || udpClient.Client.Connected == false)
return;
byte[] data = (udpClient.EndReceive(result, ref endPoint));
ReceivePacket(data);
udpClient.BeginReceive(receiveCallback, obj);
}
void ReceivePacket(byte[] data) {
byte msgId = data[0];
switch (msgId) {
case 0xA1: // (161) Network Id
this.ReceiveNetworkId(data); break;
}
}
#endregion Update
#region NetworkId
public class NetworkIdMsg : HumanoidNetworking.IMessage {
public const byte msgId = 0xA1;
public byte networkId = 0;
public NetworkIdMsg(byte networkId) {
this.networkId = networkId;
}
public NetworkIdMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
MemoryStream ms = new();
BinaryWriter bw = new(ms);
bw.Write(msgId);
bw.Write(this.networkId); // Thing Id
byte[] data = ms.ToArray();
return data;
}
public override void Deserialize(byte[] data) {
base.Deserialize(data);
this.networkId = (byte)data[1];
}
}
public void ReceiveNetworkId(byte[] data) {
NetworkIdMsg msg = new(data);
this.networkId = msg.networkId;
messageQueue.Enqueue(msg);
}
private void ProcessNetworkId(NetworkIdMsg msg) {
GameObject networkingObj = this.GetGameObject(msg.networkId);
if (networkingObj == null) {
if (this.debug <= HumanoidNetworking.DebugLevel.Error)
this.DebugLog("Could not find Networking for Instantiate Humanoid " + msg.networkId + "/0");
return;
}
HumanoidControl remoteHumanoid = humanoids[0]; //FindRemoteHumanoid(humanoids, 0);
if (remoteHumanoid == null) {
if (debug <= HumanoidNetworking.DebugLevel.Warning)
DebugLog("Remote Humanoid " + msg.networkId + "/" + 0 + "not found");
return;
}
SendThing(remoteHumanoid);
SendName(remoteHumanoid, 0, "Humanoid");
SendModel(remoteHumanoid, "https://gitlab.passervr.com/passer/models/humanoid/-/raw/main/MakeHumanPasserMedium.glb?ref_type=heads&inline=false");
SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.upperLeg);
SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.lowerLeg);
SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.foot);
SendSubThing(remoteHumanoid, remoteHumanoid.leftFootTarget.toes);
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.upperLeg);
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.lowerLeg);
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.foot);
SendSubThing(remoteHumanoid, remoteHumanoid.rightFootTarget.toes);
}
#endregion
#region Thing
protected class ThingMsg : HumanoidNetworking.IMessage {
private const byte msgId = 0x80;
public const byte length = 3;
public byte thingId;
public byte thingType;
public ThingMsg(byte thingId, byte thingType) {
this.thingId = thingId;
this.thingType = thingType;
}
public ThingMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] data = new byte[3];
data[0] = msgId;
data[1] = thingId;
data[2] = thingType;
return data;
}
public override void Deserialize(byte[] data) {
try {
uint ix = 0;
thingId = data[ix++];
thingType = data[ix++];
}
catch { }
}
}
public void SendThing(HumanoidControl humanoid) {
if (debug <= HumanoidNetworking.DebugLevel.Debug)
Debug.Log("Send Thing " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
ThingMsg thingMsg = new(0, 1);
if (udpClient != null) {
byte[] data = thingMsg.Serialize();
udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
}
}
#endregion Thing
#region SubThing
protected class SubThingMsg : HumanoidNetworking.IMessage {
private const byte msgId = 0x12; // (18)
public const byte length = 3 + 4;
public byte thingId;
public byte parentId;
readonly Vector3 position;
public SubThingMsg(byte thingId, byte parentId, Vector3 position) {
this.thingId = thingId;
this.parentId = parentId;
this.position = position;
}
public SubThingMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] data = new byte[7];
data[0] = msgId;
data[1] = thingId;
data[2] = parentId;
data[3] = 0;
data[4] = 0;
data[5] = 0;
data[6] = 0;
return data;
}
//public override void Deserialize(byte[] data) {
// try {
// uint ix = 0;
// thingId = data[ix++];
// thingType = data[ix++];
// }
// catch { }
//}
}
public void SendSubThing(HumanoidControl humanoid, HumanoidTarget.TargetedBone bone) {
if (debug <= HumanoidNetworking.DebugLevel.Debug)
Debug.Log("Send SubThing " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
SubThingMsg thingMsg = new((byte)bone.boneId, (byte)bone.parent.boneId, bone.bone.transform.position);
if (udpClient != null) {
byte[] data = thingMsg.Serialize();
udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
}
SendName(humanoid, (byte)bone.boneId, bone.bone.transform.name);
}
#endregion
#region Name
public class NameMsg : HumanoidNetworking.IMessage {
public const byte msgId = 0x91; // (145) Name
public byte networkId = 0;
public byte thingId;
public byte len;
public string name;
public NameMsg(byte thingId, string name) {
this.thingId = thingId;
this.name = name;
}
public NameMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
MemoryStream ms = new();
BinaryWriter bw = new(ms);
bw.Write(msgId); // 145 Name Msg
bw.Write((byte)thingId); // Thing Id
bw.Write((byte)name.Length);
for (int ix = 0; ix < name.Length; ix++)
bw.Write(name[ix]);
byte[] data = ms.ToArray();
return data;
}
public override void Deserialize(byte[] data) {
uint ix = 0;
this.thingId = data[ix++];
int strlen = data[ix++];
this.name = System.Text.Encoding.UTF8.GetString(data, (int)ix, strlen);
}
}
public void SendName(HumanoidControl humanoid, byte thingId, string name) {
if (debug <= HumanoidNetworking.DebugLevel.Debug)
Debug.Log("Send Name " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
NameMsg nameMsg = new(thingId, name); // humanoid.name;
if (udpClient != null) {
byte[] data = nameMsg.Serialize();
udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
}
}
#endregion
#region Model
class ModelUrlMsg : HumanoidNetworking.IMessage {
public const byte msgId = 0x90; // (144) Model URL
public byte objectId;
public Vector3 position;
public float scale;
public string url;
public ModelUrlMsg(string url) {
this.url = url;
}
public ModelUrlMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
MemoryStream ms = new();
BinaryWriter bw = new(ms);
bw.Write(msgId); // 145 Name Msg
bw.Write((byte)0x00); // Thing Id
bw.Write((byte)0x00); // Dummy position
bw.Write((byte)0x00);
bw.Write((byte)0x00);
bw.Write((byte)0x00);
SendFloat16(bw, 1.0f);
bw.Write((byte)url.Length);
for (int ix = 0; ix < url.Length; ix++)
bw.Write(url[ix]);
byte[] data = ms.ToArray();
return data;
}
//public override void Deserialize(byte[] data) {
// uint ix = 0;
// this.objectId = data[ix++];
// //this.position = ReceiveVector3(data, ref ix);
// this.position = ReceiveSpherical(data, ref ix);
// this.scale = ReceiveFloat16(data, ref ix);
// int strlen = data[ix++];
// url = System.Text.Encoding.UTF8.GetString(data, (int)ix, strlen);
//}
}
public void SendModel(HumanoidControl humanoid, string url) {
if (debug <= HumanoidNetworking.DebugLevel.Debug)
Debug.Log("Send Name " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
ModelUrlMsg msg = new(url); // humanoid.name;
if (udpClient != null) {
byte[] data = msg.Serialize();
udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
}
}
#endregion Model
#region Pose
[Serializable]
public class RoboidBonePose : HumanoidNetworking.HumanoidPose {
private readonly byte msgId = 0x10;
readonly byte boneId;
readonly Quat32 boneOrientation;
public RoboidBonePose(HumanoidTarget.TargetedBone targetedBone) {
this.boneId = (byte)targetedBone.boneId;
this.boneOrientation = new Quat32(targetedBone.bone.transform.localRotation);
}
public override byte[] Serialize() {
byte[] data = new byte[11];
data[0] = msgId;
data[1] = boneId;
data[2] = 0x03; // Pose_orientation
//data[3][4][5][6] are 0
data[7] = boneOrientation.qx;
data[8] = boneOrientation.qy;
data[9] = boneOrientation.qz;
data[10] = boneOrientation.qw;
return data;
}
}
[Serializable]
public class RoboidPose : HumanoidNetworking.HumanoidPose {
readonly Quat32 headOrientation;
public RoboidPose(HumanoidControl humanoid) {
headOrientation = new Quat32(humanoid.headTarget.head.bone.transform.rotation);
}
public override byte[] Serialize() {
MemoryStream ms = new();
BinaryWriter bw = new(ms);
bw.Write((byte)0x10); // PoseMsg
bw.Write((byte)this.head.boneId); // Thing Id
bw.Write((byte)0x03); // Pose_Orientation
bw.Write((byte)0x00); // Dummy data
bw.Write((byte)0x00);
bw.Write((byte)0x00);
bw.Write((byte)0x00);
SendQuat32(bw, headOrientation);
byte[] data = ms.ToArray();
return data;
}
}
public virtual void UpdateHumanoidPose(HumanoidControl humanoid) {
if (debug <= HumanoidNetworking.DebugLevel.Debug)
Debug.Log("Send Pose Humanoid " + humanoid.humanoidId + " nwId: " + humanoid.nwId);
RoboidPose humanoidPose = new(humanoid);
if (createLocalRemotes)
this.Receive(humanoidPose);
if (udpClient != null) {
byte[] data = humanoidPose.Serialize();
udpClient.Send(data, data.Length, "127.0.0.1", nssPort);
}
SendBone(humanoid.leftFootTarget.upperLeg);
SendBone(humanoid.leftFootTarget.lowerLeg);
SendBone(humanoid.leftFootTarget.foot);
SendBone(humanoid.rightFootTarget.upperLeg);
SendBone(humanoid.rightFootTarget.lowerLeg);
SendBone(humanoid.rightFootTarget.foot);
}
private void SendBone(HumanoidTarget.TargetedBone bone) {
RoboidBonePose bonePose = new(bone);
byte[] buffer = bonePose.Serialize();
udpClient.Send(buffer, buffer.Length, "127.0.0.1", nssPort);
}
#endregion Pose
#region Send
static void SendQuat32(BinaryWriter bw, Quat32 q) {
bw.Write((byte)q.qx);
bw.Write((byte)q.qy);
bw.Write((byte)q.qz);
bw.Write((byte)q.qw);
}
static void SendFloat16(BinaryWriter bw, float f) {
bw.Write((byte)0x3C); // Dummy value 1
bw.Write((byte)0x00);
}
#endregion Send
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3438587d9f577c241a381273590f7f70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,40 @@
using System.IO;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
namespace Passer {
public class RoboidStarter : INetworkingStarter {
//public int nssPort = 7681;
//protected UdpClient udpClient;
//protected IPEndPoint endPoint;
//protected Stream dataStream;
GameObject INetworkingStarter.GetHumanoidPrefab() {
GameObject humanoidPrefab = Resources.Load<GameObject>("HumanoidPlayer");
return humanoidPrefab;
}
void INetworkingStarter.StartClient(NetworkingStarter nwStarter) {
((INetworkingStarter)this).StartClient(nwStarter, nwStarter.roomName, nwStarter.gameVersion);
}
void INetworkingStarter.StartClient(NetworkingStarter nwStarter, string roomName, int gameVersion) {
//endPoint = new IPEndPoint(IPAddress.Any, nssPort);
//udpClient = new UdpClient(endPoint);
GameObject humanoidPrefab = Resources.Load<GameObject>("HumanoidPlayer");
GameObject.Instantiate(humanoidPrefab);
}
void INetworkingStarter.StartHost(NetworkingStarter nwStarter) {
((INetworkingStarter)this).StartClient(nwStarter);
}
void INetworkingStarter.StopClient() {
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f298f6b069bcb040ac8bcf621c853b3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
using UnityEngine;
namespace Passer.LinearAlgebra {
public class Spherical16 {
public float distance;
public float horizontal;
public float vertical;
public Spherical16(float distance, float horizontal = 0, float vertical = 0) {
this.distance = distance;
this.horizontal = horizontal;
this.vertical = vertical;
}
public static Spherical16 FromVector3(Vector3 v) {
float distance = v.magnitude;
if (distance == 0.0f) {
return new Spherical16(distance);
}
else {
float verticalAngle = Mathf.PI / 2 - Mathf.Acos(v.y / distance) * Mathf.Rad2Deg;
float horizontalAngle = Mathf.Atan2(v.x, v.z) * Mathf.Rad2Deg;
return new Spherical16(distance, horizontalAngle, verticalAngle);
}
}
}
public class Quat32 {
public byte qx;
public byte qy;
public byte qz;
public byte qw;
public Quat32(Quaternion q) {
int qx = (int)(q.x * 127 + 128);
int qy = (int)(q.y * 127 + 128);
int qz = (int)(q.z * 127 + 128);
int qw = (int)(q.w * 255);
if (q.w < 0) {
qx = -qx;
qy = -qy;
qz = -qz;
qw = -qw;
}
this.qx = (byte)(qx);
this.qy = (byte)(qy);
this.qz = (byte)(qz);
this.qw = (byte)(qw);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 79bdc65d83f2c8e43bac904e283c6c46
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -63,6 +63,12 @@ namespace Passer.Humanoid {
lowerLeg = new TargetedLowerLegBone(this); lowerLeg = new TargetedLowerLegBone(this);
foot = new TargetedFootBone(this); foot = new TargetedFootBone(this);
toes = new TargetedToesBone(this); toes = new TargetedToesBone(this);
subTargets = new TargetedBone[] {
upperLeg,
lowerLeg,
foot,
toes
};
this.isLeft = isLeft; this.isLeft = isLeft;
this.side = isLeft ? Side.Left : Side.Right; this.side = isLeft ? Side.Left : Side.Right;
@ -120,9 +126,9 @@ namespace Passer.Humanoid {
#if hVIVETRACKER #if hVIVETRACKER
public ViveTrackerLeg viveTracker = new ViveTrackerLeg(); public ViveTrackerLeg viveTracker = new ViveTrackerLeg();
#endif #endif
//#if hNEURON //#if hNEURON
// public PerceptionNeuronLeg neuron = new PerceptionNeuronLeg(); // public PerceptionNeuronLeg neuron = new PerceptionNeuronLeg();
//#endif //#endif
#if hKINECT1 #if hKINECT1
public Kinect1Leg kinect1 = new Kinect1Leg(); public Kinect1Leg kinect1 = new Kinect1Leg();
#endif #endif
@ -200,6 +206,8 @@ namespace Passer.Humanoid {
get { return foot; } get { return foot; }
} }
private TargetedBone[] subTargets;
#region UpperLeg #region UpperLeg
public TargetedUpperLegBone upperLeg; public TargetedUpperLegBone upperLeg;
@ -210,6 +218,7 @@ namespace Passer.Humanoid {
public TargetedUpperLegBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.lowerLeg) { public TargetedUpperLegBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.lowerLeg) {
this.footTarget = footTarget; this.footTarget = footTarget;
this.parent = footTarget.humanoid.hipsTarget.hips;
} }
public override void Init() { public override void Init() {
@ -254,6 +263,7 @@ namespace Passer.Humanoid {
public TargetedLowerLegBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.foot) { public TargetedLowerLegBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.foot) {
this.footTarget = footTarget; this.footTarget = footTarget;
this.parent = footTarget.upperLeg;
} }
public override void Init() { public override void Init() {
@ -289,6 +299,7 @@ namespace Passer.Humanoid {
#endregion #endregion
#region Foot #region Foot
public TargetedFootBone foot; public TargetedFootBone foot;
[System.Serializable] [System.Serializable]
@ -297,6 +308,7 @@ namespace Passer.Humanoid {
public TargetedFootBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.toes) { public TargetedFootBone(FootTarget footTarget) : base(footTarget.humanoid, footTarget.toes) {
this.footTarget = footTarget; this.footTarget = footTarget;
this.parent = footTarget.lowerLeg;
} }
public override void Init() { public override void Init() {
@ -368,6 +380,7 @@ namespace Passer.Humanoid {
public TargetedToesBone(FootTarget footTarget) : base(footTarget.humanoid) { public TargetedToesBone(FootTarget footTarget) : base(footTarget.humanoid) {
this.footTarget = footTarget; this.footTarget = footTarget;
this.parent = footTarget.foot;
} }
public override void Init() { public override void Init() {
@ -801,12 +814,13 @@ namespace Passer.Humanoid {
} }
footTarget = footTargetTransform.GetComponent<FootTarget>(); footTarget = footTargetTransform.GetComponent<FootTarget>();
if (footTarget == null) { if (footTarget == null)
footTarget = footTargetTransform.gameObject.AddComponent<FootTarget>(); footTarget = footTargetTransform.gameObject.AddComponent<FootTarget>();
footTarget.Constructor(humanoid, isLeft);
}
} }
if (footTarget.subTargets == null)
footTarget.Constructor(humanoid, isLeft);
if (isLeft) if (isLeft)
humanoid.leftFootTarget = footTarget; humanoid.leftFootTarget = footTarget;
else else

View File

@ -402,6 +402,13 @@ namespace Passer.Humanoid {
public TargetedShoulderBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.upperArm) { public TargetedShoulderBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.upperArm) {
this.handTarget = handTarget; this.handTarget = handTarget;
if (handTarget.humanoid == null || handTarget.humanoid.hipsTarget == null)
this.parent = null;
else
this.parent = (handTarget.humanoid.hipsTarget.chest.bone.transform != null) ?
handTarget.humanoid.hipsTarget.chest :
handTarget.humanoid.hipsTarget.hips;
bone.jointLimitations = true; bone.jointLimitations = true;
} }
@ -471,6 +478,7 @@ namespace Passer.Humanoid {
public TargetedUpperArmBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.forearm) { public TargetedUpperArmBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.forearm) {
this.handTarget = handTarget; this.handTarget = handTarget;
this.parent = handTarget.shoulder;
} }
public override void Init() { public override void Init() {
@ -527,6 +535,7 @@ namespace Passer.Humanoid {
public TargetedForearmBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.hand) { public TargetedForearmBone(HandTarget handTarget) : base(handTarget.humanoid, handTarget.hand) {
this.handTarget = handTarget; this.handTarget = handTarget;
this.parent = handTarget.upperArm;
} }
public override void Init() { public override void Init() {
@ -589,6 +598,7 @@ namespace Passer.Humanoid {
public TargetedHandBone(HandTarget handTarget) : base(handTarget.humanoid) { public TargetedHandBone(HandTarget handTarget) : base(handTarget.humanoid) {
this.handTarget = handTarget; this.handTarget = handTarget;
this.parent = handTarget.forearm;
} }
public override void Init() { public override void Init() {
@ -1372,12 +1382,13 @@ namespace Passer.Humanoid {
} }
handTarget = handTargetTransform.GetComponent<HandTarget>(); handTarget = handTargetTransform.GetComponent<HandTarget>();
if (handTarget == null) { if (handTarget == null)
handTarget = handTargetTransform.gameObject.AddComponent<HandTarget>(); handTarget = handTargetTransform.gameObject.AddComponent<HandTarget>();
handTarget.Constructor(humanoid, isLeft);
}
} }
if (handTarget.subTargets == null)
handTarget.Constructor(humanoid, isLeft);
if (isLeft) if (isLeft)
humanoid.leftHandTarget = handTarget; humanoid.leftHandTarget = handTarget;
else else

View File

@ -71,10 +71,20 @@ namespace Passer.Humanoid {
/// <param name="humanoid">The humanoid for this head target</param> /// <param name="humanoid">The humanoid for this head target</param>
public void Constructor(HumanoidControl humanoid) { public void Constructor(HumanoidControl humanoid) {
this.humanoid = humanoid; this.humanoid = humanoid;
neck = new TargetedNeckBone(this); this.neck = new TargetedNeckBone(this);
head = new TargetedHeadBone(this); this.head = new TargetedHeadBone(this);
#if hFACE #if hFACE
face = new FaceTarget(this); face = new FaceTarget(this);
subTargets = new TargetedBone[] {
neck,
head,
face
};
#else
subTargets = new TargetedBone[] {
neck,
head
};
#endif #endif
} }
@ -306,6 +316,7 @@ namespace Passer.Humanoid {
public override TargetedBone main { public override TargetedBone main {
get { return head; } get { return head; }
} }
private TargetedBone[] subTargets;
#region Head #region Head
@ -313,10 +324,11 @@ namespace Passer.Humanoid {
[System.Serializable] [System.Serializable]
public class TargetedHeadBone : TargetedBone { public class TargetedHeadBone : TargetedBone {
private HeadTarget headTarget; readonly private HeadTarget headTarget;
public TargetedHeadBone(HeadTarget headTarget) : base(headTarget.humanoid) { public TargetedHeadBone(HeadTarget headTarget) : base(headTarget.humanoid) {
this.headTarget = headTarget; this.headTarget = headTarget;
this.parent = headTarget.neck;
boneId = Bone.Head; boneId = Bone.Head;
@ -404,10 +416,17 @@ namespace Passer.Humanoid {
[System.Serializable] [System.Serializable]
public class TargetedNeckBone : TargetedBone { public class TargetedNeckBone : TargetedBone {
public HeadTarget headTarget; readonly private HeadTarget headTarget;
public TargetedNeckBone(HeadTarget headTarget) : base(headTarget.humanoid) { public TargetedNeckBone(HeadTarget headTarget) : base(headTarget.humanoid) {
this.headTarget = headTarget; this.headTarget = headTarget;
if (headTarget.humanoid == null || headTarget.humanoid.hipsTarget == null)
this.parent = null;
else
this.parent = (headTarget.humanoid.hipsTarget.chest.bone.transform != null) ?
headTarget.humanoid.hipsTarget.chest :
headTarget.humanoid.hipsTarget.hips;
boneId = Bone.Neck; boneId = Bone.Neck;
bone.minAngles = minNeckAngles; bone.minAngles = minNeckAngles;
@ -853,13 +872,13 @@ namespace Passer.Humanoid {
} }
headTarget = headTargetTransform.GetComponent<HeadTarget>(); headTarget = headTargetTransform.GetComponent<HeadTarget>();
if (headTarget == null) { if (headTarget == null)
headTarget = headTargetTransform.gameObject.AddComponent<HeadTarget>(); headTarget = headTargetTransform.gameObject.AddComponent<HeadTarget>();
headTarget.Constructor(humanoid);
}
humanoid.headTarget = headTarget;
} }
if (headTarget.subTargets == null)
headTarget.Constructor(humanoid);
humanoid.headTarget = headTarget; humanoid.headTarget = headTarget;
} }

View File

@ -47,9 +47,14 @@ namespace Passer.Humanoid {
/// <param name="humanoid">The humanoid for this hips target</param> /// <param name="humanoid">The humanoid for this hips target</param>
public void Constructor(HumanoidControl humanoid) { public void Constructor(HumanoidControl humanoid) {
this.humanoid = humanoid; this.humanoid = humanoid;
chest = new TargetedChestBone(this);
spine = new TargetedSpineBone(this);
hips = new TargetedHipsBone(this); hips = new TargetedHipsBone(this);
spine = new TargetedSpineBone(this);
chest = new TargetedChestBone(this);
subTargets = new TargetedBone[] {
hips,
spine,
chest
};
} }
public bool simpleSpineIK => newSpineIK; public bool simpleSpineIK => newSpineIK;
@ -161,6 +166,7 @@ namespace Passer.Humanoid {
public override TargetedBone main { public override TargetedBone main {
get { return hips; } get { return hips; }
} }
private TargetedBone[] subTargets;
#region Chest #region Chest
@ -172,6 +178,7 @@ namespace Passer.Humanoid {
public TargetedChestBone(HipsTarget hipsTarget) : base(hipsTarget.humanoid) { public TargetedChestBone(HipsTarget hipsTarget) : base(hipsTarget.humanoid) {
this.hipsTarget = hipsTarget; this.hipsTarget = hipsTarget;
this.parent = hipsTarget.spine;
boneId = Bone.Chest; boneId = Bone.Chest;
} }
@ -226,6 +233,7 @@ namespace Passer.Humanoid {
public TargetedSpineBone(HipsTarget hipsTarget) : base(hipsTarget.humanoid) { public TargetedSpineBone(HipsTarget hipsTarget) : base(hipsTarget.humanoid) {
this.hipsTarget = hipsTarget; this.hipsTarget = hipsTarget;
this.parent = hipsTarget.hips;
boneId = Bone.Spine; boneId = Bone.Spine;
} }
@ -621,12 +629,13 @@ namespace Passer.Humanoid {
} }
hipsTarget = hipsTargetTransform.GetComponent<HipsTarget>(); hipsTarget = hipsTargetTransform.GetComponent<HipsTarget>();
if (hipsTarget == null) { if (hipsTarget == null)
hipsTarget = hipsTargetTransform.gameObject.AddComponent<HipsTarget>(); hipsTarget = hipsTargetTransform.gameObject.AddComponent<HipsTarget>();
hipsTarget.Constructor(humanoid);
}
} }
if (hipsTarget.subTargets == null)
hipsTarget.Constructor(humanoid);
humanoid.hipsTarget = hipsTarget; humanoid.hipsTarget = hipsTarget;
} }

View File

@ -421,7 +421,8 @@ namespace Passer.Humanoid {
public TargetedBone(HumanoidControl humanoid, TargetedBone _nextBone) { public TargetedBone(HumanoidControl humanoid, TargetedBone _nextBone) {
if (humanoid == null) if (humanoid == null)
throw new System.Exception("Humanoid may not be null"); throw new System.Exception("Humanoid may not be null");
nextBone = _nextBone; this.humanoid = humanoid;
this.nextBone = _nextBone;
} }
public virtual void Init() { } public virtual void Init() { }

View File

@ -31,7 +31,9 @@ namespace Passer {
#endif #endif
{ {
public bool autoStart = true; public bool autoStart = true;
#if hNW_UNET #if hNW_ROBOID
protected INetworkingStarter starter = new RoboidStarter();
#elif hNW_UNET
protected INetworkingStarter starter = new UnetStarter(); protected INetworkingStarter starter = new UnetStarter();
#elif hNW_PHOTON #elif hNW_PHOTON
protected INetworkingStarter starter = new PunStarter(); protected INetworkingStarter starter = new PunStarter();