You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

65 lines
2.1 KiB
C#

using UnityEngine;
public class BallShooter : MonoBehaviour
{
public GameObject ballPrefab;
public Transform spawnPoint;
public float arcHeight = 2f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 target;
if (Physics.Raycast(ray, out RaycastHit hit))
{
target = hit.point;
}
else
{
target = ray.GetPoint(10f); // fallback
}
if (Vector3.Distance(spawnPoint.position, target) < 0.1f)
return; // avoid NaN if click too close
GameObject ball = Instantiate(ballPrefab, spawnPoint.position, Quaternion.identity);
Rigidbody rb = ball.GetComponent<Rigidbody>();
rb.useGravity = true;
Vector3 velocity = CalculateArcVelocity(spawnPoint.position, target, arcHeight);
if (float.IsNaN(velocity.x) || float.IsNaN(velocity.y) || float.IsNaN(velocity.z))
{
Destroy(ball); // safety: don't throw broken ball
return;
}
rb.velocity = velocity;
}
}
Vector3 CalculateArcVelocity(Vector3 start, Vector3 end, float height)
{
float gravity = Mathf.Abs(Physics.gravity.y);
Vector3 displacementXZ = new Vector3(end.x - start.x, 0, end.z - start.z);
float horizontalDist = displacementXZ.magnitude;
if (horizontalDist < 0.01f) horizontalDist = 0.01f; // prevent divide-by-zero
float heightDifference = end.y - start.y;
height = Mathf.Max(height, heightDifference + 0.1f); // ensure height is enough
float timeUp = Mathf.Sqrt(2 * height / gravity);
float timeDown = Mathf.Sqrt(2 * (height - heightDifference) / gravity);
float totalTime = timeUp + timeDown;
Vector3 velocityY = Vector3.up * Mathf.Sqrt(2 * gravity * height);
Vector3 velocityXZ = displacementXZ / totalTime;
return velocityXZ + velocityY;
}
}