Hiya,
I’m doing the course with a different model pack and animation library. As a result I’ve made some different model and animation choices. Because the course has the Unit model with the rifle in the same position when both idle and firing, the current code doesn’t handle animation transitions + shooting very well. In my case, my idle animation has the Unit with a rifle held at waste level, on shoot it fluidly raises the rifle into aiming position and fires. Unfortunately the existing code will shoot immediately from the hip instead of when the rifle is raised and the burst fire animation occurs.
As a result of this, I ended up using Unity Animation Events. Because Animation Events need to have access to a function on the Animator I created an event bridge script that grabs the parent object UnitAnimator and then instantiate the bullet. I wanted to understand
- Is using Animation Events a “good practice” for the use case I’m describing?
- Does reaching upwards into the parent create too tight of a coupling? Should I instead just have the event bridge script fire another event that the parent object can listen for and then instantiate the bullet?
Here is my code:
UnitAnimator.cs
private void ShootAction_OnShoot(object sender, ShootAction.OnShootEventArgs e)
{
animator.SetTrigger(Shoot);
// Store the target unit's position for when the bullet is instantiated.
targetUnitShootAtPosition = e.targetUnit.GetWorldPosition();
// If the target unit has a collider, aim for the upper half of the target.
// Otherwise, just aim for the same height as the shoot point.
if (e.targetUnit.TryGetComponent<BoxCollider>(out BoxCollider boxCollider))
{
float halfHeight = boxCollider.size.y / 2f;
targetUnitShootAtPosition.y += halfHeight + Random.Range(0f, halfHeight);
}
else
{
targetUnitShootAtPosition.y = shootPointTransform.position.y;
}
}
// Called by the animation event so that the bullet is created at the correct time
public void InstantiateBullet()
{
Transform bulletProjectileTransform = Instantiate(bulletProjectilePrefab, shootPointTransform.position, Quaternion.identity);
BulletProjectile bulletProjectile = bulletProjectileTransform.GetComponent<BulletProjectile>();
bulletProjectile.Setup(targetUnitShootAtPosition);
}
AnimationEventBridge
public class AnimationEventBridge : MonoBehaviour
{
[SerializeField] private Unit parentUnit;
private void Start()
{
parentUnit = GetComponentInParent<Unit>();
}
public void AnimationEvent_FireBullet()
{
parentUnit.GetComponent<UnitAnimator>().InstantiateBullet();
}
}