Its math part was for a full arc (ground-air-ground) trajectory, so perhaps that’s why when tested on my case (air-ground) didn’t work quite well (it a little bit went over the target)
Can anyone help? much thanks.
private void Launch()
{
// source and target positions
Vector3 pos = transform.position;
Vector3 target = _bullseye.position;
// distance between target and source
float dist = Vector3.Distance(pos, target);
// rotate the object to face the target
transform.LookAt(target);
// calculate initival velocity required to land the cube on target using the formula (9)
float Vi = Mathf.Sqrt(dist * -Physics.gravity.y / (Mathf.Sin(Mathf.Deg2Rad * _angle * 2)));
float Vy, Vz; // y,z components of the initial velocity
Vy = Vi * Mathf.Sin(Mathf.Deg2Rad * _angle);
Vz = Vi * Mathf.Cos(Mathf.Deg2Rad * _angle);
// create the velocity vector in local space
Vector3 localVelocity = new Vector3(0f, Vy, Vz);
// transform it to global vector
Vector3 globalVelocity = transform.TransformVector(localVelocity);
// launch the cube by setting its initial velocity
GetComponent<Rigidbody>().velocity = globalVelocity;
// after launch revert the switch
_targetReady = false;
}
It’s about 3 years too late, but if you are still on this problem, you might want to use a sine curve to simulate the trajectory instead. I wrote this piece of code for projectiles that I needed to hit specific targets and travel in an arc. Note that you will need to use Projectile.Spawn() to initialize the projectile prefabs.
public class Projectile : MonoBehaviour {
public float speed = 8.5f; // Speed of projectile.
public float radius = 1f; // Collision radius.
float radiusSq; // Radius squared; optimisation.
Transform target; // Who we are homing at.
Vector3 currentPosition; // Store the current position we are at.
float distanceTravelled; // Record the distance travelled.
public float arcFactor = 0.5f; // Higher number means bigger arc.
Vector3 origin; // To store where the projectile first spawned.
void OnEnable() {
// Pre-compute the value.
radiusSq = radius * radius;
origin = currentPosition = transform.position;
}
void Update() {
// If there is no target, destroy itself and end execution.
if ( !target ) {
Destroy(gameObject);
// Write your own code to spawn an explosion / splat effect.
return; // Stops executing this function.
}
// Move ourselves towards the target at every frame.
Vector3 direction = target.position - currentPosition;
currentPosition += direction.normalized * speed * Time.deltaTime;
distanceTravelled += speed * Time.deltaTime; // Record the distance we are travelling.
// Set our position to <currentPosition>, and add a height offset to it.
float totalDistance = Vector3.Distance(origin, target.position);
float heightOffset = arcFactor * totalDistance * Mathf.Sin( distanceTravelled * Mathf.PI / totalDistance );
transform.position = currentPosition + new Vector3( 0, 0, heightOffset );
// Destroy the projectile if it is close to the target.
if ( direction.sqrMagnitude < radiusSq ) {
Destroy(gameObject);
// Write your own code to spawn an explosion / splat effect.
// Write your own code to deal damage to the .
}
}
// So that other scripts can use Projectile.Spawn to spawn a projectile.
public static Projectile Spawn(GameObject prefab, Vector3 position, Quaternion rotation, Transform target) {
// Spawn a GameObject based on a prefab, and returns its Projectile component.
GameObject go = Instantiate(prefab, position, rotation);
Projectile p = go.GetComponent<Projectile>();
// Rightfully, we should throw an error here instead of fixing the error for the user.
if(!p) p = go.AddComponent<Projectile>();
// Set the projectile's target, so that it can work.
p.target = target;
return p;
}
}