aha
This commit is contained in:
107
Assets/Mirror/Examples/Billiards/Ball/WhiteBall.cs
Normal file
107
Assets/Mirror/Examples/Billiards/Ball/WhiteBall.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using Mirror;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror.Examples.Billiards
|
||||
{
|
||||
public class WhiteBall : NetworkBehaviour
|
||||
{
|
||||
public LineRenderer dragIndicator;
|
||||
public Rigidbody rigidBody;
|
||||
public float forceMultiplier = 2;
|
||||
public float maxForce = 40;
|
||||
|
||||
// remember start position to reset to after entering a pocket
|
||||
Vector3 startPosition;
|
||||
|
||||
// cast mouse position on screen to world position
|
||||
bool MouseToWorld(out Vector3 position)
|
||||
{
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
Plane plane = new Plane(Vector3.up, transform.position);
|
||||
if (plane.Raycast(ray, out float distance))
|
||||
{
|
||||
position = ray.GetPoint(distance);
|
||||
return true;
|
||||
}
|
||||
position = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
startPosition = transform.position;
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
void OnMouseDown()
|
||||
{
|
||||
// enable drag indicator
|
||||
dragIndicator.SetPosition(0, transform.position);
|
||||
dragIndicator.SetPosition(1, transform.position);
|
||||
dragIndicator.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
void OnMouseDrag()
|
||||
{
|
||||
// cast mouse position to world
|
||||
if (!MouseToWorld(out Vector3 current)) return;
|
||||
|
||||
// drag indicator
|
||||
dragIndicator.SetPosition(0, transform.position);
|
||||
dragIndicator.SetPosition(1, current);
|
||||
}
|
||||
|
||||
// all players can apply force to the white ball.
|
||||
// (this is not cheat safe)
|
||||
[Command(requiresAuthority = false)]
|
||||
void CmdApplyForce(Vector3 force)
|
||||
{
|
||||
// AddForce has different force modes, see this excellent diagram:
|
||||
// https://www.reddit.com/r/Unity3D/comments/psukm1/know_the_difference_between_forcemodes_a_little/
|
||||
// when applying a one-time force to the ball, we need 'Impulse'.
|
||||
rigidBody.AddForce(force, ForceMode.Impulse);
|
||||
}
|
||||
|
||||
[ClientCallback]
|
||||
void OnMouseUp()
|
||||
{
|
||||
// cast mouse position to world
|
||||
if (!MouseToWorld(out Vector3 current)) return;
|
||||
|
||||
// calculate delta from ball to mouse
|
||||
// ball may have moved since we started dragging,
|
||||
// so always use current ball position here.
|
||||
Vector3 from = transform.position;
|
||||
|
||||
// debug drawing: only works if Gizmos are enabled!
|
||||
Debug.DrawLine(from, current, Color.white, 2);
|
||||
|
||||
// calculate pending force delta
|
||||
Vector3 delta = from - current;
|
||||
Vector3 force = delta * forceMultiplier;
|
||||
|
||||
// there should be a maximum allowed force
|
||||
force = Vector3.ClampMagnitude(force, maxForce);
|
||||
|
||||
// apply force to rigidbody.
|
||||
// it will take a round trip to show the effect.
|
||||
// the goal for prediction will be to show it immediately.
|
||||
CmdApplyForce(force);
|
||||
|
||||
// disable drag indicator
|
||||
dragIndicator.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// reset position when entering a pocket.
|
||||
// there's only one trigger in the scene (the pocket).
|
||||
[ServerCallback]
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
rigidBody.position = startPosition;
|
||||
rigidBody.Sleep(); // reset forces
|
||||
GetComponent<NetworkRigidbodyUnreliable>().RpcTeleport(startPosition);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user