← Back to all addons

Monster Idle Movement

Posted by Mr.Titan on Jan 12, 2025 at 7:38 PM

GameplayExperimentalFeature
💡 5 🙌 1 🔥 1

Makes the AiController move around a radious from time to time. You can define: canIdle; speed; pause time; radious.

AIController.cs in attachment. Note it may contain changes that does not exist’s in yours, i don’t really remember.

Solution

Change AIController.cs:

  • Add the following parameters:

        [Header("Idle Movement Settings")]
        [SerializeField] private bool enableIdleMovement = true;
        [SerializeField, Min(0.1f)] private float idleRadius = 2.0f;
        [SerializeField, Min(0.1f)] private float idleMovementInterval = 3.0f;
        [SerializeField, Min(0.1f)] private float idleMovementSpeed = 1.0f;

        private Vector2 idleTargetPosition;
        private float idleTimer;
        private bool m_isIdleMoving = true;
  • Add method:

        private void UpdateIdleMovement()
        {
            if (!enableIdleMovement || m_target != null) return;

            idleTimer -= Time.deltaTime;

            // Pick a new random idle position within the idle radius
            if (idleTimer <= 0.0f)
            {
                idleTargetPosition = m_initialPosition + UnityEngine.Random.insideUnitCircle * idleRadius;
                idleTimer = idleMovementInterval;
            }

            // Move toward the idle target position
            Vector2 directionToIdleTarget = idleTargetPosition - (Vector2)transform.position;
            if (directionToIdleTarget.magnitude > 0.1f)
            {
                m_character.SetMovementDirection(directionToIdleTarget.normalized * idleMovementSpeed);
            }
            else
            {
                m_character.SetMovementDirection(Vector2.zero); // Stop moving when reaching the idle target
            }
        }

THE REST IN THE COMMENTS

Replace the last ìf else statement in the method FixedUpdate with the following:

// Replace all this IF and ELSE 
//if (Vector2.Distance(transform.position, m_targetPosition) > //m_soughtDistanceFromTarget)
if (m_target && Vector2.Distance(transform.position, m_targetPosition) > m_soughtDistanceFromTarget)

//else
//{ m_character.SetMovementDirection(Vector2.zero); ...}
//REPLACE TO:
else
{
    if (!m_isIdleMoving && m_character.movementDirection != Vector2.zero)
    {
        m_character.SetMovementDirection(Vector2.zero);

        if (m_character.Can(EActionFlags.Move))
        {
            m_character.SetLookAtDirection(m_targetPosition.x - transform.position.x); // Make sure the AI face its target
        }
    }
    else
    {
        if(!m_isIdleMoving) m_isIdleMoving = true;
        UpdateIdleMovement(); // Perform idle movement when no target is detected
    }
}

📜 Scripts

💬 Comments (7)

Gyvr Jan 12, 2025 at 07:43 PM
Thanks for sharing! I’m sure this will be useful for many people 🥳
JacobRiley.eth Apr 01, 2025 at 04:21 AM
Just wanted to share what worked for me in the OG core distribution file.

📜 Scripts

❤️ 1
Mr.Titan Apr 01, 2025 at 10:53 AM
Are you using 3.0? I would probably need to update this to be 3.0 complient
JacobRiley.eth Apr 01, 2025 at 02:17 PM

Indeed, using 3.0. Since this is the first version I’ve tried, I’m not entirely sure which features are part of the update versus your own customizations mentioned in the notes.

Either way, thank you 🫡

❤️ 1
Soho Apr 04, 2025 at 04:28 PM
This works in 3.0 🙂

📜 Scripts

❤️ 1
Mr.Titan Apr 04, 2025 at 05:41 PM
Hi! Can you document the changes to this file here so that everybody knows how to implement? 🤙
upvote 1
Soho Apr 05, 2025 at 03:40 AM

Updated for M2D3:

  1. Add Idle Movement Settings Added new serialized fields to configure idle movement behavior:
[Header("Idle Movement Settings")]
[SerializeField] private bool enableIdleMovement = true;
[SerializeField, Min(0.1f)] private float idleRadius = 2.0f;
[SerializeField, Min(0.1f)] private float idleMovementInterval = 3.0f;
[SerializeField, Min(0.1f)] private float idleMovementSpeed = 1.0f;
  1. Add Idle Movement Variables Add private variables to track idle movement state:
private Vector2 idleTargetPosition;
private float idleTimer;
private bool m_isIdleMoving = true;
  1. Update OnFixedUpdate Call the new UpdateIdleMovement method at the end of the OnFixedUpdate method:
UpdateIdleMovement();
  1. Implement UpdateIdleMovement Add logic to handle idle movement when no target is detected:
idleTargetPosition

private void UpdateIdleMovement()
{
    if (!enableIdleMovement || m_target != null) return;

    idleTimer -= Time.deltaTime;

    if (idleTimer <= 0.0f)
    {
        idleTargetPosition = m_initialPosition + UnityEngine.Random.insideUnitCircle * idleRadius;
        idleTimer = idleMovementInterval;
    }

    Vector2 directionToIdleTarget = idleTargetPosition - (Vector2)transform.position;
    if (directionToIdleTarget.magnitude > 0.1f)
    {
        m_subject.SetMovementDirection(directionToIdleTarget.normalized * idleMovementSpeed);
    }
    else
    {

        m_subject.SetMovementDirection(Vector2.zero);
    }
}
🔥 4

Want to continue the conversation?