Forum begins after the advertisement:


[Part 6] crawler not flipping

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 6] crawler not flipping

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #14437
    Ethan
    Participant

    ive posted the code below but the crawler will not flip rn
    using System.Collections;
    using System.Collections.Generic;
    using System.Transactions;
    using UnityEngine;

    public class Crawler : Enemy
    {
    [SerializeField] private float flipWaitTime;
    [SerializeField] private float ledgeCheckX;
    [SerializeField] private float ledgeCheckY;
    [SerializeField] private LayerMask whatIsGround;
    float timer;
    // Start is called before the first frame update
    protected override void Start()
    {
    base.Start();
    rb.gravityScale = 12.0f;
    }

    protected override void Update()
    {
    base.Update();
    if(!isRecoiling)
    {
    transform.position=Vector2.MoveTowards
    (transform.position,new Vector2(PlayerController.Instance.transform.position.x, transform.position.y),speed *Time.deltaTime);
    }
    }
    protected override void UpdateEnemyStates()
    {
    switch(currentEnemyState)
    {
    case EnemyStates.Crawler_Idle:
    Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
    Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;

    if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
    || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround))
    {
    ChangeState(EnemyStates.Crawler_Flip);
    }

    if (transform.localScale.x>0)
    {
    rb.velocity= new Vector2(speed, rb.velocity.y);
    }
    else
    {
    rb.velocity= new Vector2(-speed, rb.velocity.y);
    }
    break;

    case EnemyStates.Crawler_Flip:
    timer += Time.deltaTime;

    if(timer > flipWaitTime)
    {
    timer = 0;
    transform.localScale = new Vector2(transform.localScale.x* -1, transform.localScale.y);
    ChangeState(EnemyStates.Crawler_Idle);
    }

    break;
    }
    }
    }

    #14440
    Joseph Tang
    Moderator

    If this is the Crawler Enemy, It does not need it’s Update() Method.

        protected override void Update()
        {
            base.Update();
            if(!isRecoiling)
            {
                transform.position=Vector2.MoveTowards
                (transform.position,new Vector2(PlayerController.Instance.transform.position.x, transform.position.y),speed *Time.deltaTime);
            }
        }

    The rest of the code seems fine. Then if your Crawler looks like the Sprite is backwards, remember to set it’s spriterenderer to flip x.

    #14451
    Ethan
    Participant

    Ive added the bat and the crawler but am having some issues with the crawler not flipping and facing the player im gonna leave the code down below so i can get some help and fix the issue

    CRAWLER:
    using System.Collections;
    using System.Collections.Generic;
    using System.Transactions;
    using UnityEngine;

    public class Crawler : Enemy
    {
    [SerializeField] private float flipWaitTime;
    [SerializeField] private float ledgeCheckX;
    [SerializeField] private float ledgeCheckY;
    [SerializeField] private LayerMask whatIsGround;
    float timer;
    // Start is called before the first frame update
    protected override void Start()
    {
    base.Start();
    rb.gravityScale = 12.0f;
    }

    protected override void Update()
    {
    base.Update();
    if(!isRecoiling)
    {
    transform.position=Vector2.MoveTowards
    (transform.position,new Vector2(PlayerController.Instance.transform.position.x, transform.position.y),speed *Time.deltaTime);
    }
    }
    protected override void UpdateEnemyStates()
    {
    if(health <= 0)
    {
    Death(0.05f);
    }

    switch(GetCurrentEnemyState)
    {
    case EnemyStates.Crawler_Idle:
    Vector3 _ledgeCheckStart = transform.localScale.x > 0 ? new Vector3(ledgeCheckX, 0) : new Vector3(-ledgeCheckX, 0);
    Vector2 _wallCheckDir = transform.localScale.x > 0 ? transform.right : -transform.right;

    if (!Physics2D.Raycast(transform.position + _ledgeCheckStart, Vector2.down, ledgeCheckY, whatIsGround)
    || Physics2D.Raycast(transform.position, _wallCheckDir, ledgeCheckX, whatIsGround))
    {
    ChangeState(EnemyStates.Crawler_Flip);
    }

    if (transform.localScale.x>0)
    {
    rb.velocity= new Vector2(speed, rb.velocity.y);
    }
    else
    {
    rb.velocity= new Vector2(-speed, rb.velocity.y);
    }
    break;

    case EnemyStates.Crawler_Flip:
    timer += Time.deltaTime;

    if(timer > flipWaitTime)
    {
    timer = 0;
    transform.localScale = new Vector2(transform.localScale.x* -1, transform.localScale.y);
    ChangeState(EnemyStates.Crawler_Idle);
    }

    break;
    }
    }
    }

    ENEMY CLASS :

    using System.Collections;
    using System.Collections.Generic;
    using TMPro.EditorUtilities;
    using Unity.VisualScripting;
    using UnityEngine;

    public class Enemy : MonoBehaviour
    {
    [SerializeField] protected float health;
    [SerializeField] protected float recoilLength;
    [SerializeField] protected float recoilFactor;
    [SerializeField] protected bool isRecoiling = false;

    [SerializeField] protected float speed;

    [SerializeField] private float damage;
    [SerializeField] protected GameObject orangeBlood;

    protected float recoilTimer;
    protected Rigidbody2D rb;
    protected SpriteRenderer sr;
    protected Animator anim;

    protected bool hasTakenDamage = false;
    protected EnemyStates currentEnemyState;
    protected enum EnemyStates
    {
    //crawler
    Crawler_Idle,
    Crawler_Flip,

    //Bat
    Bat_Idle,
    Bat_Chase,
    Bat_Stunned,
    Bat_Death,
    }
    protected virtual EnemyStates GetCurrentEnemyState
    {
    get { return currentEnemyState; }
    set
    {
    if(currentEnemyState != value)
    {
    currentEnemyState = value;

    ChangeCurrentAnimation();
    }
    }
    }

    // Start is called before the first frame update
    protected virtual void Start()
    {
    rb = GetComponent<Rigidbody2D>();
    sr = GetComponent<SpriteRenderer>();
    anim= GetComponent<Animator>();
    }
    // Update is called once per frame
    protected virtual void Update()
    {
    hasTakenDamage = false;

    if(isRecoiling)
    {
    if(recoilTimer < recoilLength)
    {
    recoilTimer += Time.deltaTime;
    }
    else
    {
    isRecoiling = false;
    recoilTimer = 0;
    }
    }
    else
    {
    UpdateEnemyStates();
    }
    }
    public virtual void EnemyHit(float _damageDone, Vector2 _hitDirection, float _hitForce)
    {
    health -= _damageDone;
    if(!isRecoiling )
    {
    GameObject _orangeBlood = Instantiate(orangeBlood, transform.position,Quaternion.identity);
    Destroy(_orangeBlood, 5.5f);
    rb.AddForce(-_hitForce * recoilFactor * _hitDirection);
    }
    }
    protected void OnCollisionStay2D(Collision2D _other)
    {
    if (_other.gameObject.CompareTag(“Player”)&& !PlayerController.Instance.pState.invincible && !PlayerController.Instance.pState.invincible && health>0)
    {
    Attack();
    PlayerController.Instance.HitStopTime(0, 5, 0.5f);
    }
    }

    protected virtual void Death(float _destroyTime)
    {
    Destroy(gameObject, _destroyTime);
    }

    protected virtual void UpdateEnemyStates()
    {

    }

    protected virtual void ChangeCurrentAnimation()
    {

    }

    protected void ChangeState(EnemyStates _newState)
    {
    GetCurrentEnemyState = _newState;
    }

    protected virtual void Attack()
    {
    PlayerController.Instance.TakeDamage(damage);
    }
    }

    #14459
    Joseph Tang
    Moderator

    I’ve combined your posts together and deleted the other one.
    May i ask if the suggested removal of the Update() in Crawler.cs had any effect?

    #14463
    Ethan
    Participant

    yeah ofcourse , I removed the update code and it made it worse the crawler now doesnt chase me at all and just goes off in one direction

    #14465
    Joseph Tang
    Moderator

    Okay, so it works.

    If you check the video, the purpose of the Crawler enemy is that it does not chase the player but rather moves back and forth on the ground.

    It’s only going to move left and right and cycle through that once it detects that the edge of the ground.
    It will not chase the player but can damage the player if they collide.

    Take a look at the Bat and Charger enemy for something that will chase the player.
    The Bat will seek the player out after spotting them. The Charger will patrol the same way as the Crawler but will then speed up at the player when they spot them.

    #14466
    Ethan
    Participant

    I think there is an issue though . It doesnt really go back and fourth it just heads in one direction untill it hits a wall and then doesnt go backwards i can send a video if needed

    #14467
    Joseph Tang
    Moderator

    The most likely case is that their detection is not accurate enough, test the enemy out again but on a single platform, like a raised platform or one that is in the air.

    Normally, they should be able to detect the edges of the platform. Otherwise, It’s likely they cannot sense the end of a platform due to the box colliders of the platforms they are on being too smoothly connected.

    But yes, also send a video on their inspector and scene to show how it is functioning.

    #14468
    Ethan
    Participant

    it works now thanks to changing that code . Thanks so much for the help

Viewing 9 posts - 1 through 9 (of 9 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: