2024-10-17 17:23:05 +03:00

106 lines
3.5 KiB
C#

using UnityEngine;
namespace Mirror.Examples.BilliardsPredicted
{
public class WhiteBallPredicted : 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);
}
[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);
// forward the event to the local player's object.
// the ball isn't part of the local player.
NetworkClient.localPlayer.GetComponent<PlayerPredicted>().OnDraggedBall(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);
}
[ClientCallback]
void OnGUI()
{
// have a button to reply exactly the same force in every hit for easier testing.
if (GUI.Button(new Rect(10, 150, 200, 20), "Hit!"))
{
// hit with a slight angle so the red balls spread out in all directions
Vector3 force = Vector3.ClampMagnitude(new Vector3(10, 0, 600), maxForce);
NetworkClient.localPlayer.GetComponent<PlayerPredicted>().OnDraggedBall(force);
}
}
}
}