namespace Oculus.Platform.Samples.VrHoops
|
|
{
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
// This component handles network coordination for moving balls.
|
|
// Synchronizing moving objects that are under the influence of physics
|
|
// and other forces is somewhat of an art and this example only scratches
|
|
// the surface. Ultimately how you synchronize will depend on the requirements
|
|
// of your application and its tolerance for users seeing slightly different
|
|
// versions of the simulation.
|
|
public class P2PNetworkBall : MonoBehaviour
|
|
{
|
|
// the last time this ball locally collided with something
|
|
private float lastCollisionTime;
|
|
|
|
// cached reference to the GameObject's Rigidbody component
|
|
private Rigidbody rigidBody;
|
|
|
|
void Awake()
|
|
{
|
|
rigidBody = gameObject.GetComponent<Rigidbody>();
|
|
}
|
|
|
|
public Vector3 velocity
|
|
{
|
|
get { return rigidBody.velocity; }
|
|
}
|
|
|
|
public bool IsHeld()
|
|
{
|
|
return !rigidBody.useGravity;
|
|
}
|
|
|
|
public void ProcessRemoteUpdate(float remoteTime, bool isHeld, Vector3 pos, Vector3 vel)
|
|
{
|
|
if (isHeld)
|
|
{
|
|
transform.localPosition = pos;
|
|
}
|
|
// if we've collided since the update was sent, our state is going to be more accurate so
|
|
// it's better to ignore the update
|
|
else if (lastCollisionTime < remoteTime)
|
|
{
|
|
// To correct the position this sample directly moves the ball.
|
|
// Another approach would be to gradually lerp the ball there during
|
|
// FixedUpdate. However, that approach aggravates any errors that
|
|
// come from estimatePosition and estimateVelocity so the lerp
|
|
// should be done over few timesteps.
|
|
float deltaT = Time.realtimeSinceStartup - remoteTime;
|
|
transform.localPosition = estimatePosition(pos, vel, deltaT);
|
|
rigidBody.velocity = estimateVelocity(vel, deltaT);
|
|
|
|
// if the ball is transitioning from held to ballistic, we need to
|
|
// update the RigidBody parameters
|
|
if (IsHeld())
|
|
{
|
|
rigidBody.useGravity = true;
|
|
rigidBody.detectCollisions = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Estimates the new position assuming simple ballistic motion.
|
|
private Vector3 estimatePosition(Vector3 startPosition, Vector3 startVelocty, float time)
|
|
{
|
|
return startPosition + startVelocty * time + 0.5f * Physics.gravity * time * time;
|
|
}
|
|
|
|
// Estimates the new velocity assuming ballistic motion and drag.
|
|
private Vector3 estimateVelocity(Vector3 startVelocity, float time)
|
|
{
|
|
return startVelocity + Physics.gravity * time * Mathf.Clamp01 (1 - rigidBody.drag * time);
|
|
}
|
|
|
|
void OnCollisionEnter(Collision collision)
|
|
{
|
|
lastCollisionTime = Time.realtimeSinceStartup;
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
PlatformManager.P2P.RemoveNetworkBall(gameObject);
|
|
}
|
|
|
|
}
|
|
}
|