jerome
jerome

Reputation: 411

How to change a parent class variable from child class in unity

I'm just starting out with Unity, and I'm making a basic 2d game using OOP principles for the characters. I've created a general enemy class called EnemyController and it has a child called BasicEnemy.

The idea is that when the enemy is spawned (between two points, which are a bed and a bar in this case), it either moves to the left or right and starts to patrol between the objects. I'm using raycasting for this, and so far when the enemy hits either of those points, I've gotten the ray to flip along with the sprite. I can't seem to get the sprite to move in the newly flipped direction.

I've tried to modify the moveSpeed variable in the parent class, and I've tried to write my own movement functions LeftMove and RightMove.

My code is below.

This is the code for the Parent class:

public class EnemyController : MonoBehaviour
{
    //transform for each of the enemies
    protected Transform enemyTransform;
    protected Vector2 startPosition;
    protected int damageValue, healthLevel;
    public int moveSpeed;
    protected int randNum;
    protected Rigidbody2D rb;

    private void Start()
    {
        enemyTransform = transform;
        startPosition = enemyTransform.position;
        rb = GetComponent<Rigidbody2D>();
        randNum = Random.Range(1,3);
        // Debug.Log(randNum);

        if(randNum == 1) {
            Debug.Log("Moves Left at the start");
        } if(randNum == 2) {
            Debug.Log("Moves Right at the start");
            Flip(); 
        }
    }
    private void FixedUpdate()
    {
        Move(); 
    }

    protected virtual void Move()
    {
        if(randNum == 1) {
            rb.velocity = new Vector2(-moveSpeed, rb.velocity.y);
        }
        if(randNum == 2) {
            rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
        }
    }

    public void Flip() {
        Vector3 enemyScale = transform.localScale;
        enemyScale.x *= -1;
        transform.localScale = enemyScale;
    }

}

This is the code for the Child class:

public class BasicEnemy : EnemyController
{
    //Origin, Direction, Range for Raycasting.
    public Transform rayOriginPoint;
    private Vector2 rayDir = new Vector2(-1,0);
    public float range;

    //GameObjects that it should hit
    GameObject bar, bed;
    EnemyController parentClass;
    private void Start()
    {
        bar = GameObject.Find("minibar");
        bed = GameObject.Find("bed");
    }

    private void Update()
    {
        RaycastHit2D hitObject = Physics2D.Raycast(rayOriginPoint.position,rayDir,range);
        Debug.DrawRay(rayOriginPoint.position,rayDir*range);

        if(hitObject == true) {
            if(hitObject.collider.name == bed.name) {
                Debug.Log(hitObject.collider.name);
                Flip();
                rayDir *= -1;
                LeftMove();
            }
            if(hitObject.collider.name == bar.name) {
                Debug.Log(hitObject.collider.name);
                Flip();
                rayDir *= -1;
                RightMove();
            }
        }
    }

    void LeftMove() {
        rb.velocity = new Vector2(-1, rb.velocity.y);
    }

    void RightMove(){
       rb.velocity = new Vector2(1, rb.velocity.y);
    }
}

Can someone please help me with this? Thanks in advance!

Upvotes: 0

Views: 1442

Answers (2)

jerome
jerome

Reputation: 411

I managed to solve this issue by overriding the parent function in the child class.

private bool facingRight;

    private void Start()
    {
        bar = GameObject.Find("minibar");
        bed = GameObject.Find("bed");

        rb = GetComponent<Rigidbody2D>();
    }

    private void Update()
    {
        RaycastHit2D hitObject = Physics2D.Raycast(rayOriginPoint.position,rayDir,range);
        Debug.DrawRay(rayOriginPoint.position,rayDir*range);

        if(hitObject == true) {
            if(hitObject.collider.name == bed.name) {
                Debug.Log(hitObject.collider.name);
                rayDir *= -1;
                facingRight = true;
                Flip();
            }
            if(hitObject.collider.name == bar.name) {
                Debug.Log(hitObject.collider.name);
                rayDir *= -1;
                facingRight = false;
                Flip();
            }
        }
    }

    protected override void Move()
    {
        // rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
        base.Move();
        if(facingRight == false) {
            rb.velocity = new Vector2(-1, rb.velocity.y);
        }
        else {
            rb.velocity = new Vector2(1,rb.velocity.y);
        }
    }

Like @Prodigle said, I had a boolean that I changed in order to flip the sprite.

Upvotes: 0

Prodigle
Prodigle

Reputation: 1797

 private void FixedUpdate()
    {
        Move(); 
    }
protected virtual void Move()
{
    if(randNum == 1) {
        rb.velocity = new Vector2(-moveSpeed, rb.velocity.y);
    }
    if(randNum == 2) {
        rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
    }
}

The above block in your base controller tells your enemy which direction to move in based on randNum.

void LeftMove() {
        rb.velocity = new Vector2(-1, rb.velocity.y);
    }

    void RightMove(){
       rb.velocity = new Vector2(1, rb.velocity.y);
    }

This block in your inherited controller flips the velocity.

Immediately after the velocity is flipped from Left/Right move, the FixedUpdate calls and calls Move which then changes velocity back to what it was in randNum

Proposed Solution: Store a bool directionRight, randomize it's value at creation,

in your fixedUpdate-Move

if(directionRight)
    rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
else
   rb.velocity = new Vector2(-moveSpeed, rb.velocity.y);

have your flip function call directionRight =!directionRight to flip direction. No longer any need for your move left/right functions

Upvotes: 1

Related Questions