Crazy Tractor's Seagull AI
Congrats! You’ve now learned the ins and outs of the basic seagull AI in Crazy Tractor. 🦢🎮 Let's quickly recap the key points before you get your hands dirty with the full code.
public class SeagullWaypointMovement : MonoBehaviour
{
[Header("Seagull Stats")]
public string poolID;
public SeagullStats activeStats;
[HideInInspector] public Waypoint currentWaypoint;
private Transform previousWaypoint;
private float fleeingRotatingSpeed, fleeingMovementSpeed;
private float acceleratedRotation;
private float chaseTime = 0;
private float randomChaseTime = 20;
private Rigidbody2D rb;
private Transform playerTransform;
private Transform currentWaypointTransform;
[System.Serializable]
public struct SeagullStats
{
public float maxVelocity;
public float movementSpeed;
public float rotateSpeed;
public bool isChasingPlayer;
}
public void OnEnable()
{
if (rb == null) { rb = GetComponent(); }
if (playerTransform == null) { playerTransform = GameManager.s_player.transform; }
fleeingRotatingSpeed = 1; fleeingMovementSpeed = 1;
randomChaseTime = Random.Range(20f, 50f);
}
void Update()
{
UpdateFleeingVariables();
UpdateWaypoint();
}
private void FixedUpdate()
{
MoveTowardsWaypoint();
RotateTowardsWaypoint();
}
private void MoveTowardsWaypoint()
{
if (rb == null) { return; }
float velocityCheck = Vector2.Dot(transform.up, rb.velocity);
if (velocityCheck > activeStats.maxVelocity) { return; }
rb.velocity = transform.up * (activeStats.movementSpeed * fleeingMovementSpeed);
}
private void RotateTowardsWaypoint()
{
if (activeStats.isChasingPlayer && GameManager.s_player != null)
{
acceleratedRotation = Vector3.Distance(transform.position, playerTransform.position) / 1.2f;
Vector2 direction = (Vector2)playerTransform.position - rb.position;
direction.Normalize();
float rotatAmount = Vector3.Cross(direction, transform.up).z;
rb.angularVelocity = -rotatAmount * ((activeStats.rotateSpeed + acceleratedRotation) * fleeingRotatingSpeed);
}
else if (!activeStats.isChasingPlayer && currentWaypoint != null)
{
acceleratedRotation = 0;
Vector2 direction = (Vector2)currentWaypoint.ReturnActiveWaypointTransform().position - rb.position;
direction.Normalize();
float rotatAmount = Vector3.Cross(direction, transform.up).z;
rb.angularVelocity = -rotatAmount * (activeStats.rotateSpeed * fleeingRotatingSpeed);
}
}
private void UpdateWaypoint()
{
if (activeStats.isChasingPlayer || currentWaypoint == null) { return; }
if (currentWaypointTransform == null || currentWaypointTransform != currentWaypoint.ReturnActiveWaypointTransform())
{
currentWaypointTransform = currentWaypoint.ReturnActiveWaypointTransform();
}
float distanceFromWaypoint = Vector3.Distance(transform.position, currentWaypointTransform.position);
if (distanceFromWaypoint >= 175) { transform.position = currentWaypointTransform.position; }
else if (distanceFromWaypoint <= 5) { currentWaypoint = currentWaypoint.ReturnNextWaypoint(); }
}
private void UpdateFleeingVariables()
{
if (BossManager.instance == null || BossManager.bossState != BossManager.BossState.Active) { return; }
activeStats.isChasingPlayer = true;
fleeingRotatingSpeed = -1.0f; fleeingMovementSpeed = 1.2f;
float distance = Vector2.Distance(transform.position, playerTransform.position);
if (distance >= 200)
{
activeStats.isChasingPlayer = false;
fleeingRotatingSpeed = 1.0f; fleeingMovementSpeed = 1.0f;
ObjectPoolManager.SendObjectToPool(poolID, gameObject);
}
}
}
You’re now ready to implement, optimize, and fine-tune the AI in your own games! Keep experimenting, and happy coding! ✨👾