Pretty sure I ended up picking a very stupid way to try to solve this, but here was my stab at it.
- Throw an object {a cupcake} over an arc, to any given destination, but it must reach that destination over a given duration.
- “My” throw code (not mine) does not account for predicting how long it will take to reach that duration.
- So my idea was to fire a sort-of tracer (empty gameObject) along the same throw arc, really really fast, before the throw itself.
- Take the duration that ‘tracer’ takes, divide it into the original throw speed, and that’s the new throw speed. Then throw. Simple enough.
Conceptually it’s kinda like this:
// let the tracer's time from starting to reaching a destination be, say, 0.037
// let intended throwTime be 0.5
float throwSpeed = 100f;
throwSpeed *= (tracerLifeTime / (throwTime);
// 100 *= (0.037 / (0.5)
// 100 *= 0.074
// throwSpeed gets adjusted to 7.4, or 13.51x slower.
// resulting throw should now take (0.037 * 13.51) sec, or ~0.5 sec
// (the total time the tracer + throw takes would be ~0.537, but that can just be adjusted)
I’ve hit a wall trying to re-configure that calculation. It only sort of works, because -
- If you aim really closeby so the tracer takes like 0.000012 sec, the throw speed becomes nearly 0.
- Even if you aim further away, properly, the throw time will always take way longer than it should. An intended 0.5 can take anywhere from 0.5 to well over a second. What the hell am I missing?
At this point, all I know is:
1(a). With that calculation, the more the initial tracer speed is reduced (to a point) (e.g. 100 → 90 → 80…), the more the throw’s actual duration matches up with its intended duration.
1(b). But vastly reducing the initial tracer’s speed makes the total time (for the tracer + throw) nowhere close to the intended throw time, which kinda defeats the whole purpose.
2. I can’t find any hiccups anywhere except with the calculation for adjusting throwSpeed.
3. This idea was terrible.
It feels like I’m missing something very fundamental here. Any assistance is appreciated (including better ideas, of course).
Here’s my messy applicable method snippets. Hopefully they makes sense. Thanks.
IEnumerator TracerAdjustsThrowSpeed(Vector3 destination)
{
if (aimingCupcake)
{
aimingCupcake = false;
tracerHasFinished = false;
tracerStartTime = Time.realtimeSinceStartup;
tracerPos.position = spawnPoint;
}
while (!tracerHasFinished)
{
float startPos_Z = spawnPoint.z;
float destinationPos_Z = destination.z;
float stepDistance_Z = destinationPos_Z - startPos_Z;
Vector3 nextStep = Vector3.MoveTowards(tracerPos.position, destination, throwSpeed * Time.deltaTime);
float arc = arcHeight * (nextStep.z - startPos_Z) * (nextStep.z - destinationPos_Z) / (-0.40f * stepDistance_Z * stepDistance_Z);
float baseY = Mathf.Lerp(spawnPoint.y, destination.y, (nextStep.z - startPos_Z) / stepDistance_Z);
Vector3 nextPos = new Vector3(nextStep.x, baseY + arc, nextStep.z);
tracerPos.position = nextPos;
if (tracerPos.position == destination) {
tracerArrivedTime = Time.realtimeSinceStartup;
var airTime = Mathf.Abs((tracerArrivedTime - tracerStartTime));
var speedMultiplier = airTime / throwTime; // ADJUST FOR TRACER TIME LATER.
throwSpeed *= Mathf.Abs(speedMultiplier);
tracerHasFinished = true;
throwTo = StartCoroutine(ThrowTo(destination));
StopCoroutine(adjustThrowSpeedWithTracer);
adjustThrowSpeedWithTracer = null;
}
yield return null;
}
yield return null;
}
IEnumerator ThrowTo(Vector3 destination)
{
while (tracerHasFinished)
{
if (adjustThrowSpeedWithTracer != null)
StopCoroutine(adjustThrowSpeedWithTracer);
if (!cupcakeThrown)
{
throwStartTime = Time.realtimeSinceStartup;
cupcakeThrown = true;
spawnedCupcake = Instantiate(cupcakePrefab, spawnPoint, Quaternion.identity);
allActiveCupcakes.Add(spawnedCupcake);
}
else if (spawnedCupcake != null)
{
float startPos_Z = spawnPoint.z;
float destinationPos_Z = destination.z;
float stepDistance_Z = destinationPos_Z - startPos_Z;
Vector3 nextStep = Vector3.MoveTowards(spawnedCupcake.transform.position, destination, throwSpeed * Time.deltaTime);
// set to use Z-axis
float arc = arcHeight * (nextStep.z - startPos_Z) * (nextStep.z - destinationPos_Z) / (-0.40f * stepDistance_Z * stepDistance_Z);
float baseY = Mathf.Lerp(spawnPoint.y, destination.y, (nextStep.z - startPos_Z) / stepDistance_Z);
Vector3 nextPos = new Vector3(nextStep.x, baseY + arc, nextStep.z);
spawnedCupcake.transform.position = nextPos;
if (spawnedCupcake.transform.position == destination) {
// tracerAndThrowCompletedTime = Time.realtimeSinceStartup;
// Debug.Log("full time for throw = " + (tracerAndThrowCompletedTime - startedTracerTime));
// throwEndTime = Time.realtimeSinceStartup;
// var animationThrowTime = Mathf.Abs(throwEndTime - throwStartTime);
// Debug.Log("animation throw time = " + animationThrowTime);
// Debug.Log("throw took " + Mathf.Round(throwEndTime - throwStartTime) + " seconds");
throwSpeed = originalThrowSpeed;
cupcakeThrown = false;
spawnedCupcake = null;
tracerCanSpawn = true;
tracerHasFinished = false;
yield break;
}
}
yield return null;
}
yield return null;
}
…